游戲中物體腐化消失,燃燒消失時,會有從局部慢慢消失的效果,然后配合一些粒子特效,就能達到非常好的美術效果。
類似效果如下:
注:
_DissColor為溶解主色,_AddColor為疊加色,按照溶解的移動方向來看開始色為DissColor+AddColor
上圖中DissColor為紅色,AddColor為綠色
所以燃燒時
開始色為DissColor + AddColor = 黃色
默認色為DissColor 紅色
然后配上火的粒子特效,這樣就能模擬比較真實的燃燒效果。
我們也可以設置其他的顏色,比如被各種魔法,化學物品擊中.....算了,不敢想象了,好殘忍![]()
![]()
代碼和原理如下:
表面着色器:
Shader "Dissolve/Dissolve_TexturCoords" { Properties { _Color ("主顏色", Color) = (1,1,1,1) // 主色 _MainTex ("模型貼圖", 2D) = "white" {} // 主材質 _DissolveText ("溶解貼圖", 2D) = "white" {} // 溶解貼圖 _Tile("溶解貼圖的平鋪大小", Range (0, 1)) = 1 // 平鋪值,設置溶解貼圖大小 _Amount ("溶解值", Range (0, 1)) = 0.5 // 溶解度 _DissSize("溶解大小", Range (0, 1)) = 0.1 // 溶解范圍大小 _DissColor ("溶解主色", Color) = (1,1,1,1) // 溶解顏色 _AddColor ("疊加色,與主色疊加為開始色[R|G|B>0表示啟用]", Color) = (1,1,1,1) // 改色與溶解色融合形成開始色 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull off CGPROGRAM #pragma target 3.0 #pragma surface surf BlinnPhong sampler2D _MainTex; sampler2D _DissolveText; fixed4 _Color; // 主色 half _Tile; // 平鋪值 half _Amount; // 溶解度 half _DissSize; // 溶解范圍 half4 _DissColor; // 溶解顏色 half4 _AddColor; // 疊加色 // 最終色 static half3 finalColor = float3(1,1,1); struct Input { float2 uv_MainTex; // 只需要主材質的UV信息 }; void surf (Input IN, inout SurfaceOutput o) { // 對主材質進行采樣 fixed4 tex = tex2D(_MainTex, IN.uv_MainTex); // 設置主材質和顏色 o.Albedo = tex.rgb * _Color.rgb; // 對裁剪材質進行采樣,取R色值 float ClipTex = tex2D (_DissolveText, IN.uv_MainTex/_Tile).r; // 裁剪量 = 裁剪材質R - 外部設置量 float ClipAmount = ClipTex - _Amount; if(_Amount > 0) { // 如果裁剪材質的R色值 < 設置的裁剪值 那么此點將被裁剪 if(ClipAmount < 0) { clip(-0.1); } // 然后處理沒有被裁剪的值 else { // 針對沒有被裁剪的點,【裁剪量】小於【裁剪大小】的做處理 // 如果設置了疊加色,那么該色為ClipAmount/_DissSize(這樣會形成漸變效果) if(ClipAmount < _DissSize) { if(_AddColor.x == 0) finalColor.x = _DissColor.x; else finalColor.x = ClipAmount/_DissSize; if (_AddColor.y == 0) finalColor.y = _DissColor.y; else finalColor.y = ClipAmount/_DissSize; if (_AddColor.z == 0) finalColor.z = _DissColor.z; else finalColor.z = ClipAmount/_DissSize; // 融合 o.Albedo = o.Albedo * finalColor * 2; } } } o.Alpha = tex.a * _Color.a; } ENDCG }//endsubshader }
CG:
//溶解 Shader "Dissolve" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _DissolorTex ("DissolorTex (RGB)", 2D) = "white" {} _RAmount ("RAmount", Range (0, 1)) = 0.5 _DissolorWith("DissolorWith", float) = 0.1//溶解過度寬度 _DissColor ("DissColor", Color) = (1,1,1,1)//溶解顏色 _Illuminate ("Illuminate", Range (0, 4)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Pass { CGPROGRAM #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; struct v2f { float4 pos : POSITION; half2 texcoord : TEXCOORD0; half2 texcoord1 : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _DissolorTex; float4 _DissolorTex_ST; half _RAmount; half _DissolorWith; half4 _DissColor; half _Illuminate; v2f vert(appdata v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); o.texcoord1 = TRANSFORM_TEX(v.texcoord1, _DissolorTex); return o; } half4 frag(v2f i) :COLOR { half4 mainCol = tex2D(_MainTex,i.texcoord); half4 DissolorTexCol = tex2D(_DissolorTex,i.texcoord1); half clipVauleR = DissolorTexCol.r - _RAmount; if(clipVauleR <= 0) { if(clipVauleR > -_DissolorWith) { if(_RAmount != 1) { //插值顏色過度 float t = clipVauleR / -_DissolorWith; mainCol = lerp(mainCol, _DissColor, t); } else { discard; } } else { discard; } } return mainCol * _Illuminate; } #pragma vertex vert #pragma fragment frag ENDCG } } }
