opengl - VAO 绘制错误的索引缓冲区
问题描述
我正在尝试使用(相同的)基本着色器程序绘制多个对象。这些对象具有顶点缓冲区,我打算通过调用 glDrawElements 使用关联的索引缓冲区进行绘制。我为每个对象设置了一个 VAO,并认为我已将索引缓冲区和顶点缓冲区与 VAO 相关联,但是当我绘制第二个(以及任何其他对象)时,它们是使用错误的顶点绘制的。
这是我设置 VBO 和 EBO 的(伪)代码:
glGenBuffers(1, &vboCube);
glBindBuffer(GL_ARRAY_BUFFER, vboCube);
glBufferData(GL_ARRAY_BUFFER, getNumSphereVertices() * sizeof(Vertex), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &iboCube);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboCube);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, getNumCubeIndices() * sizeof(uint32), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(1, &vboSphere);
glBindBuffer(GL_ARRAY_BUFFER, vboSphere);
glBufferData(GL_ARRAY_BUFFER, getNumSphereVertices() * sizeof(Vertex), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &iboSphere);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboSphere);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, getNumSphereIndices() * sizeof(uint32), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
编辑:这些已更新为使用 DSA 等效项,问题仍然存在。DSA 代码如下:
glCreateBuffers(1, &vboCube);
glBindBuffer(GL_ARRAY_BUFFER, vboCube);
glNamedBufferData(vboCube, getNumCubeVertices() * sizeof(Vertex), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
接下来链接我的程序属性:
glUseProgram(programID);
uint32 vaoCube;
glCreateVertexArrays(1, &vaoCube);
glBindVertexArray(vaoCube);
i = 0
for each attribute:
uint32 attribIndex = glGetAttribLocation(program, name.c_str());
glVertexArrayVertexBuffer(vaoCube, i, vboCube, 0, stride);
glEnableVertexArrayAttrib(vaoCube, attribIndex);
glVertexArrayAttribFormat(vaoCube, attribIndex, numCells, dataType, normalise, offset);
glVertexArrayAttribBinding(vaoCube, attribIndex, i);
glVertexArrayBindingDivisor(vaoCube, i, divisor);
i++
glBindVertexArray(0);
glBindVertexArray(vaoCube);
glVertexArrayElementBuffer(vaoCube, iboCube);
glBindVertexArray(0);
uint32 vaoSphere;
glCreateVertexArrays(1, &vaoSphere);
glBindVertexArray(vaoSphere);
i = 0
for each attribute:
uint32 attribIndex = glGetAttribLocation(program, name.c_str());
glVertexArrayVertexBuffer(vaoSphere, i, vboSphere, 0, stride);
glEnableVertexArrayAttrib(vaoSphere, attribIndex);
glVertexArrayAttribFormat(vaoSphere, attribIndex, numCells, dataType, normalise, offset);
glVertexArrayAttribBinding(vaoSphere, attribIndex, i);
glVertexArrayBindingDivisor(vaoSphere, i, divisor);
i++
glBindVertexArray(0);
glBindVertexArray(vaoSphere);
glVertexArrayElementBuffer(vaoSphere, iboSphere);
glBindVertexArray(0);
最后绘制对象:
glBindVertexArray(vaoCube);
glDrawElements(GL_TRIANGLES, getNumCubeIndices(), GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
glBindVertexArray(vaoSphere);
glDrawElements(GL_TRIANGLES, getNumSphereIndices(), GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
最终结果:
VAO 设置是否不正确?
解决方案
如果您使用的是 ARB_direct_state_access/OpenGL 4.5,则应该始终如一地完全这样做。因此,“用于设置 VBO 和 EBO 的我的(伪)代码:”中的所有内容都是错误的。你应该使用glCreateBuffer
,glNamedBufferData
等等。
这很重要,因为 whileGL_ARRAY_BUFFER
是上下文状态GL_ELEMENT_ARRAY_BUFFER
的一部分,也是 VAO 状态的一部分。如果您使用的是核心 OpenGL 并且没有绑定 VAO……这意味着没有元素数组缓冲区状态。因此,您的glBindBuffer
呼叫应该出错了,并且您随后尝试使用它们的尝试同样会失败。