【Unity Shader學習筆記】Unity光照基礎-半蘭伯特光照
阿新 • • 發佈:2022-04-21
在光照無法達到的區域,模型的外觀通常是全黑的,沒有任何明暗變化,這會使模型的背光區域看起來就像一個平面。
使用半蘭伯特光照可以解決這個問題。
逐頂點光照技術也被稱為蘭伯特光照模型。因為它符合蘭伯特定律。
Valve公司在開發半條命的時候提出了半蘭伯特光照模型。
半蘭伯特光照模型沒有使用max操作來防止n和I的點積為負值,而是對其結果進行了一個α 倍的縮放再加上一個β 大小的偏移。
絕大多數情況下,α 和β的值均為0.5,即公式為:
對於模型的背光面,在漫反射模型中點積結果將對映到同一個值,即0值處;而在半蘭伯特模型中,背光面也可以由明暗變化,不同的點積結果會對映到不同的值上。
需要注意的是,半蘭伯特是沒有任何物理依據的,它僅僅是一個視覺加強技術。
半蘭伯特光照與逐畫素漫反射光照的程式碼很相近,只需要把計算部分稍作修改即可。
程式碼如下:
Shader "Unity Shaders Book/Chapter 6/HalfLambert" { Properties{ _Diffuse("Diffuse", Color) = (1, 1, 1, 1) } SubShader{ Pass { Tags {"LightMode" = "ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float3 worldNormal : TEXCOORD0; }; //逐頂點漫反射光照 v2f vert(a2v v) { v2f o; //Transfrom the vertex from object space to projection space o.pos = UnityObjectToClipPos(v.vertex); //Transform thhe normal from object space to world space o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject); return o; } fixed4 frag(v2f i) : SV_Target { //get ambient term fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //get the normal in world space fixed3 worldNormal = normalize(i.worldNormal); //get the light direction in world space fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); //Compute diffuse term(計算漫反射項) fixed halfLambert = dot(worldNormal, worldLightDir) * 0.5 + 0.5; fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert; fixed3 color = ambient + diffuse; return fixed4(color, 1.0); } ENDCG } } Fallback "Diffuse" }