较大的顶点缓冲区与多个绘制调用


14

我刚刚开始使用OpenGL,并且尝试使用它来创建2D游戏。在这个游戏中,我有一个六角形网格,由许多不同颜色的六角形组成。作为新手OpenGL程序员,我看到了绘制此网格的两种方法:

  1. 将顶点缓冲区与单个六边形的数据一起使用,然后使用统一的偏移值并在CPU上迭代多次以绘制同一程序,直到获得网格为止。
  2. 创建一个单一的非常大的预先计算的顶点缓冲区,该缓冲区在一次调用中绘制所有六边形。

什么是最有效的方法?有更好的方法吗?


您预先计算出的顶点缓冲区只需要延伸一个屏幕六边形即可,然后可以通过平滑滚动直到变成完整的六边形然后“扭曲”回去来伪造它,对于这种情况下的颜色,您可以保留一个GPU上的2D纹理,在顶点着色器中读取,然后将其平面插值到片段着色器中。
MickLH 2013年

通过通常是指一种渲染操作依赖于先前操作的结果的情况。您在此问题中要问的实际上与减少一次通过中的绘制调用次数有关。我知道这听起来有些古怪,但是了解差异非常重要,否则多遍算法就没有多大意义;)
Andon M. Coleman 2013年

@ AndonM.Coleman Hmm,谢谢,我显然不熟悉图形术语。那么,在这种情况下,我将如何形容呢?多个着色器/程序调用?
亚历克西斯·金

您可以立即看出这是单遍算法,因为没有顺序依赖性。您可以按任何顺序绘制这些六边形,但仍可获得相同的结果。您可能需要进行多次绘制调用才能为OpenGL提供渲染它们所需的数据,但是OpenGL实际上可以自由地并行绘制它们,因为没有依赖关系。如果是多次通过,则六边形B可能需要六边形A的结果才能被绘制,或者您可能需要多次绘制相同的六边形并合并结果。
安东·科尔曼

Answers:


9

确实有几种方法可以制成这样的网格。

最有效的方法是实例化。这样,您在VBO中只制作一次六角形,并将其渲染一百,一千或一百万次。您可以使用第1点中所述的带有均匀着色器的着色器来手动完成此操作,但是还具有内置的OpenGL功能。为此,请看一下glDrawElementsInstanced

请注意,如果您绘制的实例对象数量超过一定数量,则实例化仅比其他方法更快。例如,使用1个大VBO可以更快地绘制图形300,但是如果您使用实例渲染,则可以绘制200万个图形。

如果使用实例渲染,则可以使用Attribute Divisors发送每个对象的数据。您需要发送位置和颜色。

关于实例化渲染的很好的教程:单击

实际上,最好的方法是尝试这两种方法,并检查绘制1帧所需的毫秒数。这样,您还可以同时学习两种方法,这总是很好。

另请注意,实例渲染是OpenGL的一种现代功能,您必须使用着色器才能使用它。但是始终最好从一开始就学习正确的方法。


2
实例化不一定是最有效的。在我见过的许多实现中,实例化支持是为了保持一致性而实现的,但比单独绘制许多对象要慢(实际上,驱动程序在执行此操作时可能执行不佳)。这是一个选择,也是一个不错的选择,但是在做出关于“最有效”的任何假设之前,应谨慎配置和测试目标OS /硬件。
肖恩·米德迪奇

同意 例如,我在Windows / Linux和Ati / nVidia上看到了不同的性能。感谢您的添加。
巴萨2014年

1
事实上。如果在单个vbo中绘制多个组合的网格(共享相同的空间)。实例化不可能更快。实例化的问题是:顶点不是并行计算的交叉实例。它仅消除了gpu / cpu / gpu sync / drawcall。因此,绘制一个包含1000个球体的顶点缓冲区比用硬件实例化绘制1000个球体更快。(不涉及平截头剔除/对象距离细节优化)
Jeroen van Langen

3

方法1的编码更简单,并且只要您一次视图中没有太多的六角形就可以了。由于您是OpenGL的新手,因此您可能要坚持这一点,以避免同时增加过多的复杂性。

如果一次查看大量的六边形(例如几百或上千个),则必须使用开销较小的方法来避免进行这么多单独绘制的CPU开销。方法2可以为此使用实例化,甚至更好。我希望实例化比方法2更快,或者肯定不会更差,因为对于所有实例,您只需要更新每个实例数据的缓冲区,而不是顶点数据的(大得多)缓冲区即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.