unity 消融效果

在这里插入图片描述
如上图所示,本shader的功能就是让箱子一点一点的消融,然后逐渐消失。
这个shader功能主要分为两个部分,第一个部分是消失,第二个部分是边缘着色,第三个部分是自定义阴影投射的Pass。
消失的实现是比较简单的,只需要一行代码即可,clip(burn.r - _BurnAmount);直接裁减掉不满足要求的片元,burn是一个噪声图,这样可以形成随机消失的效果。
边缘着色部分的代码还是有一定的水平的,通过burn.r-_BurnAmount值的大小来判定其离消失的点的距离,然后把这个值平滑到0~_LineWidth区间中,通过这个值在原纹理和被烧焦的颜色之间进行差值即可。为了优化视觉效果,代码中还通过这个值对两种烧焦的颜色进行采样,然后还还了五次方,这些操作我想大抵上还是经验所得。
最后一个功能就是阴影投射纹理,因为如果直接使用系统的阴影投射纹理的话,裁剪掉的内容还是会在阴影中显示出来的,所以,需要自己写阴影投射纹理,在阴影投射纹理中也同样裁剪掉相同的点,这一部分更多的是使用系统的API,属于记忆部分。
完整代码如下:

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"
}
发布了31 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43813453/article/details/101035404