【unity shader】unity游戏特效-仿《黑暗欺骗》模型消融消失效果
閑暇時(shí)看紙魚實(shí)況,看到游戲中有個(gè)這樣的效果:
視頻鏈接,UP主:薄海紙魚
臥槽,放慢再看一遍:
可以看到,玩家在惹怒Boss后,所有的椅子瞬間消失,Boss戰(zhàn)還未開打就已經(jīng)逼格拉滿了。給玩家留下震撼的印象以及實(shí)力差所帶來的壓抑和絕望。
太帥了!這個(gè)效果我也想要!
實(shí)現(xiàn)思路
仔細(xì)觀察椅子消失瞬間:
想要實(shí)現(xiàn)這個(gè)效果有三個(gè)要求:
一是要剔除片元來達(dá)到物體消融的效果。
二是在剔除片元的操作里設(shè)定剔除的條件。
三是在剔除的邊緣上顏色高亮
看完了馮樂樂女神的書,我們就知道解決第一個(gè)問題需要用到的就是clip函數(shù),該函數(shù)可以剔除指定的片元
clip(x) ///相當(dāng)于下面這句 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,否則正面剔除一半時(shí)玩家會(huì)發(fā)現(xiàn)后面早空了。
可以看見關(guān)鍵代碼在這兩句
half dis = i.objPos.y - _DissolveDirection.y; clip(dis);clip()剔除掉我們不需要的片元。而dis的那句話是用物體對(duì)象的模型坐標(biāo)的y軸與我們給的一個(gè)三維矢量的y軸進(jìn)行相減計(jì)算,軸上相減的結(jié)果小于0的部分片元就會(huì)被剔除掉。
還可以拓展成下面這樣:
half3 dis = i.objPos.xyz - _DissolveDirection.xyz; half discardCondition = * dis.y; clip(discardCondition);如果想要左右方向的消除,就把dis.y改為x即可。
但要注意,這個(gè)是利用的模型坐標(biāo)系進(jìn)行計(jì)算。如果一個(gè)模型(假設(shè)是人體模型)。他模型坐標(biāo)系的Y軸不是向上而是向前。那你就不能用y軸上的計(jì)算來實(shí)現(xiàn)從頭到腳的順序消失。
你可以考慮用世界坐標(biāo)系解決,世界坐標(biāo)系XYZ軸方向是不會(huì)變的,但同樣會(huì)引入新的問題——物體所在的位置會(huì)影響計(jì)算結(jié)果。這個(gè)問題我目前還沒有比較好的解決方法,看看以后有沒有好兄弟來幫個(gè)忙。
OK,這是目前的效果:
emmmmmm,其實(shí)我想要你們從頭的方向開始消失,而不是腳。。。
這里我用了一個(gè)笨辦法,引入一個(gè)新int屬性,用1和-1來控制消融的方向;想要反方向?乘個(gè)負(fù)一就好。
OK,前兩個(gè)問題搞定了,現(xiàn)在需要解決高亮的問題了。
咱們前面不是利用兩個(gè)矢量相減計(jì)算嗎?小于0的部分被剔除掉了。那我們就再設(shè)定一個(gè)小于某值但大于0的范圍,相減結(jié)果在這個(gè)范圍內(nèi)的,返回的顏色值要發(fā)生改變。
效果如下:
圖中的_width值設(shè)為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 更新:
在網(wǎng)上找到了puppet_master大佬的文章,他的文章深度和廣度真的不是我這種萌新能比的。
參考文章鏈接,作者:puppet_master
這是看過他的文章后改進(jìn)的代碼:
其中,sign函數(shù)長這樣:
當(dāng)x>0,sign(x)=1;
當(dāng)x=0,sign(x)=0;
當(dāng)x<0, sign(x)=-1;
它用這里是為了保證顏色邊界鮮明。如果沒有sign函數(shù)的處理它會(huì)變成這樣:
(這里的材質(zhì)參數(shù)寬度值為0.35,顏色的邊界都如此不明顯。而前面的圖寬度值僅為0.1)
總結(jié)
以上是生活随笔為你收集整理的【unity shader】unity游戏特效-仿《黑暗欺骗》模型消融消失效果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 函数的值域【基础辅导和中阶辅导】
- 下一篇: 外网访问redis cluster的大坑