有些时候需要让角色死亡时逐渐燃烧消失,用表面着色器很容易实现。
可以用一张黑白图片控制各部位的消融顺序,比如让该图片的某通道和一个变量相比,小于该变量则舍弃片元。变量从0不断变大,则消融面积逐渐扩大。
燃烧部分的颜色则读取自一张渐变贴图,类似于渐变纹理。可以取代纹理颜色或进行差值,也可以直接当做自发光(Emission)。
代码:
Shader "Test"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {} //纹理贴图
_DisolveTex("DisolveTex",2D) = "white"{}//噪声图,影响哪些位置被消融
_Threshold("Threshold",Range(0,1)) = 0 //控制消融程度
_EdgeLength("EdgeLength", Range(0,0.2)) = 0.1 //过渡部分多少大
_BurnTex("BurnTex", 2D) = "white"{} //渐变图,过渡部分用
_BurnInstensity("BurnInstensity", Range(0,5)) = 1 //过渡部分的强度
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
sampler2D _DisolveTex;
half _Threshold;
sampler2D _BurnTex;
half _EdgeLength;
half _BurnInstensity;
struct Input
{
float2 uv_MainTex;
float2 uv_DisolveTex;
};
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
//读取纹理贴图
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) ;
o.Albedo = c.rgb;
//消融
float cutout = tex2D(_DisolveTex, IN.uv_DisolveTex).r;
//值小于0时舍弃该片元。
clip(cutout - _Threshold);
//temp越接近0的位置越接近消融边界。
float temp = saturate((cutout - _Threshold) / _EdgeLength);
//用temp当uv坐标读取渐变纹理。temp越接近0读取位置越靠近左下,temp越接近1读取位置越靠近右上。
fixed4 edgeColor = tex2D(_BurnTex,float2(temp,temp));
//将过渡的燃烧颜色作为自发光。temp=1时该片元完全不显示过渡颜色,当小于1时显示过渡颜色。
fixed4 finalColor = _BurnInstensity * lerp(edgeColor, fixed4(0,0,0,0), temp);
o.Emission = finalColor.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
增大_Threshold值的效果:
如果想要用c#代码控制消融,先获得材质
material = GetComponent<SkinnedMeshRenderer>().materials[0];
之后就可以修改material.SetFloat("_Threshold", 值);