一个大的OpenGL顶点缓冲区,还是很多小的缓冲区?

时间:2014-10-03 06:49:42

标签: c++ opengl

假设我有5个实体(对象),方法Render()。每个实体都需要在缓冲区中设置自己的顶点进行渲染。

以下两个选项中的哪一个更好?

  1. 使用glGenBuffer创建的一个大的预分配缓冲区,每个实体将使用(缓冲区的id作为Render方法的参数传递),将其顶点写入{{1}的缓冲区}。
  2. 每个实体都创建并使用自己的缓冲区。
  3. 如果一个大缓冲区更好,如何使用适当的着色器和所有内容正确渲染此缓冲区中的所有顶点(来自所有实体)?

2 个答案:

答案 0 :(得分:9)

只要具有一定的大小,就可以使用多个VBO。你想要避免的是有很多小的绘制调用,并且必须非常频繁地绑定不同的缓冲区。

缓冲区必须有多大才能避免过多的开销,这取决于很多因素,甚至不可能给出经验法则。发挥作用的因素包括:

  • 硬件性能特征。
  • 驾驶员效率。
  • 相对于片段数量(三角形大小)的顶点数。
  • 着色器的复杂性。

通常,保留通常在单个顶点缓冲区中同时绘制的相似/相关对象是有意义的。

将所有内容放在一个缓冲区中似乎极端,实际上可能会产生负面影响。假设你有一个很大的世界",你只能在任何给定的帧中渲染一个小子集。如果你走到极端,一个巨大的缓冲区中包含所有顶点,那么每次绘制调用都需要GPU访问该缓冲区。根据体系结构以及缓冲区的分配方式,这可能意味着:

  • 尝试将缓冲区保留在专用的GPU内存(例如VRAM)中,如果它太大,可能会出现问题。
  • 将内存映射到GPU地址空间。
  • 固定/连接内存。

如果上述任何一个需要应用于一个非常大的缓冲区,但最终只使用它的一小部分来渲染一个帧,那么这些操作就会有很大的浪费。在具有VRAM的系统中,它还可以防止其他分配(如纹理)适合VRAM。

如果使用只能访问参数给出的缓冲区子集的调用来完成渲染,例如glDrawArrays()glDrawRangeElements(),则驱动程序可能会避免使整个缓冲区GPU成为可能无障碍。但我不一定会指望这种情况发生。

答案 1 :(得分:1)

对于您拥有的每个实体,使用一个带有glGenBuffer的VBO(顶点缓冲区对象)更容易,但它并不总是最好的事情,这取决于使用情况。但是,在大多数情况下,每个实体拥有1个VBO并不是一个问题,渲染很少受到影响。

好消息位于:OpenGL Vertex Specification Best Practices