处理 OpenGL VBO 中的死对象

Posted

技术标签:

【中文标题】处理 OpenGL VBO 中的死对象【英文标题】:Dealing with dead objects in OpenGL VBOs 【发布时间】:2012-11-12 18:36:17 【问题描述】:

想象一个典型的游戏,其中在模拟世界中创建和销毁对象。创建这些对象时,它们的顶点数据存储在 VBO 中。此 VBO 每帧渲染一次。

是否有处理死对象的最佳实践? IE。当对象被销毁从而不再需要渲染时,其对应的 VBO 数据应该如何处理?

您似乎想“释放”该内存以供其他对象将来使用。否则,您的 VBO 最终将几乎完全被无效数据填充。

我有一个可能的想法来实现这一点:一个 VBO 内存映射,其中单个字节被标记为空闲或正在使用。 (此映射将作为普通数组存在于 CPU 上,而不是 GPU 上。)创建对象时,我们将其数据缓冲到由映射确定的空闲区域。我们将该区域标记为地图上使用的区域。然后当对象被销毁时,我们将同一区域标记为空闲。我想如果你很懒,你可以将地图存储为布尔数组,或者如果你想做对的话,可以将它打包为每个 VBO 字节的一个地图位。

到目前为止,这听起来是不是最好的方法?有没有我没有看到的更常见的方法?

我知道很多这些问题都取决于您正在渲染的场景的特征,所以这里是上下文。我的场景由数百个对象组成。每个对象大约有八个顶点。每个顶点都有一个存储为浮点数的位置和纹理坐标。所以,我们正在研究大约:

4 bytes per float * 6 floats per vert * 8 verts per object * 500 objects
= 96,000 bytes of vertex data

【问题讨论】:

你的问题是碎片化还是你根本不删除vbo的? @Viktor:创建 VBO 非常昂贵。如果您有大量短暂的对象(例如玩家发射的子弹),那么拥有一个始终是“子弹列表”的长寿命 VBO 并更新帧之间的坐标是有效的方法,即使对象的数量也是如此可能会有所不同。 @Viktor:碎片化,有点像。更准确地说,问题是死对象堆积的顶点数据。只有一个 VBO,因此我无法删除它。为了性能,将所有对象放在一个 VBO 中是有意义的。为每个 192 字节对象设置一个单独的 VBO 不是最理想的。 "我的场景由数百个对象组成。每个对象大约有八个顶点。" 那么... Minecraft。 边界框精灵,实际上:) 【参考方案1】:

听起来您正在考虑使用池分配器。在这些方面已经完成了很多现有工作,这些工作也应该很好地适用于 VBO 内的分配。

如果所有元素的大小相同,这将非常简单。否则,您需要担心碎片,但堆管理器是众所周知的。

我将提供的最简单的改进是从最后一个填充的插槽开始扫描空闲插槽,而不是总是从头开始。

您可以使用deque 样式的数据结构来存储空闲位置列表,从而以空间换取速度,从而无需扫描空闲位置。

存储在 VBO 中的数据大小确实对管理器没有影响。只有可以单独重新利用的插槽数。

【讨论】:

是的!关于碎片化的重要观点。幸运的是,我的对象几乎都一样大。

以上是关于处理 OpenGL VBO 中的死对象的主要内容,如果未能解决你的问题,请参考以下文章

游戏环境中的 OpenGL VBO/DisplayList

OpenGL - 绘制存储在 VBO 中的大量信息

OpenGL 使用单个 VBO 渲染多个对象,并使用另一个 VBO 更新对象的矩阵

如何将元素映射到 OpenGL VBO 中的颜色?

将两个不同的网格放在同一个顶点 VBO 中的 OpenGL 最佳实践

iOS OpenGL ES 2.0 VBO 混淆