在OpenGL 3+中绘制多个纹理四边形的最快方法

15
自从OpenGL 3.1及以上版本中移除了GL_QUADS,没有使用它的情况下绘制大量矩形的最快方法是什么?我尝试了几种不同的方法(如下),并在我的机器上对它们的速度进行了排名,但我想知道是否有更好的方法,因为最快的方法似乎仍然是浪费和不优雅的。需要注意的是,在每种方法中,我都使用具有交错顶点和纹理坐标的VBO,因为我认为这是最佳实践(虽然我可能是错误的)。此外,我还要说一句,不能在不同的矩形之间重用任何顶点,因为它们将具有不同的纹理坐标。
  1. 使用具有原始重启索引的GL_TRIANGLE_STRIP的glDrawElements,使索引数组看起来像{0, 1, 2, 3, PRI, 4, 5, 6, 7, PRI, ...}。这会从我的VBO中取出前4个顶点,将它们视为三角形条形以制作矩形,然后将接下来的4个顶点视为单独的条带。问题在于索引数组似乎是一个空间浪费。GL_QUADS在早期的OpenGL版本中的好处是它会自动在每4个顶点之间重启原语。尽管如此,这仍然是我能找到的最快方法。
  2. 几何着色器。我为每个矩形传入1个顶点,然后在着色器中构建适当的由4个顶点组成的三角形带。这似乎是最快和最优雅的方法,但我已经阅读并现在看到,与传递冗余数据相比,几何着色器的效率不高。
  3. 使用GL_TRIANGLES的glDrawArrays。我只是独立地绘制每个三角形,不重用任何顶点。
  4. 使用具有GL_TRIANGLE_STRIP的glMultiDrawArrays,"first"数组的所有倍数为4,并且"count"数组的许多元素为4。这告诉显卡从0开始绘制第一个4,然后从4开始绘制第一个4,依此类推。我认为这样缓慢的原因是无法在VBO中放置这些索引数组。

1
我不确定这里是否有明确的答案,性能可能因GPU或驱动程序的不同而有所不同。 - Tim
  1. 不是。
  2. 几何着色器并不适合单独使用,最好将输出保存到缓冲区并重复使用。
  3. 或许。
  4. 可能。
  5. VBOs。在图形处理中,快速通常不是最优雅的,但差异可能足以弥补它。
- ssube
什么是5?我已经尽可能地使用VBO。 - noumenon28
1个回答

5
您已经涵盖了所有典型的好方法,但我想建议几个不太典型的方法,我认为它们可能有更高的性能。根据问题的措辞,我假设您正在尝试绘制一个 m * n 的图块数组,并且它们都需要不同的纹理坐标。
  • 几何着色器不是添加和删除顶点的正确工具。虽然它能够完成这个任务,但它真正适用于在动态地改变要渲染的基元数量时使用(例如阴影体积生成)。如果您只想绘制一堆相邻的不同基元,并带有不同的纹理坐标,那么我认为最快的方法是使用镶嵌着色器。只需传入单个四边形,让镶嵌器以过程方式计算纹理坐标。
  • 一种类似且更具可移植性的方法是查找每个四边形的纹理坐标。这很简单:假设您正在绘制 50x20 个四边形,您将拥有一个 50x20 的纹理,其中存储了所有纹理坐标。在您的顶点程序中(或者可能更有效地在您的几何程序中)调用此纹理,并将结果发送到变量程序以进行实际渲染。

请注意,在上述两种情况下,您可以重复使用顶点。在第一种方法中,中间顶点是即时生成的。在第二种方法中,顶点的纹理坐标在着色器中被缓存值替换。


如果四边形不相邻,镶嵌着色器是否能够工作? - noumenon28
1
据我所知,不会。随着优化的进行,所需的工作变得更加复杂。但是,你应该问自己是否真的需要这些优化。首先用任何方法让代码正常运行最为重要。 - geometrian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接