前向渲染路径、延迟渲染路径和顶点照明渲染路径
前向渲染需要渲染该对象的渲染图元,并计算两个缓冲区的信息:一个是颜色缓冲区、一个是深度缓冲区。用深度缓冲来决定片元是否可见,如果可见更新颜色缓冲区的颜色值。
三种处理光照的方式:逐顶点处理、逐像素处理、球谐函数处理。 使用哪种处理模式取决于光源的类型和渲染模式。 其中渲染模式指该光源是否重要(important)。
在场景中存在大量的实时光源的时候,前向渲染会执行多个Pass,再将这些结果混合起来得到最终的光照。 而延迟渲染是使用额外的缓冲区(G缓冲:G-buffer),其中存储了我们关心的表面信息。 延迟渲染包含两个Pass,一个不进行任何光照的计算,仅仅计算那些片元可见,第二个Pass进行真正的光照计算。
1.平行光 2.点光源 3.聚光灯 4.面光源
在我们计算点光源的光照的时候 1.将Pass的Tags的LightMode设置为ForwardAdd,我们要使用Blend开启和设置混合模式,因为我们不希望Pass覆盖掉之前的光照结果,还需要使用#pragma multi_compile_fwdadd指令,此指令保证我们在Shader中使用光照衰减等光照变量可以被正确的赋值。
Tags{ "LightMode" = "ForwardAdd" }
Blend One One
CGPROGRAM
// Apparently need to add this declaration
#pragma multi_compile_fwdadd
2.在计算光源方向的时候,如果是平行光,直接使用_WorldSpaceLightPos0.xyz得到光源位置,如果是点光源或者聚光灯,我们使用_WorldSpaceLightPos0.xyz减去世界空间下的顶点位置。
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
3.最后我们计算不同光源的衰减 这里Unity使用一张纹理表作为查找表,以在片元着色器中得到光源的衰减。
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
#if defined (POINT)
float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#elif defined (SPOT)
float4 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1));
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif