4

在我的程序中,我想绘制许多球体。首先,我为球体创建顶点、索引,然后将它们绑定到 voa/vbo/ibo。之后,我创建了 1000 个随机模型矩阵。现在我有两种方法来绘制网格。

  1. 只需通过 ModelMatrices 调用列表循环 1000 次glDrawElements。在 CPU 上计算矩阵 MVP 并像统一一样发送到着色器。
  2. 将所有矩阵绑定到额外的 VBO 并将它们像“in”变量一样发送到着色器。然后用 调用一次glDrawElementsInstanced

在测试程序中,我绘制了 1000 个球体(大约 2000 万个顶点)当我使用第一种方法时,我得到大约 27FPS,而第二种方法将性能降低到 19FPS。理论上第二种方法应该比第一种方法实现更好的性能。

这是代码。

我认为瓶颈是顶点着色器中的这种乘法(VP * ModelMatrix),因为它需要为每个(网格中的顶点)* 1000 完成。

什么可以升级,我做错了什么?

4

2 回答 2

10

实例化并不总是胜利。这是您必须分析的那种优化,看看它是否值得做。

一般来说,如果您要渲染大量实例(1000 相当多,但还不够。想想 10,000),其中包含适度数量的顶点(20,000 可能太多了。更多地查看 100-3000 或所以)。此外,您的每个实例的数据不必要地大;当您可以轻松使用向量和四元数时,您会使用矩阵。

实例化的目的是减少CPU 开销。特别是每次绘制调用的 CPU 开销和状态更改。总共有 2000 万个顶点,1000 次绘制调用和状态更改的 CPU 开销很有可能不是您最大的问题。

于 2012-10-09T14:45:22.900 回答
5

因为你有旋转不变的球体,你可以用一个简单的平移 vec3 替换你的矩阵(也许用 w = uniform scale ?)。我不确定它会改变什么,不过,你很少受 ALU 约束。但是 20M 的顶点是相当多的。

1000 draw call / frame 完全在 PC 可以处理的范围内(一般应该 < 3000 ),这解释了简单版本并不太慢的事实。

至于实例化的性能不佳,我真的不知道,但我怀疑这与你高达 20k 的顶点/网格有关。实例化是为相当小的网格设计的,所以 GPU 可能无法处理得很好。您可以尝试在关闭 Vsync 的情况下与较小的网格(200 个顶点)进行比较吗?我很好奇。

于 2012-10-09T09:46:58.163 回答