使用VBO的最佳方式

时间:2013-04-10 10:17:37

标签: opengl vbo

使用维管组织的最快和最灵活(适用于大多数情况)的方法是什么?

我正在开发一个openGL应用程序,我希望它能达到最佳性能,所以我需要有人来回答这些问题。我读了很多问题和答案,但我想有很多我不需要的信息弄乱了我的大脑......

  • 我应该使用多少个vbos?
  • 我应该如何创建vbos?
  • 如果数据大小未修复,我应该如何更新vbos数据?
  • 我该如何渲染vbos?
  • 我应该如何处理我不想再渲染的vbos中的数据?

2 个答案:

答案 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特有的。