这是对 VAO 的正确使用吗?
没有1。
glVertexAttribPointer
GL_ARRAY_BUFFER
使用在调用函数时绑定到的缓冲区对象。所以你不能这样做:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
这不会使用bufferObject
; 它将使用最初调用GL_ARRAY_BUFFER
时绑定的任何内容。glVertexAttribPointer
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
再次调用。
1:本讨论假设您没有使用新的ARB_vertex_attrib_binding。或者,正如众所周知的那样,“ Direct3D 究竟如何进行顶点属性绑定。 ”如果您碰巧使用提供此扩展的实现,您可以有效地做您所说的,因为属性格式与缓冲区对象的存储。同样,折磨的逻辑glVertexAttribPointer
也消失了。
一般来说,我们在 OpenGL 世界中解决这个问题的方法是将尽可能多的东西放在同一个缓冲区对象中。如果做不到这一点,只需为每个对象使用一个 VAO。