内置管线

Shader "SunY/C15-Dissolve"
{
    Properties
    {
        _BurnAmount("Burn Amount", Range(0, 1)) = 0
        _LineWidth("Line Width", Range(0, 0.2)) = 0.1
        _MainTex("Main Tex", 2D) = "wihte"{}
        _BumpMap("Normal Map", 2D) = "bump"{}
        _BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)
        _BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)
        _BurnMap("Burn Map", 2D) = "white"{}
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry" }

        Pass
        {
            Tags { "LightMode" = "ForwardBase" }
            Cull Off

            CGPROGRAM

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            #pragma vertex vert
            #pragma fragment frag

            #pragma multi_compile_fwdbase

            fixed _BurnAmount;
            fixed _LineWidth;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            fixed4 _BurnFirstColor;
            fixed4 _BurnSecondColor;
            sampler2D _BurnMap;
            float4 _BurnMap_ST;

            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 tangent : TANGENT;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uvMainTex : TEXCOORD0;
                float2 uvBumpMap : TEXCOORD1;
                float2 uvBurnMap : TEXCOORD2;
                float3 lightDir : TEXCOORD3;
                float4 worldPos : TEXCOORD4;
                SHADOW_COORDS(5)
            };

            v2f vert(a2v v)
            {
                v2f o;

                o.pos = UnityObjectToClipPos(v.vertex);
                o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);
                o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);

                TANGENT_SPACE_ROTATION;

                o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);

                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;

                clip(burn.r - _BurnAmount);

                fixed3 tangentLightDir = normalize(i.lightDir);
                fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));

                fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(tangentNormal, tangentLightDir));

                fixed t = 1 - smoothstep(0, _LineWidth, burn.r - _BurnAmount);
                fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);
                burnColor = pow(burnColor, 5);

                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
                fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001, _BurnAmount));

                return fixed4(finalColor, 1);
            }

            ENDCG
        }

        Pass
        {
            Tags { "LightMode" = "ShadowCaster" }

            CGPROGRAM

            #include "UnityCG.cginc"

            #pragma vertex vert
            #pragma fragment frag

            #pragma multi_compile_shadowcaster

            fixed _BurnAmount;
            sampler2D _BurnMap;
            float4 _BurnMap_ST;

            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                V2F_SHADOW_CASTER;
                float2 uv : TEXCOORD1;
            };

            v2f vert(a2v v)
            {
                v2f o;

                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                o.uv = TRANSFORM_TEX(v.texcoord, _BurnMap);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 burn = tex2D(_BurnMap, i.uv).rgb;
                clip(burn.r - _BurnAmount);
                SHADOW_CASTER_FRAGMENT(i)
            }

            ENDCG
        }
    }
}

URP渲染管线

Shader "SunY/C15-U-Dissolve"
{
    Properties
    {
        _BurnAmount("Burn Amount", Range(0, 1)) = 0
        _LineWidth("Line Width", Range(0, 0.2)) = 0.1
        _MainTex("Main Tex", 2D) = "white"{}
        _BumpMap("Normal Map", 2D) = "bump"{}
        _BurnFirstColor("Burn First Color", Color) = (1, 1, 1, 1)
        _BurnSecondColor("Burn Second Color", Color) = (1, 1, 1, 1)
        _BurnMap("Burn Map", 2D) = "white"{}
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry" "RenderPipeline" = "UniversalPipeline"}

        Pass
        {
            Tags { "LightMode" = "UniversalForward" }
            Cull Off

            HLSLPROGRAM

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            #pragma vertex vert
            #pragma fragment frag

            half _BurnAmount;
            half _LineWidth;
            float4 _MainTex_ST;
            float4 _BumpMap_ST;
            half4 _BurnFirstColor;
            half4 _BurnSecondColor;
            float4 _BurnMap_ST;

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            TEXTURE2D(_BumpMap);
            SAMPLER(sampler_BumpMap);
            TEXTURE2D(_BurnMap);
            SAMPLER(sampler_BurnMap);

            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 tangent :TANGENT;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uvMainTex : TEXCOORD0;
                float2 uvBumpMap : TEXCOORD1;
                float2 uvBurnMap : TEXCOORD2;
                float3 worldPos : TEXCOORD3;
                float3 tangentLightDir : TEXCOORD4;
            };

            v2f vert(a2v v)
            {
                v2f o;

                o.pos = TransformObjectToHClip(v.vertex);
                o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);
                o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
                o.worldPos = TransformObjectToWorld(v.vertex).xyz;

                Light light = GetMainLight();

                float3x3 rotation = CreateTangentToWorld(v.normal, v.tangent, v.tangent.w);
                o.tangentLightDir = TransformObjectToTangent(light.direction, rotation);

                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                half4 burn = SAMPLE_TEXTURE2D(_BurnMap, sampler_BurnMap, i.uvBurnMap);
                clip(burn.r - _BurnAmount);

                float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.worldPos);
                Light light = GetMainLight(SHADOW_COORDS);

                half3 tangentLightDir = normalize(i.tangentLightDir);
                half3 tangentNormal = UnpackNormal(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, i.uvBumpMap));

                half3 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uvMainTex).rgb;
                // 环境光
                half3 ambient = _GlossyEnvironmentColor * albedo;

                // 计算半兰伯特漫反射
                half3 diffuse = light.color.rgb * albedo * (dot(tangentLightDir, tangentNormal) * 0.5 + 0.5);

                half t = 1 - smoothstep(0, _LineWidth, burn.r - _BurnAmount);
                half3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);
                burnColor = pow(burnColor, 5);

                half3 finalColor = lerp(ambient + diffuse * light.shadowAttenuation, burnColor, t * step(0.0001, _BurnAmount));

                return half4(finalColor, 1);
            }

            ENDHLSL
        }
    }
}