unity ablation effect

Keywords: Fragment Unity


As shown in the figure above, the function of this shader is to melt the box bit by bit and then gradually disappear.
This shader function is mainly divided into two parts, the first part is disappearance, the second part is edge shading, and the third part is Custom Shadow Projection Pass.
The implementation of disappearance is relatively simple, only one line of code is needed, clip(burn.r - _BurnAmount); direct reduction of unsatisfactory fragments, burn is a noise map, which can form the effect of random disappearance.
The code of the edge shading part is still at a certain level. The distance from the vanishing point is determined by the value of burn.r-_BurnAmount. Then the value is smoothed into the 0-LineWidth interval, and the difference between the original texture and the burned color can be obtained by this value. In order to optimize the visual effect, the code also uses this value to sample the two burned colors, and then returns the fifth power, which I think is mostly from experience.
The last function is shadow projection texture, because if you use the system's shadow projection texture directly, the clipped content will still appear in the shadow, so you need to write shadow projection texture yourself, and also cut the same points in the shadow projection texture, this part is more using the system. The traditional API belongs to the memory part.
The complete code is as follows:

Shader "Unity Shaders Book/Chapter 15/Dissolve" {
       Properties {
              _BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0
              _LineWidth("Burn Line Width", Range(0.0, 0.2)) = 0.1
              _MainTex ("Base (RGB)", 2D) = "white" {}
              _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 "Lighting.cginc"
                     #include "AutoLight.cginc"
                     
                     #pragma multi_compile_fwdbase
                     
                     #pragma vertex vert
                     #pragma fragment frag
                     
                     fixed _BurnAmount;
                     fixed _LineWidth;
                     sampler2D _MainTex;
                     sampler2D _BumpMap;
                     fixed4 _BurnFirstColor;
                     fixed4 _BurnSecondColor;
                     sampler2D _BurnMap;
                     
                     float4 _MainTex_ST;
                     float4 _BumpMap_ST;
                     float4 _BurnMap_ST;
                     
                     struct a2v {
                           float4 vertex : POSITION;
                           float3 normal : NORMAL;
                           float4 tangent : TANGENT;
                           float4 texcoord : TEXCOORD0;
                     };
                     
                     struct v2f {
                           float4 pos : SV_POSITION;
                           float2 uvMainTex : TEXCOORD0;
                           float2 uvBumpMap : TEXCOORD1;
                           float2 uvBurnMap : TEXCOORD2;
                           float3 lightDir : TEXCOORD3;
                           float3 worldPos : TEXCOORD4;
                           SHADOW_COORDS(5)
                     };
                     
                     v2f vert(a2v v) {
                           v2f o;
                           o.pos = mul(UNITY_MATRIX_MVP, 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)).xyz;
                            
                            o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                            
                            TRANSFER_SHADOW(o);
                           
                           return o;
                     }
                     
                     fixed4 frag(v2f i) : SV_Target {
                           fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
                           
                           clip(burn.r - _BurnAmount);
                           
                           float3 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 * max(0,  dot(tangentNormal, tangentLightDir));
                           fixed t = 1 - smoothstep(0.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 to render object as a shadow caster
              Pass {
                     Tags { "LightMode" = "ShadowCaster" }
                     
                     CGPROGRAM
                     
                     #pragma vertex vert
                     #pragma fragment frag
                     
                     #pragma multi_compile_shadowcaster
                     
                     #include "UnityCG.cginc"
                     
                     fixed _BurnAmount;
                     sampler2D _BurnMap;
                     float4 _BurnMap_ST;
                     
                     struct v2f {
                           V2F_SHADOW_CASTER;
                           float2 uvBurnMap : TEXCOORD1;
                     };
                     
                     v2f vert(appdata_base v) {
                           v2f o;
                           
                           TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                           
                           o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
                           
                           return o;
                     }
                     
                     fixed4 frag(v2f i) : SV_Target {
                           fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
                           
                           clip(burn.r - _BurnAmount);
                           
                           SHADOW_CASTER_FRAGMENT(i)
                     }
                     ENDCG
              }
       }
       FallBack "Diffuse"
}

Posted by Kazhultee on Thu, 19 Sep 2019 06:18:16 -0700