代码,讲解都在注释上面了:
冯乐乐的《unity shader 入门精要》:
相关知识:
- 透明度
- 阴影计算
- 普通光照
- 法线贴图
Properties
{
_BurnAmount("BurnAmount",Range(0,1)) = 0
_LineWidth("LineWidth",Range(0,0.2)) = 0.1
_MainTex("MainTex",2D) = "white"{}
_BumpMap("BumpMap",2D) = "white"{}
_BumpFirstColor("BumpFirstColor",Color) = (1,1,1,1)
_BumpSencondColor("BumpSencondColor",Color) = (1,1,1,1)
_BurnMap("BurnMap",2D) = "white"{}
}
SubShader
{
pass {
Tags{"LightMode" = "ForwardBase"}
Cull Off
//cg语言开始编写
CGPROGRAM
//片段程序
#pragma fragment frag
#pragma multi_compile_fwdbase
struct Output {
float4 pos:POSITION;
float2 uvMainTex:TEXCOORD0;
float2 uvBumpMap:TEXCOORD1;
float2 uvBurnMap:TEXCOORD2;
float3 lightDir:TEXCOORD3;
float3 worldPos:TEXCOORD4;
//阴影
SHADOW_COORDS(5)
};
Output vert(Input v)
{
Output o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uvMainTex = TRANSFORM_TEX(v.uv, _MainTex);
o.uvBumpMap = TRANSFORM_TEX(v.uv, _BumpMap);
o.uvBurnMap = TRANSFORM_TEX(v.uv, _BurnMap);
//切线空间转换rotation
TANGENT_SPACE_ROTATION;
o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//阴影计算
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(Output i) :SV_Target
{
fixed4 burn = tex2D(_BurnMap,i.uvBurnMap);
//为了全部剪除,需要对burn.a - _BurnAmount进行差值判断
float val = burn.a - _BurnAmount < 0.01 ? -1 : burn.a - _BurnAmount;
//裁剪
clip(val);
//采样物体本身纹理图
float3 albedo = tex2D(_MainTex, i.uvMainTex).xyz;
//计算切线空间数据
float3 tangentLight = normalize(i.lightDir);
float3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));
//环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
//切线空间下的漫反射,也可以自己添加镜面高光,为了法线贴图
fixed3 diff = _LightColor0.rgb*albedo*max(0, dot(tangentLight, tangentNormal));
//裁剪边缘的颜色区域宽度
fixed t = 1 - smoothstep(0, _LineWidth, burn.a - _BurnAmount);
fixed3 burnColor = lerp(_BumpFirstColor, _BumpSencondColor, t);
burnColor = pow(burnColor, 5);
//阴影计算atten
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
fixed3 finalColor = lerp(ambient + diff * atten, burnColor, t*step(0.0001, _BurnAmount));
return fixed4(finalColor, 1);
}
ENDCG
}
//可以试着将这个pass注释掉,看效果,会发现阴影没有随着裁剪而变化
pass{
Tags{"LightMode" = "ShadowCaster"}
//cg语言开始编写
CGPROGRAM
//片段程序
#pragma fragment frag
#pragma multi_compile_shadowcaster
struct Output {
V2F_SHADOW_CASTER;
float2 uvBurnMap:TEXCOORD2;
};
Output vert(Input v)
{
Output o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
o.uvBurnMap = TRANSFORM_TEX(v.uv, _BurnMap);
return o;
}
fixed4 frag(Output i) :SV_Target
{
fixed4 burn = tex2D(_BurnMap,i.uvBurnMap);
float val = burn.a - _BurnAmount < 0.01 ? -1 : burn.a - _BurnAmount;
clip(val);
SHADOW_CASTER_FRAGMENT(i)//投射阴影
}
ENDCG
}
CGINCLUDE
//在逻辑中申明顶点和片段://编译申明函数
//顶点程序
#pragma vertex vert
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityCG.cginc"
struct Input {
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
float3 normal:NORMAL;
float4 tangent:TANGENT;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
sampler2D _BurnMap;
float4 _BurnMap_ST;
float _BurnAmount;
float _LineWidth;
float4 _BumpFirstColor;
float4 _BumpSencondColor;
ENDCG
}
FallBack "Specular"//影子
效果: