OpenGL,VAO和多个缓冲区

Lun*_*rse 23 opengl

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

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

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

目前,每当调用一个绘图调用时,我迭代所有设置的顶点流并绑定它们的顶点缓冲区,应用顶点声明,禁用未使用的顶点属性并绘制基元.

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

这是VAO的正确用法吗?

Nic*_*las 45

这是VAO的正确用法吗?

没有1.

glVertexAttribPointer 使用在GL_ARRAY_BUFFER 调用函数时绑定的缓冲区对象.所以你不能这样做:

glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
Run Code Online (Sandbox Code Playgroud)

不会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, ...);
Run Code Online (Sandbox Code Playgroud)

属性0和1将来自buffer1,属性2将来自buffer2.VAO现在可以捕获所有状态.要渲染,您只需执行以下操作:

glBindVertexArray(VAO);
glDraw*();
Run Code Online (Sandbox Code Playgroud)

简而言之,如果要在OpenGL中更改属性存储的来源,还必须更改其格式.即使格式相同,也必须glVertexAttribPointer再次拨打电话.

1:本讨论假设您没有使用新的ARB_vertex_attrib_binding.或者,正如其他人所知," 究竟Direct3D如何进行顶点属性绑定. "如果您碰巧使用提供此扩展的实现,您可以有效地执行您所说的内容,因为属性格式与缓冲区对象的存储空间.而且,折磨的逻辑glVertexAttribPointer消失了.

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