本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。
这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。
========================================== 分割线 ==========================================
终于到了Diffuse Shading一章的最后一篇了!回忆一下,在上一篇中,一共学习了两种改善漫反射光照的方法:一种是完全根据感性认识,使用Half Lembert方法改变了光照值区间,使得物体颜色整体提亮;一种是通过一张渐变图,来控制光照值。
这两种方法都只考虑到了入射光线和反射点所在的平面法向量的夹角,但是想象实际生活中我们观察一个物体,即便是在相同的光照下观察物体的同一点,如果我们观察位置有所改变,看到的结果也会不一样。因此,这一篇中,我们将引入这一新的参数:view direction——观察点方向。
为了达到这一目的,我们使用一张二维的渐变图来代替之前的一维渐变图(因为在之前的方法中,我们仅使用一个参数就决定了该图的采样位置),使用两个参数来决定采样的真正的UV坐标:一个参数由入射光线和平面法向量计算而得,一个由观察点方向和平面法向量计算而得。
Shader "Custom/RampDiffuse" { Properties { _EmissiveColor ("Emissive Color", Color) = (1,1,1,1) _AmbientColor ("Ambient Color", Color) = (1,1,1,1) _MySliderValue ("This is a Slider", Range(0,10)) = 2.5 _RampTex ("Ramp Texture", 2D) = "white"{} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf BasicDiffuse float4 _EmissiveColor; float4 _AmbientColor; float _MySliderValue; sampler2D _RampTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { float4 c; c = pow((_EmissiveColor + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Alpha = c.a; } inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten) { float difLight = max(0, dot (s.Normal, lightDir)); float hLambert = difLight * 0.5 + 0.5; float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb; float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (ramp); col.a = s.Alpha; return col; } ENDCG } FallBack "Diffuse" }
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)这个参数将会由Unity内部提供,来得到当前摄像机的观察位置到观察点的方向向量。
float rimLight = max(0, dot (s.Normal, viewDir));
float rim_hLambert = rimLight * 0.5 + 0.5;
float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rim_hLambert)).rgb;
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { float difLight = max(0, dot (s.Normal, lightDir)); // Add this line float rimLight = max(0, dot (s.Normal, viewDir)); // Modify this line float dif_hLambert = difLight * 0.5 + 0.5; // Add this line float rim_hLambert = rimLight * 0.5 + 0.5; // Modify this line float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rim_hLambert)).rgb; float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (ramp); col.a = s.Alpha; return col; }
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { float difLight = dot (s.Normal, lightDir); float rimLight = dot (s.Normal, viewDir); float3 ramp = tex2D(_RampTex, float2(difLight, rimLight)).rgb; float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (ramp); col.a = s.Alpha; return col; }
float difLight = max (0, dot (s.Normal, lightDir));
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { float difLight = max (0, dot (s.Normal, lightDir)); float rimLight = max (0, dot (s.Normal, viewDir)); float dif_hLambert = difLight * 0.5 + 0.5; float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rimLight)).rgb; float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (ramp); col.a = s.Alpha; return col; }