【发布时间】:2014-06-13 05:51:47
【问题描述】:
我正在寻找一种同时渲染多个网格的方法,这样我就不必为每个网格发出绘制调用。我在这里处理的是 2D 渲染,一个典型的对象,比如一个正方形,里面可能只有两个三角形。但是,一个对象也可能非常复杂,有数千个三角形。
现在每个对象都可以自行移动。从概念上讲,为每个“对象”设置一个 VBO(或 VBO/IBO 对)是完全合理的:只要对象不发生变化,我每帧必须上传到 GPU 的只是变换信息:一个位置向量和一个方向值。或者,等效地,一个变换矩阵。
但这种方法的问题在于,对于 1000 个方形对象的场景,我需要初始化 1000 个 VBO 和 1000 个 IBO,并且为了渲染 2000 个三角形,需要进行 1000 个绘制调用,每帧设置 1000 套制服。
好的。如果所有这些对象都相同,我可以有一个 VBO/IBO 来描述它们,设置一个统一缓冲区对象(或者统一数组更合适——我仍然需要学习如何使用这些)和转换数据它们中的每一个,并发出一个实例化绘制调用,让顶点着色器通过使用它接收到的实例编号从 UBO 中提取转换数据。伟大的。
我只想更进一步。我想做相当于在不相同的网格上实例化的事情:我有 1000 个不同的对象,我很高兴在 1000 个单独的顶点/索引缓冲区对或一对巨大的顶点/索引缓冲区中描述它们。我想一次性将他们的转换数据发送到 GPU。只需让驱动程序/GPU 绑定或选择正确的顶点即可。
这可以吗?可以在不使用 SM4 几何着色器的情况下完成吗?
更新:我只是想到了一种可能的方法来实现这一点。我使用顶点属性作为我的“实例化”值,用它来索引包含转换的 UBO。这是这样做的方法吗?
【问题讨论】:
-
这有点过早优化的味道。是什么让你认为你需要这样做,你不能只是以正常方式渲染这些“1000 个对象”?
-
我可能不需要它。但我有兴趣学习如何以最好的方式使用这项技术来实现我的目的。我希望能够拥有非常多的对象,如果我可以通过一次调用将它们全部绘制出来,我将获得的不仅仅是避免函数调用开销的好处,我还可以获得视口剔除,而且我确信还有其他一些事情,免费。
-
这如何给您视口剔除?实例化不会剔除任何东西;它不能。事实上,实例化的全部意义在于减少 CPU 开销,因此您尝试尽可能少地对每个实例进行处理。即使是快速的截锥体剔除也应该避免。
-
你说得对。我想我的意思是天真的方法可以让我手动剔除,这实际上是一个优点而不是缺点。不知道为什么我在那里提到它。好的——每个对象都有一个顶点缓冲区(对)肯定有很大的好处。这样,如果我删除了一个对象,我就可以删除它的缓冲区,而无需更多的内务处理。所以,我现在正在寻找的是一种无需显式调用即可发出缓冲区绑定命令的方法。不可能?
-
这并不能解释为什么您认为以正常方式绘制“1000 个对象”将是一个重大的性能问题。你试过了吗?是瓶颈吗?这些物体到底有多大?您尝试过哪些渲染方式?
标签: opengl geometry vertex-buffer geometry-instancing