效果如图:
原理在代码注释中。
Shader代码:
Shader"Custom/RealisticSnow"{
Properties{
_MainTex("Base(RGB)",2D)="white"{}
_Bump("Bump",2D)="bump"{}
_Snow("SnowLevel",Range(0,1))=0
_SnowColor("SnowColor",Color)=(1.0,1.0,1.0,1.0)
_SnowDirection("SnowDirection",Vector)=(0,1,0)
_SnowDepth("SnowDepth",Range(0,0.2))=0.1
_Wetness("Wetness",Range(0,0.5))=0.3
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD200
CGPROGRAM
#pragmasurfacesurfLambertvertex:vert
sampler2D_MainTex;
sampler2D_Bump;
float_Snow;
float4_SnowColor;
float4_SnowDirection;
float_SnowDepth;
float_Wetness;
structInput{
float2uv_MainTex;
float2uv_Bump;
float3worldNormal;
INTERNAL_DATA
};
voidvert(inoutappdata_fullv){
//通过【模型到视角的逆转置矩阵】将【积雪方向】转换到【模型坐标系】中
float4sn=mul(UNITY_MATRIX_IT_MV,_SnowDirection);
//计算当前【点的法线方向】和【下雪反方向】的点乘[-1,1]
//如果顶点点乘大于设置的_Snow值,那么该点就往【点的法线方向】和【下雪反方向】之和的方向挤出
//如果雪量_Snow为0.5,那么模型法线为up的点挤出最多
if(dot(v.normal,sn.xyz)>=lerp(1,-1,_Snow))
{
v.vertex.xyz+=(sn.xyz+v.normal)*_SnowDepth*_Snow;
}
}
voidsurf(InputIN,inoutSurfaceOutputo){
half4c=tex2D(_MainTex,IN.uv_MainTex);
o.Normal=UnpackNormal(tex2D(_Bump,IN.uv_Bump));
//_Snow为0.5时,diff值域【-1,1】
halfdifference=dot(WorldNormalVector(IN,o.Normal),_SnowDirection.xyz)-lerp(1,-1,_Snow);
//当_Wetness为0.3时,要控制diff的最终值域为【0,1】,那么就有0
//可以得出【法线方向】和【积雪方向】夹角为73-90度之间时,就会有【雪】与【地面】材质叠加的效果
//而小于73度的,都是积雪;大于90度的没有积雪
difference=saturate(difference/_Wetness);
o.Albedo=difference*_SnowColor.rgb+(1-difference)*c;
o.Alpha=c.a;
}
ENDCG
}
FallBack"Diffuse"
}
来源:http://www.lxway.com/40250226.htm