使用glDrawElements绘制3D网格时的奇怪行为

Strange behaviour when drawing a 3D mesh using glDrawElements

本文关键字:glDrawElements 绘制 3D 网格 使用      更新时间:2023-10-16

让我解释一下我写了什么代码以及问题是如何出现的。

我做了一个简单的OpenGL应用程序,它读取一个。obj文件并渲染它。

我读取文件并将顶点和索引数据放在两个向量中:std::vector vertices<Vertex>std::vector indices<GLuint>。Vertex是我构造的一个结构体:

struct Vertex{
    glm::vec3 Position;
    glm::vec3 Normal;
}

那么现在让我们假设我已经读取了一个。obj,并且用它的数据填充了上面的向量。之后,在渲染网格之前,使用以下代码设置缓冲区。

void Mesh::setupBuffers()
{
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    glGenBuffers(1,&EBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeof(MyVertex),&vertices[0],GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size()*sizeof(GLuint),&indices[0],GL_STATIC_DRAW);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(MyVertex),(GLvoid*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
    glEnableVertexAttribArray(1);
    glBindVertexArray(0);
}

请注意,上面的代码只被调用一次,即在我加载一个新的.obj之后。

最后渲染我使用的网格:

void Mesh::Draw()
{
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSIGNED_INT,0);
    glBindVertexArray(0);
    GLenum error =  glGetError();
    if(error) std::cout << error << std::endl;
}

绘制函数在每次渲染迭代中被调用。

当我渲染了第一个模型并想要绘制另一个模型时,出现了问题。假设通过按下按钮'a',另一个模型正在加载(通过清除和填充相同的顶点和索引向量),setupBuffer()被调用,程序进入渲染循环。这样网格就不会被绘制,我得到错误1282

我发现如果我在每个渲染迭代中调用setupBuffer(),即:

void Mesh::Draw()
{
    setupBuffers();
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSIGNED_INT,0);
    glBindVertexArray(0);
    GLenum error =  glGetError();
    if(error) std::cout << error << std::endl;
}

一切正常,没有错误。

显然这不是正确的方式来渲染,因为缓冲区正在生成在每个绘图调用虽然网格数据(aka顶点,索引)不改变。

您需要为每个网格生成不同的VAO VBO和EBO。像这样

calss Mesh{
std::vector<Vertex> vertices;
std::vector<GLuint> indices;
GLuint VAO, VBO, EBO;
}