【unity shader】unity游戏特效-仿《黑暗欺骗》模型消融消失效果
閑暇時看紙魚實況,看到游戲中有個這樣的效果:
 視頻鏈接,UP主:薄海紙魚
臥槽,放慢再看一遍:
 
可以看到,玩家在惹怒Boss后,所有的椅子瞬間消失,Boss戰(zhàn)還未開打就已經逼格拉滿了。給玩家留下震撼的印象以及實力差所帶來的壓抑和絕望。
太帥了!這個效果我也想要!
實現(xiàn)思路
仔細觀察椅子消失瞬間:
 
 想要實現(xiàn)這個效果有三個要求:
 一是要剔除片元來達到物體消融的效果。
 二是在剔除片元的操作里設定剔除的條件。
 三是在剔除的邊緣上顏色高亮
看完了馮樂樂女神的書,我們就知道解決第一個問題需要用到的就是clip函數(shù),該函數(shù)可以剔除指定的片元
clip(x) ///相當于下面這句 if(x < 0) {discard; }ok,上代碼:
Shader "Unlit/DirectionalDissolve" {Properties{_MainTex ("Texture", 2D) = "white" {}_DissolveDirection ("消融方向",Vector) = (0,0,0,0)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{Cull offCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float3 objPos : TEXCOORD1;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;half4 _DissolveDirection;v2f vert (appdata v){v2f o;//v.vertex.xyz += v.normal * saturate(sin(_Time.w)) * 10;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.objPos = v.vertex;//mul(unity_ObjectToWorld,v.vertex).xyz;return o;}fixed4 frag (v2f i) : SV_Target{half3 dis = i.objPos.xyz - _DissolveDirection.xyz;half discardCondition = dis.y;clip(discardCondition);fixed4 texColor = tex2D(_MainTex, i.uv);fixed4 col = fixed4(texColor.rgb,1.0);return col;}ENDCG}} }這里最好開Cull off,否則正面剔除一半時玩家會發(fā)現(xiàn)后面早空了。
可以看見關鍵代碼在這兩句
half dis = i.objPos.y - _DissolveDirection.y; clip(dis);clip()剔除掉我們不需要的片元。而dis的那句話是用物體對象的模型坐標的y軸與我們給的一個三維矢量的y軸進行相減計算,軸上相減的結果小于0的部分片元就會被剔除掉。
還可以拓展成下面這樣:
half3 dis = i.objPos.xyz - _DissolveDirection.xyz; half discardCondition = * dis.y; clip(discardCondition);如果想要左右方向的消除,就把dis.y改為x即可。
但要注意,這個是利用的模型坐標系進行計算。如果一個模型(假設是人體模型)。他模型坐標系的Y軸不是向上而是向前。那你就不能用y軸上的計算來實現(xiàn)從頭到腳的順序消失。
 你可以考慮用世界坐標系解決,世界坐標系XYZ軸方向是不會變的,但同樣會引入新的問題——物體所在的位置會影響計算結果。這個問題我目前還沒有比較好的解決方法,看看以后有沒有好兄弟來幫個忙。
OK,這是目前的效果:
 
 emmmmmm,其實我想要你們從頭的方向開始消失,而不是腳。。。
這里我用了一個笨辦法,引入一個新int屬性,用1和-1來控制消融的方向;想要反方向?乘個負一就好。
OK,前兩個問題搞定了,現(xiàn)在需要解決高亮的問題了。
咱們前面不是利用兩個矢量相減計算嗎?小于0的部分被剔除掉了。那我們就再設定一個小于某值但大于0的范圍,相減結果在這個范圍內的,返回的顏色值要發(fā)生改變。
 效果如下:
 
圖中的_width值設為0.1,fixed4(1,1,1,1)代表輸出白色。
 我這里用了if,但這種語句是不建議用在shader里的,GPU上做這種邏輯判斷是非常非常奢侈的。
 可惜目前沒有想出更好的辦法,只能先把問題放在這了。
最終代碼:
Shader "Unlit/DirectionalDissolve" {Properties{_MainTex ("Texture", 2D) = "white" {}_DissolveDirection ("消融方向",Vector) = (0,0,0,0)_InverseDir("反向",Range(-1,1)) = 1[HDR]_Color ("顏色",Color) = (1,1,1,1)_Width ("寬度",Range(0.0,1.0)) = 0.1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{Cull offCGPROGRAM#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float3 objPos : TEXCOORD1;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;half4 _DissolveDirection;fixed _InverseDir;fixed4 _Color;fixed _Width;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.objPos = v.vertex;return o;}fixed4 frag (v2f i) : SV_Target{//_DissolveDirection.y = sin(_Time.y);half3 dis = i.objPos.xyz - _DissolveDirection.xyz;half discardCondition = _InverseDir * dis.y;clip(discardCondition);fixed4 texColor = tex2D(_MainTex, i.uv);fixed4 col = fixed4(texColor.rgb,1.0);if(discardCondition < _Width){ return _Color * col; }return col;}ENDCG}} }最終效果:
 
2021/8/15 更新:
 在網上找到了puppet_master大佬的文章,他的文章深度和廣度真的不是我這種萌新能比的。
 參考文章鏈接,作者:puppet_master
 這是看過他的文章后改進的代碼:
其中,sign函數(shù)長這樣:
 
 當x>0,sign(x)=1;
 當x=0,sign(x)=0;
 當x<0, sign(x)=-1;
 它用這里是為了保證顏色邊界鮮明。如果沒有sign函數(shù)的處理它會變成這樣:
 
 (這里的材質參數(shù)寬度值為0.35,顏色的邊界都如此不明顯。而前面的圖寬度值僅為0.1)
總結
以上是生活随笔為你收集整理的【unity shader】unity游戏特效-仿《黑暗欺骗》模型消融消失效果的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 函数的值域【基础辅导和中阶辅导】
- 下一篇: 外网访问redis cluster的大坑
