glUniform vs. single draw call performance



假设我有很多我想渲染的网格。我有两个选择:

  1. Bake将每个网格转换为VBO并使用单个绘制调用进行渲染。
  2. 使用glUniform进行变换和颜色,并使用许多绘制调用(但仍然是单个VBO)

假设场景在帧间变化很小,哪种方法会更好?

不止这两种选择。至少还有一条:

  1. 为变换和颜色使用属性,并使用许多绘制调用。

选项3与选项2类似,但设置属性(使用glVertexAttrib4f等调用)通常比设置制服更快。设置制服的效率高度依赖于平台。但它们通常不会被频繁修改。它们被称为uniform是有原因的。:)

也就是说,选择1可能是您的用例中变换/颜色很少变化的最佳选择。如果您还没有这样做,您可以尝试在单独的VBO中保留修改的属性(使用GL_DYNAMIC_DRAW),而在自己的VBO中保持不变的属性(使用GL_STATIC_DRAW)。然后使用glBufferSubData对动态缓冲区进行必要的更新。

现实是,没有简单的规则来预测什么会表现最好。这取决于您的数据和绘制调用的大小,数据更改的频率和大小,以及您所运行的平台。如果您想确信您正在使用最有效的解决方案,您需要实现所有这些解决方案,并开始进行基准测试。

一般来说,选项1(最小化draw调用的数量)是最好的建议。这里有几个注意事项:

当在至少一个移动设备上使用非常大的vbo时,我看到性能急剧下降(假设与opengl-es标签相关)。(来自供应商的)解释涉及内部缓冲区超过一定大小。

如果把所有的信息放在顶点属性中,会显著地增加顶点缓冲区的大小,那么你为读取冗余信息(因为每个顶点并没有真正变化)所付出的代价(可能是昂贵的内存读取)可能会抵消使用更少的绘制调用所节省的费用。

最好的建议(但也很无聊)就是测试(我知道这在手机平台上开发尤其困难,因为你的代码可能运行在许多潜在的实现上)。尽量保持您的管道/工具链足够灵活,以便您可以轻松地尝试和比较不同的选项。

最新更新