就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果你觉得这个问题可以改进并可能重新打开,visit the help center 寻求指导。




8年前关闭。




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

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

  • 我应该使用多少个 vbo?
  • 我应该如何创建 vbos?
  • 如果数据大小不固定,我应该如何更新 vbos 数据?
  • 我应该如何渲染 vbos?
  • 我应该如何处理我不想再渲染的 vbos 中的数据?
  • 最佳答案



    尽可能少。切换 VBO 的成本虽小,但可衡量。通常,您会尝试将类似的数据分组到 VBO 中。例如在 FPS 游戏中,大街上的各种垃圾、小 Prop 等,通常会位于同一个或仅少数几个 VBO 中。

    它还归结为绘制批量大小。 glDraw… 渲染少于大约 100 个基元的调用是次优的(即使在 15 年前也是如此)。因此,您希望尽可能批处理至少 100 个基元。但是,如果单个网格只有,比如说 20 个三角形(用于实例化的低多边形 Prop 等),每个都在它自己的 VBO 中,你不能再批量处理了。



    glGenBuffers → glBindBuffer → glBufferData

    UPDATE 你可以向 glBufferData 的 data 参数传递一个空指针来初始化缓冲区对象,而无需设置数据。



    创建具有比数据大小更粗粒度的 VBO。您的操作系统无论如何都会为您的主机端数据执行此操作,这称为分页。此外,如果您想使用 glMapBuffer 使缓冲区对象成为主机页面大小的倍数,这对整个系统来说非常好。

    当前系统上通常的页面大小是 4kiB。这就是我选择的 VBO 大小粒度。更新:顺便说一句,您可以询问您的操作系统正在使用哪种页面大小。虽然这取决于操作系统,但我会问另一个问题。

    使用 glBufferSubData 更新数据或在主机端映射内存中使用 glMapBuffer 修改映射它,然后使用 glUnmapBuffer。

    如果数据超过缓冲区对象,则创建一个新的更大的对象并使用 glCopyBufferSubData 进行复制。见最后一段。



    glBindBuffer → glDraw...



    如果数据仅消耗 VBO 的一部分并与其他数据共享,并且您没有耗尽内存,那么,不要访问它。理想情况下,您保留一些索引,您可以在其中跟踪哪个 VBO 的哪些部分可用于哪种任务。这非常像内存管理,特别是一种称为对象堆栈(obstacks)的方案。

    然而,最终压缩现有的缓冲区对象可能是有意义的。为此,您将创建一个新的缓冲区对象,将其绑定(bind)为写入目标,并选择旧的缓冲区对象作为读取目标。然后使用 glCopyBufferSubData 将内容复制到一个新的、收紧的缓冲区对象中。当然,您随后必须更新对缓冲区对象名称(=OpenGL ID)和偏移量的所有引用。

    出于这个原因,在 OpenGL 缓冲区对象之上编写一个薄的抽象层是有意义的,它跟踪 OpenGL 缓冲区对象所在的无结构 blob 中的实际类型数据。

    关于opengl - 使用 VBO 的最佳方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15923075/

    10-12 19:42