US3S4L4——延迟渲染路径

延迟渲染路径

延迟渲染路径对光照的数量没有任何限制,并且所有灯光都可以采用逐像素渲染。
理论上来说,即使场景中有成百上千个实时灯光,依然可以保持比较流畅的渲染帧率。
它支持法线纹理、阴影等等效果的处理;但是它不能处理半透明物体,并且不支持真正的抗锯齿。 这些不支持的内容会自动使用前向渲染路径。

  1. 延迟渲染路径处理光照的方式

    对光照的数量没有任何限制,并且所有灯光都可以采用逐像素渲染,它不能处理半透明物体,并且不支持真正的抗锯齿

  2. 延迟渲染路径在哪里进行光照计算

    • 第一个Pass:主要判断哪些片元可见,并且将可见片元的相关信息存储到G缓冲区中(对于每个物体,该Pass只会执行一次,通常无需我们自己实现)
    • 第二个Pass:利用G缓冲区中各个片元的相关信息进行真正的相关计算,最终将颜色写入颜色缓冲区
  3. 延迟渲染路径的内置光照变量

    Unity会自动填充自定义变量 sampler2D _CameraGBufferTexture0~4​,其中存储的就是G缓冲区中的数据,我们可以通过他们获取数据来进行逻辑处理

延迟渲染路径处理光照的方式

延迟渲染的效率不依赖于场景的复杂度,而是和我们使用的屏幕空间的大小有关。
这是因为延迟渲染路径中除了使用颜色缓冲和深度缓冲外,还会利用一个叫做 G 缓存的额外缓存区,
它会存储我们关心的表面(通常是离摄像机最近的表面)的其他信息,比如表面的法线、位置、材质属性等等。
总之我们需要的信息都存储到缓冲区中,而这些缓冲区可以理解为一张张的2D图片,我们实际上是在这些图像空间中进行处理的。

延迟渲染路径在哪里进行光照计算

延迟渲染路径进行光照计算,还是在 Shader 当中的 Pass​ 渲染通道中进行计算。延迟渲染路径中主要包含两个 Pass

  • 第一个 Pass​(对于每个物体,该 Pass​ 只会执行一次,通常无需我们自己实现)

    主要判断哪些片元可见,并且将可见片元的相关信息存储到 G 缓冲区中,比如:表面法线、视角方向、漫反射系数等等数据

  • 第二个 Pass​:利用 G 缓冲区中各个片元的相关信息进行真正的相关计算,最终将颜色写入颜色缓冲区

    1
    2
    3
    4
    Pass
    {
    Tags { "LightMode" = "Deferred" }
    }

注意:在第二个 Pass​ 中计算光照时,默认情况下只能用 Unity 内置的标准(Standard)光照模型计算

延迟渲染路径的内置光照变量

常用内置光照变量

变量名 类型 描述
sampler2D _CameraGBufferTexture0​;
sampler2D _CameraGBufferTexture1​;
sampler2D _CameraGBufferTexture2​;
sampler2D _CameraGBufferTexture3​;
……
sampler2D 这些变量是自定义变量,我们一般无需实现延迟渲染路径中的第一个 Pass​,G 缓冲中的相关数据 Unity 会帮助我们存储到这些自定义变量中,我们可以直接使用他们来参与计算:
_CameraGBufferTexture0​:漫反射颜色 (RGB),遮挡 (A)。
_CameraGBufferTexture1​:镜面反射颜色 (RGB),粗糙度 (A)
_CameraGBufferTexture2​:世界空间法线 (RGB),未使用 (A)。
_CameraGBufferTexture3​:发射 + 光照 + 光照贴图 + 反射探针缓冲区
_CameraGBufferTexture4​:光照遮挡值 (RGBA)
……
​_LightColor​ float4 光源颜色(#include "UnityDeferredLibrary.cginc"​)
_LightMatrix0 float4x4 世界空间到光源空间的变换矩阵(#include "UnityDeferredLibrary.cginc"​)

为了更好的使用上述的自定义变量,需要先引用 UnityGBuffer.cginc

1
#include “UnityGBuffer.cginc”

假设我们声明了三个自定义的 G 缓冲贴图变量

1
2
3
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;

在第一个 Pass​ 后(无需自己声明),这些 G 缓冲贴图变量就会自动被 Unity 存储 G 缓冲相关数据,
我们便可以在第二个 Pass​ 内对这些数据进行采样,然后将采样数据传入到 UnityStandardDataFromGbuffer​,
最终就会得到 UnityStandardData​,通过这些数据即可进行光照计算

1
2
3
4
half4 gbuffer0 = tex2D(_CameraGBufferTexture0, uv);
half4 gbuffer1 = tex2D(_CameraGBufferTexture1, uv);
half4 gbuffer2 = tex2D(_CameraGBufferTexture2, uv);
UnityStandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);