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"
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章