之前的Shader中,使用的Lambert光照模型
#pragma surface surf Lambert
這是一個很經(jīng)典的漫反射模型,光強與入射光的方向和反射點處表面法向夾角的余弦成正比。簡單解釋就是一個點的反射光強是和該點的法線向量和入射光向量和強度和夾角有關(guān)系的,其結(jié)果就是這兩個向量的點積。
代碼
Shader "Demo/Diffuse Lighting"{
Properties{
_MainTex("MainTex", 2D) = ""{}
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD 200
CGPROGRAM
#pragma surface surf CustomDiffuse
sampler2D _MainTex;
struct Input{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o) {
float4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
inline float4 LightingCustomDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten) {
float dl = max(0, dot(s.Normal, lightDir));
float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (dl * atten * 2);
col.a = s.Alpha;
return col;
}
ENDCG
}
FallBack "Diffuse"
}
#pragma surface surf CustomDiffuse
#pragma語句在這里聲明了接下來的Shader的類型,計算調(diào)用的方法名,以及指定光照模型。之前我們一直指定Lambert為光照模型,而現(xiàn)在我們將其換為了CustomDiffuse(對應下面的LightingCustomDiffuse方法)
Shader中對于方法的名稱有著比較嚴格的約定,想要創(chuàng)建一個光照模型,首先要做的是按照規(guī)則聲明一個光照計算的函數(shù)名字,即Lighting+方法名。對于我們的光照模型CustomDiffuse,其函數(shù)的名稱就是LightingCustomDiffuse。
之前使用的Lambert光照模型,來自Unity的內(nèi)建Shader,在Lighting.cginc文件中包含了LightingLambert的實現(xiàn)。
inline float4 LightingCustomDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten) {
float dl = max(0, dot(s.Normal, lightDir));
float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (dl * atten * 2);
col.a = s.Alpha;
return col;
}
SurfaceOutput s 是函數(shù)surf處理后的輸出,我們講對其上的點根據(jù)光線進行處理,fixed3 lightDir 是光線的方向,fixed atten 表示光衰減的系數(shù)。在計算光照的代碼中,我們先將輸入的s的法線值和輸入光線進行點積(dot函數(shù)是CG中內(nèi)置的數(shù)學函數(shù))。點積的結(jié)果在-1至1之間,這個值越大表示法線與光線間夾角越小,這個點也就應該越亮。之后使用max來將這個系數(shù)結(jié)果限制在0到1之間,是為了避免負數(shù)情況的存在而導致最終計算的顏色變?yōu)樨摂?shù),輸出一團黑。接下來我們將surf輸出的顏色與場景光線的顏色_LightColor0.rgb(由Unity根據(jù)場景中的光源得到的,在Lighting.cginc中有聲明)進行乘積,然后再與剛才計算的光強系數(shù)和輸入的衰減系數(shù)相乘,最后得到在這個光線下的顏色輸出。
與使用Lamber光照模型的貼圖效果一樣,這里就不再展示效果圖了。