1. 程式人生 > >從最簡單的SurfaceShader開始層層解剖unity的標準光照模型

從最簡單的SurfaceShader開始層層解剖unity的標準光照模型

我們新建一個Standard Surface Shader,單擊showgenerated code開啟該表面著色器被編譯成vfShader之後的程式碼。

程式碼框架如下:

每個pass裡面還帶有1~2個前處理器模組,每個必要的模組的片段程式中都進行了標準光照模型的處理,我們提取其中一個

開啟Unity安裝目錄Editor\Data\CGIncludes中的UnityPBSLighting.cginc檔案找到這兩個方法。

LightingStandard_GI()函式輸出一個UnityGI型的全域性光照引數,傳入到LightingStandard方法中。

LightingStandard()方法中計算一些引數傳入核心的UNITY_BRDF_PBS()方法中。

我們開啟UnityStandardBRDF.cginc找到BRDF3_Unity_PBS()方法

// Old school, not microfacet based Modified Normalized Blinn-Phong BRDF

// Implementation uses Lookup texture for performance

//

// * Normalized BlinnPhong in RDF form

// * Implicit Visibility term

// * No Fresnel term

//

// TODO: specular is too weak in Linear rendering mode

half4 BRDF3_Unity_PBS (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,

half3 normal, half3 viewDir,

UnityLight light, UnityIndirect gi)

{

half3 reflDir = reflect (viewDir, normal);

half nl = saturate(dot(normal, light.dir));

half nv = saturate(dot(normal, viewDir));

// Vectorize Pow4 to save instructions

half2 rlPow4AndFresnelTerm = Pow4 (half2(dot(reflDir, light.dir), 1-nv)); // use R.L instead of N.H to save couple of instructions

half rlPow4 = rlPow4AndFresnelTerm.x; // power exponent must match kHorizontalWarpExp in NHxRoughness() function in GeneratedTextures.cpp

half fresnelTerm = rlPow4AndFresnelTerm.y;

half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));

half3 color = BRDF3_Direct(diffColor, specColor, rlPow4, smoothness);

color *= light.color * nl;

color += BRDF3_Indirect(diffColor, specColor, gi, grazingTerm, fresnelTerm);

return half4(color, 1);

}

half3 BRDF3_Indirect(half3 diffColor, half3 specColor, UnityIndirect indirect, half grazingTerm, half fresnelTerm)

{

half3 c = indirect.diffuse * diffColor;

c += indirect.specular * lerp (specColor, grazingTerm, fresnelTerm);

return c;

}

這裡就是對光照模型的實現,包括菲涅耳反射(最簡單)等效果。

另外Lighting.cginc中還封裝了Lambert和BlinnPhong光照模型,自己寫vfShader的時候可以拿來用。

下面來看看Standard.Shader:

下載"Standard" Shader 並開啟,找到第一個pass的主體。

開啟UnityStandardCore.cginc檔案找到片段程式,發現也是用的該光照模型。(這是forwardbase通道,其他通道相同)