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

时间:2016-11-13 15:05:46

标签: c++ opengl 3d glsl

让我解释一下我写的代码以及问题是如何产生的。

我制作了一个简单的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;
}

在每次渲染迭代中都会调用Draw函数。

问题在我渲染第一个模型并想要绘制另一个模型时出现。让我们说按下按钮&#39; a&#39;正在加载另一个模型(通过清除和填充上面相同的顶点和索引向量),正在调用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;
}

一切正常,我没有错误。

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

1 个答案:

答案 0 :(得分:0)

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

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