使用glDrawElements绘制3D网格时的奇怪行为
问题描述:
因此,让我解释一下我写的代码以及问题是如何出现的。使用glDrawElements绘制3D网格时的奇怪行为
我做了一个简单的OpenGL应用程序,它读取.obj文件并呈现它。
我读取文件并将顶点和索引数据放在两个矢量中:std::vector vertices<Vertex>
和std::vector indices<GLuint>
。顶点是一个结构我构建了:
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;
}
一切工作正常,我没有错误。
显然这不是正确的渲染方式,因为虽然网格数据(又名顶点,索引)不会改变,但在每次绘图调用中都会生成缓冲区。
答
您需要为每个网格生成不同的VAO VBO和EBO。 类似这样的东西
calss Mesh{
std::vector<Vertex> vertices;
std::vector<GLuint> indices;
GLuint VAO, VBO, EBO;
}
感谢您的回复!我已经这样做了,实际上我的Mesh类有这些数据成员。每次加载新模型时,都会创建一个新的Mesh对象,其中包含您提到的数据成员。 –