- 噪声纹理(一张灰度图)采样得到其中噪声值(rgb中其中一个就行),使用这个值进行alphaTest或者其他用途
- 使用了一个过渡色,即将消融与不消融之间的过渡颜色,具体原理在代码中有注释
- 阴影的特殊处理,因为消融后不应该再投射阴影,所以必须要自己定义“LightMode” = “ShadowCaster”阴影投射pass,得到正确的阴影投射图。
Shader "FFD/15/Dissolve"
{
Properties
{
_BurnAmount("Burn Amount",range(0.0,1.0)) = 0.0
_LineWidth("Burn Line Width",range(0.0,0.2)) = 0.1
_BumpScale ("Bump Scale",range(-1,1)) = 0
_MainTex("Main Tex",2D) = "white"{}
_BumpTex("Bump Map",2D) = "bump"{}
_BurnTex("Burn Map",2D) = "white"{}
_BurnFirstColor("Burn First Color",Color) = (1,1,1,1)
_BurnSecondColor("Burn Second Color",Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
cull off
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwardbase
#include "UnityCG.cginc"
#include "autolight.cginc"
#include "lighting.cginc"
struct v2f
{
float2 mainUV : TEXCOORD0;
float2 bumpUV : TEXCOORD1;
float2 burnUV : TEXCOORD2;
float3 worldNormal : NORMAL;
float4 TtoW0 : TEXCOORDD3;
float4 TtoW1 : TEXCOORD4;
float4 TtoW2 : TEXCOORD5;
float4 pos : SV_POSITION;
SHADOW_COORDS(6)
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpTex;
float4 _BumpTex_ST;
sampler2D _BurnTex;
float4 _BurnTex_ST;
float _BurnAmount;
float _LineWidth;
float _BumpScale;
fixed4 _BurnFirstColor;
fixed4 _BurnSecondColor;
v2f vert (appdata_full v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.mainUV = TRANSFORM_TEX(v.texcoord, _MainTex);
o.bumpUV = TRANSFORM_TEX(v.texcoord, _BumpTex);
o.burnUV = TRANSFORM_TEX(v.texcoord, _BurnTex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
float3 biNormal = cross(v.normal,v.tangent.xyz)*v.tangent.w;
float3 biNormalWorld = UnityObjectToWorldDir(biNormal);
float3 tangentWorld = UnityObjectToWorldDir(v.tangent);
float4 worldPos = mul(unity_ObjectToWorld,v.vertex);
o.TtoW0 = float4(tangentWorld.x,biNormalWorld.x,o.worldNormal.x,worldPos.x);
o.TtoW1 = float4(tangentWorld.y,biNormalWorld.y,o.worldNormal.y,worldPos.y);
o.TtoW2 = float4(tangentWorld.z,biNormalWorld.z,o.worldNormal.z,worldPos.z);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.mainUV);
fixed3 burn = tex2D(_BurnTex,i.burnUV).rgb;
clip(burn.g-_BurnAmount);
float3x3 tanToWorld = float3x3(i.TtoW0.xyz,i.TtoW1.xyz,i.TtoW2.xyz);
float4 worldPos = float4(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w,1);
float3 norBump = UnpackNormal(tex2D(_BumpTex,i.bumpUV));
norBump.xy = norBump.xy * _BumpScale;
norBump.z = sqrt(1-saturate(dot(norBump.xy,norBump.xy)));
float3 worldNormal = normalize(mul(tanToWorld,norBump));
float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * col;
fixed3 diffuse = _LightColor0.xyz * saturate(dot(worldNormal,worldLight)) * col;
// UNITY_LIGHT_ATTENUATION(atten,i,worldPos);
float shadow = SHADOW_ATTENUATION(i);
float t = 1-smoothstep(0,_LineWidth,(burn.r-_BurnAmount));
//如果t为1的话说明当前像素马上要被灼烧掉此时颜色应该很红,如果为0的话说明还要等BurnAmount的值增加到1才灼烧,此时颜色应该很淡
//如果t为0说明burn.r-_BurnAmount>_LineWidth;也就是说amount还没怎么增长,此时burnColor全为第一个颜色
fixed4 burnColor = lerp(_BurnFirstColor,_BurnSecondColor,t);
// burnColor = pow(burnColor,5);
fixed3 finalColor = lerp(ambient+diffuse*shadow,burnColor.xyz,t*step(0.001,_BurnAmount));
return fixed4(finalColor,1);
// fixed testSmooth = smoothstep(0.5,0.6,0.655);
// return fixed4(testSmooth,testSmooth,testSmooth,testSmooth);
// return fixed4(0.655,0.655,0.655,0.655);
}
ENDCG
}
Pass
{
Tags{"LightMode" = "ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "unitycg.cginc"
#include "autolight.cginc"
#include "lighting.cginc"
float _BurnAmount;
sampler2D _BurnTex;
float4 _BurnTex_ST;
struct v2f{
//系统定义的宏,包含了阴影投射需要的变量值
V2F_SHADOW_CASTER;
float2 uv : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
//计算得到上面宏定义好的变量值
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
o.uv = TRANSFORM_TEX(v.texcoord,_BurnTex);
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed3 burn = tex2D(_BurnTex,i.uv).rgb;
clip(burn.r-_BurnAmount);
//完成阴影投射
SHADOW_CASTER_FRAGMENT(i);
}
ENDCG
}
}
FallBack "Diffuse"
}