Lambert光照模型,根据光照向量与顶点发现的夹角来确定光照强度:
Shader "James/VP Shader/LightModel-Lambert" { Properties { _MainTex ("MainTex", 2D) = "white" {} } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float _LightColor0; sampler2D _MainTex; float4 _MainTex_ST; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float3 lightDir : TEXCOORD1; float3 normal : TEXCOORD2; }; v2f vert(appdata_full v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); // 从顶点位置到Light的局部向量 o.lightDir = ObjSpaceLightDir(v.vertex); o.normal = v.normal; return o; } float4 frag(v2f i) : COLOR { i.lightDir = normalize(i.lightDir); i.normal = normalize(i.normal); // 纹理采样 float4 c = tex2D(_MainTex, i.uv); // 光强度,法向和光照方向的cos值 float diffuse = max(0, dot(i.normal, i.lightDir)); // 纹理色 * 光源色 * 强度参数 c = c * _LightColor0 * diffuse; return c * 2; } ENDCG } } FallBack "Diffuse" }
Phong光照模型,根据光照向量的反射向量与视线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:
Shader "James/VP Shader/LightModel-Phong" { Properties { _MainTex ("MainTex", 2D) = "white" {} _gloss ("Gloss", Float) = 1 } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float _LightColor0; sampler2D _MainTex; float4 _MainTex_ST; float _gloss; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float3 normal : TEXCOORD1; float3 lightDir : TEXCOORD2; // 光照方向 float3 reflectLightDir : TEXCOORD3; // 光照反射方向 float3 viewDir : TEXCOORD4; // 视线方向 }; v2f vert(appdata_full v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = v.normal; // 从顶点位置到light的局部向量 o.lightDir = ObjSpaceLightDir(v.vertex); // 反射向量,注意需要使用-o.lightDir o.reflectLightDir = reflect(-o.lightDir, v.normal); // 视线,顶点到camera的局部变量 o.viewDir = ObjSpaceViewDir(v.vertex); return o; } float4 frag(v2f i) : COLOR { i.normal = normalize(i.normal); i.reflectLightDir = normalize(i.reflectLightDir); i.viewDir = normalize(i.viewDir); // 纹理采样 float4 c = tex2D(_MainTex, i.uv); // 漫射光强度 float diffuse = max(0, dot(i.normal, i.lightDir)); // 镜面光强度 float specular = max(0, dot(i.reflectLightDir, i.viewDir)); specular = pow(specular, 32) * _gloss; // 纹理色 * 光源色 * 强度参数 c = c * _LightColor0 * (diffuse + specular); return c * 2; } ENDCG } } FallBack "Diffuse" }
BinnPhong光照模型,根据光照向量和视线的半角向量,与顶点法线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:
Shader "James/VP Shader/LightModel-BinnPhong" { Properties { _MainTex ("MainTex", 2D) = "white" {} _gloss ("Gloss", Float) = 5 } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float _LightColor0; sampler2D _MainTex; float4 _MainTex_ST; float _gloss; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float3 normal : TEXCOORD1; float3 lightDir : TEXCOORD2; // 光照方向 }; v2f vert(appdata_full v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = v.normal; // 顶点->light的局部向量 o.lightDir = ObjSpaceLightDir(v.vertex); // 顶点->camera的局部向量 float3 viewDir = ObjSpaceViewDir(v.vertex); return o; } float4 frag(v2f i) : COLOR { i.lightDir = normalize(i.lightDir); i.normal = normalize(i.normal); // 半角向量,光照方向和视线的中间值 float3 halfDir = (i.lightDir + i.normal) * 0.5; // 纹理采样 float4 c = tex2D(_MainTex, i.uv); // 漫射光强度 float diffuse = max(0, dot(i.normal, i.lightDir)); // 镜面光强度 float specular = max(0, dot(i.normal, halfDir)); specular = pow(specular, 32) * _gloss; // 纹理色 * 光源色 * 强度参数 c = c * _LightColor0 * (diffuse + specular); return c * 2; } ENDCG } } FallBack "Diffuse" }
BinnPhong比Phong少计算一次反射向量,会更简洁和高效。