什么是延迟渲染?


54

我听说过延迟渲染,以及如何在场景中使用“渲染”灯光而不会造成很大的性能损失,但是它是什么?(从高层次上)它是如何实现的?

Answers:


55

延迟渲染的定义特征是,它实质上将场景渲染的复杂度从O(几何*灯光)更改为O(几何+灯光)。

这是通过首先使用着色器渲染场景来实现的,该着色器旨在输出基本属性,例如(至少)位置*,法线和漫反射颜色。其他属性可能包括每个像素的镜面反射值和其他材质属性。它们存储在全屏渲染目标中,统称为G缓冲区。

(*:值得注意的是,开发人员通常会选择存储深度,并使用它来重建位置,因为具有可用的深度对于许多其他效果很有用。

一旦生成了G缓冲区,就可以通过每光每像素精确地求解一次BRDF来计算屏幕上任何像素的全光照结果。换句话说,如果您有20个网格,每个网格都受20个灯光影响,则传统(“前向”)渲染将要求您重新渲染每个网格几次,以累积影响它的每个灯光的结果。在最坏的情况下,这将是每个网格每个灯光一个绘制调用,或总共400个绘制调用!对于这些绘制调用中的每一个,您都将多余地重新变换网格的顶点。还有一个很好的可能性,就是对实际上不受光影响的像素进行着色,或者在最终结果中不可见(因为它们将被场景中的其他几何图形遮挡)。所有这些都会浪费GPU资源。

与延迟渲染进行比较:您只需要渲染一次网格即可填充G缓冲区。此后,对于每个灯光,您将绘制一个边界形状,该形状代表灯光影响的程度。对于点光源,这可以是一个小球体,对于定向光源,则可以是全屏四边形,因为整个场景都会受到影响。

然后,当您为该灯光的边界体积执行像素/片段着色器时,您将从G缓冲区纹理中的适当位置读取几何属性,并使用这些值确定照明结果。仅对最终结果中可见的场景像素进行阴影处理,并且每个光源仅对其进行一次阴影处理。这表示潜在的巨大节省。

但是,它也不是没有缺点。这是一个很难扩展以处理透明几何体的范例(请参阅:深度剥离)。实际上如此困难,以至于几乎所有延迟的渲染实现都退回到场景的透明部分的正向渲染。延迟渲染还消耗大量的VRAM和帧缓冲区带宽,这导致开发人员竭尽全力将G缓冲区属性巧妙地打包和压缩为最小/最小的组件。


8

Deferred Rendering也称为Deferred Shading,是指将中间结果存储到纹理中的大量可能的渲染路径,然后稍后通过对中间数据进行采样来完成渲染方程式。

几何缓冲区是一个较早的示例,其中场景被渲染为一系列缓冲区,其中包含例如不透明几何的位置,法线和基础纹理。尚未应用照明,最终颜色未知。在随后的遍中,将渲染灯光,并对几何缓冲区进行采样。这意味着可以使用屏幕像素上可能可见的固定数量的灯光来渲染大量灯光。传统渲染会评估所有光源是否遮挡了屏幕上从未见过的表面。

存在许多变化,例如包括首先渲染光信息。

参见以获取更多信息:http : //en.wikipedia.org/wiki/Deferred_shading http://delicious.com/aancsiid/deferred-shading


-3

延迟渲染是在进行第二遍处理以遮蔽所有内容之前处理的几何对象。这很有用,因为它将复杂度更改为O(像素*光源),使您可以使用复杂的场景,而对性能的影响很小。

实现起来非常简单。第一遍至少需要渲染距离,法线和颜色。您可以添加更多纹理来进行渲染,例如镜面反射和位置渲染,但会占用内存。

渲染完这些球之后,就可以渲染一些球体,其中每个球体的中心都有一个唯一的光源,将它们加在一起,将它们全部裁剪到场景中的几何体,最后应用衰减。


我认为这不会给答案增加任何新的内容。看起来就像是Neverender回答的改写部分。
HolyBlackCat

@HolyBlackCat有几个重要的区别。首先,有一个正确的复杂度方程,其次,它更加简洁,同时仍在解释如何实际实现。
hellol11

there's the correct complexity equation真正。但是我要说的只是一个小细节。您可以建议将其作为对其他答案的修改,或者在拥有足够声誉后就此发表评论。因此,做出一个新的答案有点过头了。it's much more concise我个人认为那不是很好。答案的详细信息越有用,就越好,不是吗?
HolyBlackCat

1
@HolyBlackCat是的,是的。就我个人而言,我不只是为了回答一个简单的问题而不得不经历一堵墙。
hellol11
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.