在讲光照模型之前,我们先回顾一下上篇Shader山下(一)第一个Shader的代码:
Shader "Custom/BasicDiffuse" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque"}
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
其中这一句:
#pragma surface surf Lambert
我们修改这一句,改为:
#pragma surface surf BasicDiffuse
inline fixed4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed difLight = max(0, dot (s.Normal, lightDir));
fixed4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
col.a = s.Alpha;
return col;
}
如果你把这个shader用在场景中的物体上,你不会发现与之前的shader有任何变化。因为这其实就是Lambert模型。
第一个参数s与surf里的参数类型一致,实际上就是在surf方法处理完之后,传递给LightingBasicDiffuse的。
第二个参数lightDir表示光照向量。
第三个参数atten表示光衰减系数。
第一行将像素的法线向量与光照向量进行点积操作。操作返回[-1,1]的值,表示两个向量之间的夹角关系,1表示二者同向平行,-1表示二者反向平行,0表示二者垂直。然后如果点积值值小于0,则取0,赋值给difLight。我们知道,当二者平行的时候,也就意味着光照向量与该像素垂直,也就是该点可以接收到最多的光照。
第二行声明了一个颜色变量col。
第三行用s的色彩值与光照颜色_LightColor0(从Unity场景中获取的)相乘(rgb三个分量分别相乘),最后再乘以difLight和atten并乘以2(参考)。
第四行将s的Alpha值赋值给color的a。
第五行返回col。
就是根据像素点的法线方向与光照方向将光照颜色与像素颜色进行混合。
理解这个最简单的光照模型之后,我们可以考虑自己修改。例如,我们在Properties里面添加:
_LightRate ("Light Rate", Range(0,1)) = 0.5
并在SubShader的CGPROGRAM后面ENDCG之前添加:
fixed _LightRate;
inline fixed4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed difLight = max(0, dot (s.Normal, lightDir));
difLight = difLight * (1 - _LightRate) + _LightRate;
fixed4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
col.a = s.Alpha;
return col;
}
接着我们还可以实现一些更有意思的光照模型。
在Properties里面添加:
_StartColor("Start Color", Color) = (1,0,0,1)
_EndColor("End Color", Color) = (0,1,1,1)
在SubShader的CGPROGRAM后面ENDCG之前添加:
fixed4 _StartColor;
fixed4 _EndColor;
inline fixed4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed difLight = max(0, dot (s.Normal, lightDir));
difLight = difLight * (1 - _LightRate) + _LightRate;
fixed3 ramp = lerp(_StartColor, _EndColor, difLight).rgb;
fixed4 col;
col.rgb = s.Albedo * _LightColor0.rgb * ramp;
col.a = s.Alpha;
return col;
}
调整Light Rate和颜色,你还可能得到这样一个Cube:
如果换成Sphere,你会发现,这其实是渐变色: