这是VAO的正确用法吗?
否。
glVertexAttribPointer
uses the buffer object that was bound to GL_ARRAY_BUFFER
at the moment the function was called。所以,你不能做到这一点:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
这将不使用bufferObject
;当最初调用glVertexAttribPointer
时,它将使用与GL_ARRAY_BUFFER
绑定的任何内容。
VAO捕获此状态。因此,VAO将针对每个顶点属性存储被调用时绑定到GL_ARRAY_BUFFER
的任何缓冲区对象。这允许你做这样的事情:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
属性0和1将来自buffer1
和属性2将来自buffer2
。 VAO现在可以捕获所有状态。要渲染,你只是这样做:
glBindVertexArray(VAO);
glDraw*();
总之,如果你想要更改属性的存储来自于OpenGL,则还必须更改它的格式。即使格式相同,您也必须再次拨打glVertexAttribPointer
。
:此讨论假定您使用新ARB_vertex_attrib_binding是不。或者,正如其他人所知,“Exactly how Direct3D does vertex attribute binding.”如果您恰好使用提供此扩展的实现,则可以有效地执行您正在讨论的内容,因为属性格式不与缓冲对象的存储绑定。另外,glVertexAttribPointer
的折磨逻辑消失了。
一般来说,我们在OpenGL世界中解决这个问题的方法是将尽可能多的东西放在同一个缓冲区对象中。如果不这样做,只需为每个对象使用一个VAO。
感谢这个伟大的答案。那么'glBufferData'步骤在哪里起作用?在使用'glVertexAttribPointer'之前,你不必先缓冲数据吗?对不起,我对OpenGL很陌生 –