OpenGL,VAO和多个缓冲区

时间:2013-01-10 01:51:33

标签: opengl

我正在使用OpenGL编写一个小图形引擎(通过带有C#的OpenTK)。

要定义顶点属性,我有一个VertexDeclaration类,其中包含一个VertexElement结构数组,这些结构映射到glEnableVertexAttribArray / glVertexAttribPointer调用。

另外,为了支持多个顶点流,我有一个特殊的结构,包含顶点缓冲区,顶点声明,顶点偏移和实例频率(如XNA的VertexBufferBinding结构)。

目前,无论何时调用绘图调用,我都会迭代所有设置的顶点流和 绑定它们的顶点缓冲区,应用顶点声明,禁用未使用的顶点属性并绘制基元。

我想使用VAO将glEnableVertexAttribArray调用缓存到它们中, 每当应用顶点流时,绑定VAO并更改其数组缓冲区绑定。

这是否正确使用了VAO?

1 个答案:

答案 0 :(得分:42)

  

这是否正确使用了VAO?

没有 1

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;当最初调用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 。或者,正如其他人所知,“Exactly how Direct3D does vertex attribute binding.”如果您碰巧使用提供此扩展的实现,您可以有效地执行您所说的内容,因为属性格式与缓冲区对象无关存储。此外,glVertexAttribPointer的折磨逻辑已经消失。

通常,我们在OpenGL世界中解决这个问题的方法是在同一个缓冲区对象中放置尽可能多的东西。如果做不到这一点,只需为每个对象使用一个VAO。