如何在 OpenGL 中集成间接绘制、实例化渲染和 GPU 遮挡剔除

Mar*_*ycz 5 c++ opengl rendering instance culling

我正在开发一个渲染引擎,它使用绘制间接和实例渲染来渲染场景几何体。一些对象是根据实例化的基本形状(例如立方体或球体)按程序生成的,其他对象是在整个场景中实例化和使用的网格对象。现在,实例化几何体是使用对 glDrawElementsInstanced 的单独绘制调用来绘制的(现在有效,但通常不好),并且使用对 glMultiDrawElementsIndirect 的单个调用来绘制单个对象(在统一的 VBO 中)。由于我在渲染管道中使用照明和纹理(无绑定),并且场景很复杂,总共有数十万个网格,因此我需要实现 GPU 遮挡和视锥体剔除。两者都需要它:减轻片段着色器和顶点着色器的负担。

对我来说,主要问题是找到一种合理的方法来对实例几何体执行这些 GPU 剔除操作。虽然对于仅渲染一次的对象(使用间接绘制),所有剔除内容都通过示例很好地说明了,但它们似乎都没有解决实例网格物体的剔除问题。这样做似乎没有真正的障碍,但如何以最佳方式实现这一点。

我建议如下:

  1. 对实例化和非实例化几何体仅使用一次绘制间接调用。(没有真正的理由将它们分开,因为 glMultidrawElementsIndirect 提供了实例)
  2. 将网格的实例数据保存在两个单独的缓冲区(SSBO)中。一种具有所有场景对象的所有实例数据,另一种具有可见实例的实例数据。绘制间接命令是在计算着色器中编写的(在剔除之后),并根据某种可见性索引调整了实例计数和基本实例(我在这里正确吗)?

问题是:这种实例数据的复制(复制到两个单独的缓冲区中)是否合理,或者是否有更有效的方法?