假设我有很多我想渲染的网格。我有两个选择:
- Bake将每个网格转换为VBO并使用单个绘制调用进行渲染。
- 使用glUniform进行变换和颜色,并使用许多绘制调用(但仍然是单个VBO)
假设场景在帧间变化很小,哪种方法会更好?
不止这两种选择。至少还有一条:
- …
- …
- 为变换和颜色使用属性,并使用许多绘制调用。
选项3与选项2类似,但设置属性(使用glVertexAttrib4f
等调用)通常比设置制服更快。设置制服的效率高度依赖于平台。但它们通常不会被频繁修改。它们被称为uniform是有原因的。:)
也就是说,选择1可能是您的用例中变换/颜色很少变化的最佳选择。如果您还没有这样做,您可以尝试在单独的VBO中保留修改的属性(使用GL_DYNAMIC_DRAW
),而在自己的VBO中保持不变的属性(使用GL_STATIC_DRAW
)。然后使用glBufferSubData
对动态缓冲区进行必要的更新。
现实是,没有简单的规则来预测什么会表现最好。这取决于您的数据和绘制调用的大小,数据更改的频率和大小,以及您所运行的平台。如果您想确信您正在使用最有效的解决方案,您需要实现所有这些解决方案,并开始进行基准测试。
一般来说,选项1(最小化draw调用的数量)是最好的建议。这里有几个注意事项:
当在至少一个移动设备上使用非常大的vbo时,我看到性能急剧下降(假设与opengl-es标签相关)。(来自供应商的)解释涉及内部缓冲区超过一定大小。
如果把所有的信息放在顶点属性中,会显著地增加顶点缓冲区的大小,那么你为读取冗余信息(因为每个顶点并没有真正变化)所付出的代价(可能是昂贵的内存读取)可能会抵消使用更少的绘制调用所节省的费用。
最好的建议(但也很无聊)就是测试(我知道这在手机平台上开发尤其困难,因为你的代码可能运行在许多潜在的实现上)。尽量保持您的管道/工具链足够灵活,以便您可以轻松地尝试和比较不同的选项。