GL_ARB_vertex_attrib_binding和索引图

时间:2015-12-26 20:07:12

标签: opengl vao

我尝试在OpenGL中渲染类似Minecraft的世界。世界被分成几个块(每个块包含N ^ 3个块),每个帧都会渲染这些块。

目前我每块使用一个VAO。我一直认为这有点奇怪,因为每个块使用相同的顶点格式 - 为什么我不能使用单个VAO,然后通过更改索引和顶点缓冲区绑定来绘制每个块?

最近我遇到了核心4.3中的 GL_ARB_vertex_attrib_binding 扩展,似乎解决了这个问题 - 现在可以分离VAO和VBO绑定。但是没有提到索引缓冲区绑定,它们仍然是VAO状态的一部分,使得扩展在索引渲染时无用。我唯一能想到的是在渲染时为每个块和顶点缓冲区绑定更改更新绑定索引缓冲区的内容,但这没什么意义。

我的问题是,我是否理解扩展功能正确?如果我这样做,是否有另一种方法可以避免每块VAO而不将每块索引缓冲区合并为一个大型IBO (因为它会不必要地使块流式传输管理复杂化)

1 个答案:

答案 0 :(得分:3)

你有......部分误解了顶点属性绑定的目的。

是的,它会在separationvertex format之间创建buffer bindings。但是,此分离仅在 API 的级别上。也就是说,你有像glVertexAttribFormat那样设置格式的函数,以及用于设置缓冲区的glBindVertexBuffer。

但所有这些功能仍然会修改VAO状态。

但是,没有必要仅因为您正在更改 VAO中的状态而更改VAO。顶点属性绑定存在的原因是因为改变顶点格式状态是昂贵的。而改变缓冲区绑定状态不是(或者至少,它不是,因为昂贵)。因此,调用glBindVertexBuffer比调用glVertexAttribFormat更便宜。

这就是为什么这个功能存在的原因:这样你就不会为了执行便宜的操作而拨打昂贵的电话。

所以你想做的事情很好;您可以绑定VAO,然后根据需要进行glBindVertexBufferglBindBuffer(GL_ELEMENT_ARRAY_BUFFER)来电。是的,这些将修改VAO中的状态,但那又如何呢?只要你不触及VAO中的顶点格式,你就可以了。

话虽如此,如果你的目标是性能,你可能不应该改变每个块的缓冲区绑定状态。将所有块(或至少大块组)放入同一缓冲区的不同区域。块组的所有索引同样应该存在于单个缓冲区中。索引应该相对于该块数据的开头,因此您应该能够使用16位GLshort索引。

当需要渲染特定块时,使用BaseVertex-based rendering选择要渲染的单个块。 base_vertex用于为索引提供偏移量。此偏移量应基于块的最大大小。

这样,要使用一组块进行渲染,可以最大限度地减少所执行的缓冲区绑定操作的数量。因此,最小化绘制调用之间的状态更改次数。