下面从官方文档整理的代码,在代码里面以做好解释。
Shader "Custom/OfficialExam2" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Ramp("Ramp",2D) = ""{}
}
SubShader {
//告诉系统该shader将会在渲染非透明物体时被渲染。
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
//下面附有三个光照模型这里使用SimpleSpecular,系统内建的光照模型有:Lembert(diffuse) 和 BlinnPhong(specular).
#pragma surface surf SimpleSpecular
sampler2D _Ramp;
//在U3D中,内建光照模型的功能不能满足我们的需求时,我们需要自己写光照模型。
//光照模型的格式系统已经定义好了,我们必须按照这个格式。
// 有关光照模型的定义:"http://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html"
//下面是一个镜面反射的例子
half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
//这里将光照方向向量与视角方向相加。在游戏运行时,view与camera相同。
half3 h = normalize (lightDir + viewDir);
// 将模型的法向量与光照方向点乘,结果为Cos(angle),在与0比较取最大值。也就是说小于0的时候将等于0.
//这里有必要说viewDir 与 lightDir 是入射点引到视点和灯光位置的向量
half diff = max (0, dot (s.Normal, lightDir));
//这里与上面的算法一样,需要提到的是当光的方向与视角的方向的和,与上面与法向量的关系会一样。
float nh = max (0, dot (s.Normal, h));
//pow()指数。 48.0表示高光指数,这个指数越高说明光照越聚集。
float spec = pow (nh, 48.0);
half4 c;
//OK我们重点理解这句话,先看加号前面。 根据上面的理解,当diff等于0时表达式1将不会对模型进行灯光着色。 那么只有他大于0,大于0是怎样的情况呢,
//就是灯光照射到模型上
//第二个表达式会形成光斑的效果,cos在向量越接近垂直时,将会越小。
//这样就能使两个别表达式为模型着上灯光的颜色了。
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
c.a = s.Alpha;
return c;
}
//这个比较简单
half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
//点乘 法线向量和光照方向向量。 回事一个介于(-1,1)之间的一个数。
half NdotL = dot (s.Normal, lightDir);
//转化到(0,1)之间,因为color介于(0,1)
half diff = NdotL * 0.5 + 0.5;
half4 c;
//OK,乘上衰减
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
c.a = s.Alpha;
//返回这个值。
return c;
}
//这个与上面的差不多,多了一个ramp ,理解的时候记得ramp是一个从黑到白渐进的一直灰度图。
half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
float diff = NdotL * 0.5 + 0.5;
// float2 diff2 = float2(diff,diff);
half3 ramp = tex2D (_Ramp,float2(diff,diff)).rgb;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
c.a = s.Alpha;
return c;
}
half4 LightingStandard (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
c.a = s.Alpha;
return c;
}
//这部分是模型对光照贴图的处理。
inline fixed4 LightingStandard_SingleLightmap (SurfaceOutput s, fixed4 color) {
half3 lm = DecodeLightmap (color);
return fixed4(lm, 0);
}
inline fixed4 LightingStandard_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
half3 lm = lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade);
return fixed4(lm, 0);
}
inline fixed4 LightingStandard_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {
UNITY_DIRBASIS
half3 lm = DecodeLightmap (color);
half3 scalePerBasisVector = DecodeLightmap (scale);
if (surfFuncWritesNormal)
{
half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));
lm *= dot (normalInRnmBasis, scalePerBasisVector);
}
return fixed4(lm, 0);
}
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D(_MainTex,IN.uv_MainTex).rgb;
}
ENDCG
}
FallBack "Diffuse"
}
//不对之处 ,欢迎指正。