OpenGL - 进一步加快QUADS渲染的一步

时间:2011-10-19 17:50:12

标签: performance opengl stream vbo quad

我一直在尝试一下,现在可以使用

在屏幕上渲染大约300万个GL_QUADS
glDrawArrays(GL_QUADS, 0, nVertexCount);

我还使用多个缓冲,循环通过18个顶点缓冲对象,每个顶点有100万个顶点。使用存储在堆上的压缩数据和简单计算来计算每个顶点位置。我用

ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

glUnmapBuffer(GL_ARRAY_BUFFER);

每个帧将每个顶点写入缓冲区对象。当缓冲区对象已满时,我取消映射它,调用glDrawArrays,然后绑定并映射下一个VBO以传输更多顶点数据。当所有18个被使用时,我在逻辑上绑定第一个并重新开始。

根据我的经验,使用VBO的映射几乎是使用堆数组的顶点数据的两倍。我怎么知道?因为,由于我渲染了3百万个GL_QUADS,因此帧速率明显低于30 fps。我只能用眼睛观察VBO的帧速率是两倍。

我还做了观察,在每个填充的顶点缓冲区对象上连续两次调用glDrawArrays(导致渲染两倍的四边形,但一旦流动顶点数据的努力) - 仅比渲染慢得多只有一次。因此,我认为主要的瓶颈是将顶点数据流式传输到顶点缓冲区对象(2 GHz双核处理器占用了60%!)。

现在每个顶点需要3个浮点数和2个浮点数用于纹理坐标。 (总共20个字节)。我想我可以将这个数量缩短为3 GL_SHORT加上2 GL_SHORT纹理坐标。使用转换矩阵(总共5个字节),但这只会加速4倍。 (不知怎么,sizeof(GL_SHORT)在我的系统上给出4,所以我也不确定。)

无论如何,那里有游戏,甚至已经很老了但是每帧都会在屏幕上呈现超过3百万个基元(并且它们不可避免地必须流式传输这些顶点,因为没有GPU可以保持这样很多数据)并且仍然可以获得超过100 fps的体面帧速率!

我确信,我仍然缺少这个过程中的一些重点,但我无法弄清楚它是什么。有什么建议吗?

编辑: 这些是粒子系统中的松散四边形。 (或者更确切地说,因为每个人可能最终都有不同的纹理(纹理取自单个纹理的子纹理,所以没有广泛的绑定;)))

3 个答案:

答案 0 :(得分:2)

  

我确信,我仍然缺少这个过程中的一些重点

点应该是我是否需要绘制3 MB的三角形?,而不是如何打破硬件限制?

您应该知道的限制应该是硬件。传输速率,GPU时钟和内存时钟是没有更新硬件时无法覆盖的特性。实际上,您应该尝试有效地使用当前的硬件。

据我所知,你需要在渲染时更新顶点缓冲区;所以你映射缓冲区对象,更新数据,取消映射和渲染。我想你是重复做的。在这种情况下,您必须考虑从CPU到GPU的传输速率;你能减少渲染场景所需的数据吗?也许内插关键的顶点位置?

例如,如果我需要渲染地形,我可以发送数十亿个三角形来渲染完美的地形。但我肯定只使用最重要的结果就可以达到相同的效果。使用较少的三角形而不会扭曲好结果,让我能够做得越来越多。

在1920x1080有2 MB的像素......我需要使用2 MB的三角形来绘制它?也许片段着色器会表现得更好。

有许多技术用于减少处理负载(包括CPU和GPU)和传输速率:

  • 剔除
  • 详细程度
  • 实例渲染
  • 关键帧动画
  • 骨骼动画

答案 1 :(得分:1)

实际上你可以做很多事情(或者为了获得更多的吞吐量而做的事情)。 我只是略读一些,因为这可以(并且确实)填写(或更多)书籍。

  1. 绘制三角形,而不是四边形。最终,四边形将被分割为tris(图形硬件针对三角形处理进行了优化)。
  2. 当你有大量三角形的物体时,你将尽可能使用条带和风扇(减少从3N发送到N + 2的顶点数据量)。
  3. 巧妙地缓存数据(特别是在渲染大型场景时)至关重要。如您所见,数据传输是系统的瓶颈。因此,基本上每个引擎都经过大量优化,以避免不必要的数这取决于应用程序。在这里,这也是一个可以写很多书(并且已经写过)的主题。
  4. 我可以推荐这些书籍作为主题的一个条目:

    http://www.realtimerendering.com/

    http://www.gameenginebook.com/

答案 2 :(得分:1)

  

每个顶点位置都是使用存储在堆上的压缩数据和简单计算来计算的。

也许顶点或几何着色器可以代替吗?

  

无论如何,那里有游戏,甚至已经很老了但是每帧都会在屏幕上呈现超过3百万个基元(并且它们不可避免地必须流式传输这些顶点,因为没有GPU可以保持这样很多数据)

3000000 * 20 bytes = 60 megabytes即使是较旧的GPU也很容易接触到。