【问题标题】:Fastest way to draw many textured quads in OpenGL 3+在 OpenGL 3+ 中绘制许多纹理四边形的最快方法
【发布时间】:2012-09-23 20:38:19
【问题描述】:

由于 GL_QUADS 已从 OpenGL 3.1 及更高版本中删除,不使用它来绘制大量四边形的最快方法是什么?我尝试了几种不同的方法(如下),并在我的机器上对它们进行了速度排名,但我想知道是否有更好的方法,因为最快的方法仍然看起来既浪费又不优雅。我应该提到,在每种方法中,我都使用具有交错顶点和纹理坐标的 VBO,因为我认为这是最佳实践(尽管我可能错了)。另外,我应该说我不能在单独的四边形之间重用任何顶点,因为它们会有不同的纹理坐标。

  1. glDrawElements 和 GL_TRIANGLE_STRIP 使用原始重启索引,因此索引数组看起来像 {0, 1, 2, 3, PRI, 4, 5, 6, 7, PRI, ...}。这会在我的 VBO 中获取前 4 个顶点,将它们视为三角形条以形成一个矩形,然后将接下来的 4 个顶点视为单独的条。这里的问题只是索引数组看起来很浪费空间。在早期版本的 OpenGL 中,GL_QUADS 的好处是它每 4 个顶点自动重新启动图元。不过,这是我能找到的最快的方法。

  2. 几何着色器。我为每个矩形传入 1 个顶点,然后在着色器中构造适当的 4 个顶点的三角形条带。这似乎是最快和最优雅的,但我已经阅读并且现在看到,与传递冗余数据相比,几何着色器效率不高。

  3. 带有 GL_TRIANGLES 的 glDrawArrays。我只是独立绘制每个三角形,不重用顶点。

  4. glMultiDrawArrays 与 GL_TRIANGLE_STRIP,“第一个”数组的所有 4 倍数的数组,以及“计数”数组的一组 4 的数组。这告诉视频卡从 0 开始绘制前 4 个,然后从 4 开始绘制前 4 个,依此类推。我认为这很慢的原因是您不能将这些索引数组放在 VBO 中。

【问题讨论】:

  • 我不确定这里是否有明确的答案,性能可能很容易因一个 gpu 到另一个甚至一个驱动程序而不同。
  • 1.不,2. 几何着色器不打算单独使用,当输出保存到缓冲区并重复使用时,它们的性能最好,3. 可能,4. 可能,5. VBO。快速的图形通常不是最优雅的,但差异可能足以弥补它。
  • 什么是 5?我已经在尽我所能使用 VBO。

标签: opengl


【解决方案1】:

您已经介绍了所有典型的好方法,但我想推荐一些不太典型的方法,我怀疑它们可能具有更高的性能。根据问题的措辞,我假设您正在尝试绘制一个 m*n 瓷砖数组,它们都需要不同的纹理坐标。

  • 几何着色器不是添加和删除顶点的正确工具。它能够做到这一点,但它确实适用于您实际更改动态渲染的图元数量的情况(例如阴影体积生成)。如果您只想绘制一大堆具有不同纹理坐标的相邻不同图元,我怀疑绝对最快的方法是使用曲面细分着色器。只需传入一个四边形并让曲面细分器按程序计算纹理坐标。
  • 一种类似且更便携的方法是查找每个四边形的纹理坐标。这很简单:假设您正在绘制 50x20 的四边形,您将拥有一个 50x20 的纹理来存储所有纹理坐标。在您的顶点程序中点击此纹理(或者在您的几何程序中可能更有效)并将结果以可变的形式发送到片段程序以进行实际渲染。

请注意,在上述两种情况下,您都可以重用顶点。在第一种方法中,中间顶点是动态生成的。其次,顶点的纹理坐标在着色器中被替换为纹理中的缓存值。

【讨论】:

  • 但是如果四边形不相邻,镶嵌着色器会起作用吗?
  • 不,据我所知不会。随着您越来越优化,所需的工作变得更加复杂。但是,您应该问自己是否需要这些优化。首先使用 any 方法让代码正常工作是最值得的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
相关资源
最近更新 更多