使用维管组织的最快和最灵活(适用于大多数情况)的方法是什么?
我正在开发一个openGL应用程序,我希望它能达到最佳性能,所以我需要有人来回答这些问题。我读了很多问题和答案,但我想有很多我不需要的信息弄乱了我的大脑......
答案 0 :(得分:18)
- 我应该使用多少个vbos?
尽可能少。切换VBO需要很小但可测量的成本。通常,您会尝试将类似的数据分组到VBO中。例如,在FPS游戏中,街道上所有不同种类的垃圾,小道具等通常会位于相同或仅少量的VBO中。
它还归结为绘制批量大小。 glDraw…
调用少于约100个原语的调用是次优的(即使是15年前也是如此)。所以你想在可能的情况下批量至少100个原语。但是,如果单个网格只有20个三角形(用于实例化的低多元数道具等),则每个网格都在自己的VBO中,你不能再批量更多。
- 我应该如何创建vbos?
glGenBuffers→glBindBuffer→glBufferData
UPDATE 您可以将空指针传递给glBufferData的data
参数,以初始化缓冲区对象而无需设置数据。
- 如果数据大小未修复,我应该如何更新vbos数据?
使用比数据大小更粗的粒度创建VBO。无论如何,您的操作系统正在为您的主机端数据执行此操作,它称为分页。此外,如果你想使用 glMapBuffer 使缓冲区对象成为主机页面大小的倍数对整个系统来说非常好。
当前系统的常用页面大小为4kiB。这就是我选择的VBO大小粒度。 更新:您可以BTW询问您的操作系统正在使用的页面大小。那是OS依赖的,我会问另一个问题。
使用glBufferSubData更新数据,或者在主机端映射内存中使用glMapBuffer modify映射,然后使用glUnmapBuffer。
如果数据超出缓冲区对象,则创建一个新的,更大的数据并使用glCopyBufferSubData进行复制。参见lase段。
- 我该如何渲染vbos?
glBindBuffer→glDraw ...
- 我应该如何处理我不想再渲染的vbos中的数据?
如果数据只消耗VBO的一部分并与其他数据共享,那么你的内存不足,那么,就是不要访问它。理想情况下,您可以保留一些索引,在该索引中,您可以跟踪哪个VBO具有哪些部分可用于执行何种任务。这非常类似于内存管理,特别是称为对象堆栈(obstacks)的方案。
但是最终可能会使现有缓冲区对象变得紧凑。为此,您将创建一个新的缓冲区对象,将其绑定为写入目标,并选择旧的缓冲区对象作为读取目标。然后使用glCopyBufferSubData将内容复制到一个新的,收紧的缓冲区对象中。当然,您必须更新对缓冲区对象名称(= OpenGL ID)和偏移的所有引用。
因此,在OpenGL缓冲区对象之上编写一个精简抽象层是有意义的,它可以跟踪无结构blob OpenGL缓冲区对象中的实际类型化数据。
答案 1 :(得分:-2)
我应该使用多少个vbo?
根据你的需要,听起来很傻但是那样,
如果数据大小未修复,我该如何更新vbos数据?
覆盖并渲染具有不同数据和长度的相同VBO。
我应该如何创建vbos?
我该如何呈现vbos?
请参阅VBO tutorial
我应该如何处理我不想再渲染的vbos中的数据?
创建一个新的vbo并将数据复制到其中或仅渲染内存中的那部分vbo。
仅渲染部分请参阅glVertexBuffer glTexCoordPointer(只根据偏移量计算新指针和新尺寸)
修改1:
使用单个VBO可以解决所有问题,因为你必须自己管理新的顶点位置/纹理坐标的分配,这真的很快就会变得非常混乱。
最好将小道具分组到VBO中并批量绘制命令。
我可以使用glBufferSubData将数据添加到缓冲区(将100个元素添加到大小为x的缓冲区中)吗?
不,这是不可能的,因为描述说明updates a subset of a buffer object's data store
,而子集是集合中较小的集合。
修改2
一个好的教程也是Learning Modern 3D Graphics Programming,但它不是VBO特有的。