前向渲染&延迟渲染

前向渲染&延迟渲染


读书是在别人思想的帮助下,建立起自己的思想。 ——鲁巴金

在unity中,渲染路径决定了光照是如何应用到Unity Shader中的。我们只有为Shader正确的选择和设置需要的渲染路径,该Shader的光照计算才能被正确的执行。

LightMode标签设置

Unity Shader 中, Pass 的LightMode标签支持的渲染路径设置选项:

Always : 不管使用哪种渲染路径, 该 Pass 总是会被渲染, 但不会计算任何光照。
ForwardBase:用于前向渲染。该Pass会计算环境光、最重要的平行光、逐顶点/SH光源和Lightmaps。
ForwardAdd: 用于前向渲染。该Pass会计算额外的逐像素光源。每个 Pass 对应一个光源。
Deferred:用于延迟渲染。该Pass会渲染G缓冲(G-buffer)。
ShadowCaster: 把物体的深度信息渲染到阴影映射纹理(shadowmap)或一张深度纹理中。
PrepassBase: 用于遗留的延迟渲染。该 Pass 会渲染发现和高光反射的指数部分。
PrepassFinal: 用于遗留的延迟渲染。该Pass通过合并纹理、光照和自发光来渲染得到最后的颜色。
Vertex、VertexLMRGBM 和 VertexLM : 用于遗留的顶点照明渲染。
前向渲染(Forward Rendering)。

核心思想:每进行一次完整的前向渲染,我们需要渲染该对象的渲染图元,并计算两个缓冲区的信息:一个是颜色缓冲区,一个是深度缓冲区。我们通过深度缓冲区判断一个片元是否是可见的,如果可见的话就更新颜色缓冲区中的颜色值。

  • 无效计算— 前向渲染对一个几何体进行一系列的计算,对于多个物体,一个几何体处理完之后才会进行下一个几何体的处理。所以我们就可以发现问题:有太多的无效渲染。
  • 计算量— 同时,如果光照特别多,每个几何体都要对这些光照计算一遍的话计算量非常大。针对这些缺点,后来也有一系列的解决方式,如Early-z 、Z-Prepass 、 Hi-Z 等剔除方法。
  • 透明处理— 可以处理处理半透明物体。

前向渲染路径中有三种处理关照的方式:

逐顶点处理、逐像素处理、球谐函数(Spherical Harmonics, SH)处理。而决定一个灯光是哪种处理模式取决于它的类型和模式:

  • 场景中最亮的平行光总是按照逐像素处理的。
  • 渲染模式被设置成Not Important的光源,会按逐顶点或者SH处理。
  • 渲染模式被设置成Important的光源,会按逐像素处理。
  • 如果逐像素光源数量小于Quality Setting中的逐像素光照数量,会有更多的光源按照逐像素的方式渲染。

内置的光照变量和函数:

在UnityShaderVariables.cginc文件中,我们可以找到Unity提供的和处理光照有关的变量:

CBUFFER_START(UnityLighting)

        #ifdef USING_DIRECTIONAL_LIGHT
        uniform fixed4 _WorldSpaceLightPos0;
        #else
        uniform float4 _WorldSpaceLightPos0;
        #endif

        uniform float4 _LightPositionRange; // xyz = pos, w = 1/range

        // Built-in uniforms for "vertex lights"
        float4 unity_4LightPosX0;        // x coordinates of the 4 light sources in world space
        float4 unity_4LightPosY0;        // y coordinates of the 4 light sources in world space
        float4 unity_4LightPosZ0;        // z coordinates of the 4 light sources in world space
        float4 unity_4LightAtten0;        // scale factors for attenuation with squared distance

        float4 unity_LightColor[8];        // array of the colors of the 4 light sources
        float4 unity_LightPosition[8];        // apparently is not always correctly set
        // x = -1
        // y = 1
        // z = quadratic attenuation
        // w = range^2
        float4 unity_LightAtten[8];        // apparently is not always correctly set
        float4 unity_SpotDirection[8];

        // SH lighting environment
        float4 unity_SHAr;
        float4 unity_SHAg;
        float4 unity_SHAb;
        float4 unity_SHBr;
        float4 unity_SHBg;
        float4 unity_SHBb;
        float4 unity_SHC;
CBUFFER_END

在UnityCG.cginc可以找到光照处理辅助函数:

// Computes world space light direction
inline float3 WorldSpaceLightDir( in float4 v );

// Computes object space light direction
inline float3 ObjSpaceLightDir( in float4 v );

// Computes world space view direction
inline float3 WorldSpaceViewDir( in float4 v );

// Computes object space view direction
inline float3 ObjSpaceViewDir( in float4 v );

float3 Shade4PointLights (
float4 lightPosX, float4 lightPosY, float4 lightPosZ,
float3 lightColor0, float3 lightColor1, float3 lightColor2, float3 lightColor3,
float4 lightAttenSq,
float3 pos, float3 normal);

float3 ShadeVertexLights (float4 vertex, float3 normal);

// normal should be normalized, w=1.0
half3 ShadeSH9 (half4 normal);

延迟渲染(Deferred Rendering)

较于前向渲染,延迟渲染不同的是先进行可见性判断,接着进行光照计算。延迟渲染除了颜色缓冲区、深度缓冲区,还使用了G缓冲区(G-buffer),在这里面存储着我们需要的信息,并会根据这里面的信息进行光照计算。也就是说,先确定渲染到屏幕上的像素,再用像素去做光照。

  • 有效计算 — 当场景中所有几何体都写入G-Buffer之后,==不管场景中有多少物体、多少三角形,光照计算都已经和它们没有关系了!!!==所以,只渲染可见的像素,不会有无效的计算。
  • 显卡要求 — 所以,延迟渲染很适合场景中光源数目比较多的情况,而且每个光源都可以按逐像素的方式进行处理。但是,这也就说明了延迟渲染对显卡的要求比较高。
  • ==抗锯齿 ==— 因为延迟渲染相当于是render to texture,如果使用MSAA的话,会消耗大量的带宽。所以延迟渲染无法使用多重采样抗锯齿(MSAA)。
  • 透明处理 —不能处理半透明物体。多个半透明对象可以覆盖同一个屏幕像素,而G-Buffer中每个像素只可以存储一个值。在光照Pass中,深度值,表面法线,diffuse颜色和高光色被当前的屏幕像素所采样来进行光照,因为每个G-Buffer只能采样一个值,透明物体不能光照pass中被支持。延迟渲染的时候,一般都是先渲染非透明的Mesh,后续再单独渲染透明Mesh。
  • 模型使用同一个光照Pass — 当mesh渲染到Gbuffer之后,我们已经不知道哪个像素点属于哪个mesh了,只能使用同一套光照计算。

因为文章开头的那句话,在阅读时更加注重自己的思考,文中有错误之处,烦请大家批评指正!不胜感激!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值