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

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

  • 使用一个由glGenBuffer创建的预先分配的大缓冲区,每个实体将通过使用Render将其顶点写入缓冲区来使用每个缓冲区(作为glBufferSubData方法的参数传递的缓冲区的ID)。
  • 每个实体都创建并使用其自己的缓冲区。

  • 如果一个大缓冲区更好,那么如何使用适当的着色器和所有内容正确渲染该缓冲区中的所有顶点(来自所有实体)?

    最佳答案

    只要具有一定的大小,拥有多个VBO就可以了。您要避免的是进行许多小的绘制调用,并且必须非常频繁地绑定(bind)不同的缓冲区。

    为了避免过多的开销,必须有多大的缓冲区取决于许多因素,甚至连经验法则也几乎是不可能的。影响因素包括:

  • 硬件性能特征。
  • 驱动程序效率。
  • 相对于片段数的顶点数(三角形大小)。
  • 着色器的复杂性。

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

    将所有内容放在一个缓冲区中似乎是极端的,实际上可能会产生不利影响。假设您有一个大的“世界”,在该世界中,您只在任何给定帧中渲染一小部分。如果极端,将所有顶点都放在一个巨型缓冲区中,则每次绘制调用都需要GPU可以访问该缓冲区。根据体系结构以及缓冲区的分配方式,这可能意味着:
  • 尝试将缓冲区保留在专用的GPU内存(例如VRAM)中,如果内存太大,可能会出现问题。
  • 将内存映射到GPU地址空间。
  • 固定/连接内存。

  • 如果需要将以上任何内容应用于非常大的缓冲区,但是最终只使用其中的一小部分来渲染帧,则在这些操作中会浪费很多时间。在具有VRAM的系统中,它还可能阻止其他分配(例如纹理)适合VRAM。

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

    关于c++ - 一个大的OpenGL顶点缓冲区,还是许多个小的顶点缓冲区?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26174436/

    10-16 05:15