properties
{
_Diffuse("my Diffuse",Color)=(1,0,0,1) //漫反射颜色
}
Subshader
{
Tags{"LightMode"="ForwardBase" }
pass
{
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 color : COLOR; //与float2 uv:TEXCOORD0似
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(mul(v.normal, (float3x3)_World2Object));
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));
o.color = ambient + diffuse;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return fixed4(i.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
【说明】
1. LightMode
LightMode是个非常重要的选项,因为它将决定该pass中光源的各变量的值。如果一个pass没有指定任何LightMode tag,那 么我们就会得到上一个对象残留下来的光照值,这并不是我们想要的。其他各个LightMode的具体含义可以参见官网(很重要,一定要去看,特别是对于每个Pass的细节解释,一定要点进去看!!!),这里做一个简单的解释。
LightMode=Vertex:会设置4个光源,并按亮度从明到暗进行排序,它们的值会存储在unity_LightColor[n], unity_LightPosition[n], unity_LightAtten[n]这些数组中。因此,[0]总会得到最亮的光源。
LightMode=ForwardBase: _LightColor0将会是主要的directional light的颜色。
LightMode=ForwardAdd:和上面一样, _LightColor0将是该逐像素光源的颜色。
2. 计算漫发射需要知道4个参数:
漫反射颜色:_Color
顶点法线:v.normal
光源的颜色和强度:_LightColor0
光源方向:_WorldSpaceLightPos0
3. 计算法线和光源方向之间的点积,只有两者在同一坐标空间下才有意义。可以使用顶点变换矩阵的逆转置矩阵对法线进行相同的 变换,因此首先得到模型空间到世界空间的变换矩阵的逆矩阵_World2Object,由于法线是一个三维矢量,因此只需要截取 _World2Object的前三行前三列。
4. 得到了世界空间中的法线和光源方向后,需要进行归一化操作。得到点积的结果后,要防止这个结果为负值,所有使用saturate 函数,它的作用是可以把参数截取到[0,1]的范围内。最后,再与光源的颜色和强度以及漫反射的颜色相乘,就得到了最终的漫 反射光照部分。