延迟渲染与预片段着色器深度剔除

Deferred Rendering vs pre fragment shader Depth Culling

据称延迟渲染的优势在于它允许片段着色器仅执行 numLights * numPixels 次。这是因为在前向渲染中,很多时候同一个像素被渲染了两次。但是,如果在片段着色器之前和几何着色器之后执行深度剔除或 z 剔除,这将使其与延迟渲染一样高效,并且不需要大型 G-Buffer。我相信在较新版本的 OpenGL 中可以做到这一点,那么为什么没有人这样做呢?如果我的想法有错误,请告诉我。

注意:也许这不是一个恰当的问题,但我不知道还有什么地方可以post这个。

However, what if depth culling or z-culling was performed before the fragment shader and after the geometry shader, this would cause it to be as efficent as defered rendering

不,不会。

您仍将为每个光执行一次所有顶点处理阶段,因为标准正向渲染需要为每个光绘制每个模型。在延迟渲染中,每个模型只绘制一次,因此节省了顶点处理时间。

这很重要,因为许多现代硬件都使用所谓的 "unified shader architecture"。这意味着硬件能够动态分配着色器工作负载。如果渲染大量顶点,但使用短片段着色器,则它可以将更多着色器单元分配给 VS 阶段。如果您使用简单的 VS 渲染 4 个顶点,但使用复杂的 FS,那么它可以将很少的硬件分配给顶点阶段,而将更多的硬件分配给片段着色器。

因此在延迟渲染中,您将花费更多的可用着色器处理器时间来执行有用的工作。通过前向渲染,您将 GPU 的资源分配给有用的 FS 工作和重复且无用的 VS 工作。

接下来,您可能会建议使用变换反馈来捕获渲染结果并重新渲染它们。但现在你只是用一个瓶颈换取另一个瓶颈:你占用更多内存,你用 VS 工作换取内存带宽。


I perform a draw call only once so there are no redundant geomitries, and I instead loop through all of the lights in the fragment shader using an array of lights as a uniform.

这只是用一种低效率换取另一种低效率,尽管这通常更快(但灵活性较低)。您不必多次渲染每个网格,而是 运行 对不一定可见的片段进行非常耗时的 FS 调用。

Early depth tests 不作任何保证。硬件不可能保证执行的每个 FS 调用都是可见的,因为 GPU 可能还没有光栅化遮挡对象。早期的深度测试无法确定绘制内容的顺序。

保证所有 FS 调用可见的唯一方法是执行深度预传递。也就是说,您渲染场景中的所有内容,但没有片段着色器。所以唯一得到更新的是深度。然后,您使用实际着色器再次渲染场景。

但是,您要渲染整个场景两次。着色器负载平衡可能要困难得多,因为要剔除整个对象。

您必须认识到的另一件事是延迟渲染并不能保证性能。它只是另一种渲染方法,有其自身的优点和缺点。您可以创建延迟渲染比正向渲染的任何变体都慢的情况。您还可以创建延迟渲染速度更快的环境。虽然随着灯光数量的增加,延迟渲染通常是最好的选择,但总有一些情况可以使另一种渲染技术在性能上更优越。