之前的Shader中,使用的Lambert光照模型
#pragma surface surf Lambert
这是一个很经典的漫反射模型,光强与入射光的方向和反射点处表面法向夹角的余弦成正比。简单解释就是一个点的反射光强是和该点的法线向量和入射光向量和强度和夹角有关系的,其结果就是这两个向量的点积。
代码
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的类型,计算调用的方法名,以及指定光照模型。之前我们一直指定Lambert为光照模型,而现在我们将其换为了CustomDiffuse(对应下面的LightingCustomDiffuse方法)
Shader中对于方法的名称有着比较严格的约定,想要创建一个光照模型,首先要做的是按照规则声明一个光照计算的函数名字,即Lighting+方法名。对于我们的光照模型CustomDiffuse,其函数的名称就是LightingCustomDiffuse。
之前使用的Lambert光照模型,来自Unity的内建Shader,在Lighting.cginc文件中包含了LightingLambert的实现。
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 是函数surf处理后的输出,我们讲对其上的点根据光线进行处理,fixed3 lightDir 是光线的方向,fixed atten 表示光衰减的系数。在计算光照的代码中,我们先将输入的s的法线值和输入光线进行点积(dot函数是CG中内置的数学函数)。点积的结果在-1至1之间,这个值越大表示法线与光线间夹角越小,这个点也就应该越亮。之后使用max来将这个系数结果限制在0到1之间,是为了避免负数情况的存在而导致最终计算的颜色变为负数,输出一团黑。接下来我们将surf输出的颜色与场景光线的颜色_LightColor0.rgb(由Unity根据场景中的光源得到的,在Lighting.cginc中有声明)进行乘积,然后再与刚才计算的光强系数和输入的衰减系数相乘,最后得到在这个光线下的颜色输出。
与使用Lamber光照模型的贴图效果一样,这里就不再展示效果图了。