Unity Shader-死亡溶解效果(轉(zhuǎn))

簡介

游戲里面角色死亡的時(shí)候诚隙,有很多方式可以表現(xiàn)人物死亡效果献雅。最簡單粗暴的昵仅,播放完死亡動畫直接刪除或者直接Y軸逐漸降低斗遏,沉到地下;比較好的死亡效果就是今天要研究的這種效果-死亡溶解梅猿。個(gè)人印象比較深刻的就是《生化危機(jī)6》里面的克里斯篇氓辣,里面的功夫喪尸掛掉之后都是會有一個(gè)類似的死亡溶解效果。不過《生化危機(jī)6》這種3A大作的效果肯定不僅僅是一個(gè)shader能做出來的袱蚓,還配合了粒子做出了消散以及著火的效果钞啸。

趕腳一般學(xué)習(xí)shader的童鞋,都會研究一下這個(gè)東東....畢竟這個(gè)效果灰常常用喇潘。今天体斩,我也來研究一下死亡溶解效果的實(shí)現(xiàn)。

基本溶解效果

溶解颖低,也就是讓這個(gè)模型逐漸消失絮吵。那么,最簡單的忱屑,直接讓這個(gè)像素的Fragment Shader操作discard蹬敲,這個(gè)像素就消失了。然后莺戒,我們要做的就是讓這個(gè)溶解的對象一部分消失伴嗡,另一部分存在,所以从铲,這個(gè)時(shí)候我們就需要一個(gè)Mask圖進(jìn)行控制瘪校,我們采樣這張Mask圖,就可以得到這個(gè)像素點(diǎn)當(dāng)前的Mask值,然后用這個(gè)Mask值與我們設(shè)定的一個(gè)閾值來進(jìn)行比較阱扬,小于閾值的部分discard泣懊,大于的部分正常計(jì)算。最終麻惶,我們將這個(gè)閾值從0逐漸增加到1馍刮,就可以實(shí)現(xiàn)模型的一部分像素先消失,直至整個(gè)模型完全消失的效果用踩。

簡單的原理解釋完了渠退,先來一發(fā)基本的溶解效果:

//溶解效果

//by:puppet_master

//2017.5.18

Shader "ApcShader/DissolveEffect"

{

Properties{

_Diffuse("Diffuse", Color) = (1,1,1,1)

_MainTex("Base 2D", 2D) = "white"{}

_DissolveMap("DissolveMap", 2D) = "white"{}

_DissolveThreshold("DissolveThreshold", Range(0,1)) = 0

}

CGINCLUDE

#include "Lighting.cginc"

uniform fixed4 _Diffuse;

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _DissolveMap;

uniform float _DissolveThreshold;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : TEXCOORD0;

float2 uv : TEXCOORD1;

};

v2f vert(appdata_base v)

{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

//采樣Dissolve Map

fixed4 dissolveValue = tex2D(_DissolveMap, i.uv);

//小于閾值的部分直接discard

if (dissolveValue.r < _DissolveThreshold)

{

discard;

}

//Diffuse + Ambient光照計(jì)算

fixed3 worldNormal = normalize(i.worldNormal);

fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

fixed3 lambert = saturate(dot(worldNormal, worldLightDir));

fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;

fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;

return fixed4(color, 1);

}

ENDCG

SubShader

{

Tags{ "RenderType" = "Opaque" }

Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

最近找了個(gè)比較帥氣的模型,先爆個(gè)照(開啟了BloomDepth Of Field):

然后脐彩,讓偶們把它溶解掉碎乃,這里我們直接使用了一張?jiān)肼晥D,最簡單的雪花點(diǎn)的那種就可以啦惠奸,逐漸調(diào)大Dissolve Threshold梅誓,就可以了:

增加過渡的溶解效果

上面的溶解效果感覺就像被打成篩子一樣...木有明顯的過渡,感覺效果不是很好佛南。下面寫一個(gè)增加了過渡的溶解效果梗掰,讓被溶解的部分邊緣變成我們設(shè)置的顏色,為了增加豐富性嗅回,我們可以增加兩個(gè)過渡顏色及穗。分別設(shè)置兩個(gè)閾值。首先是當(dāng)閾值小于顏色A閾值的時(shí)候绵载,返回顏色A埂陆,閾值小于顏色B的時(shí)候,返回顏色B娃豹,否則返回原始顏色焚虱。shader代碼如下:

//溶解效果

//by:puppet_master

//2017.5.18

Shader "ApcShader/DissolveEffect"

{

Properties{

_Diffuse("Diffuse", Color) = (1,1,1,1)

_DissolveColorA("Dissolve Color A", Color) = (0,0,0,0)

_DissolveColorB("Dissolve Color B", Color) = (1,1,1,1)

_MainTex("Base 2D", 2D) = "white"{}

_DissolveMap("DissolveMap", 2D) = "white"{}

_DissolveThreshold("DissolveThreshold", Range(0,1)) = 0

_ColorFactorA("ColorFactorA", Range(0,1)) = 0.7

_ColorFactorB("ColorFactorB", Range(0,1)) = 0.8

}

CGINCLUDE

#include "Lighting.cginc"

uniform fixed4 _Diffuse;

uniform fixed4 _DissolveColorA;

uniform fixed4 _DissolveColorB;

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _DissolveMap;

uniform float _DissolveThreshold;

uniform float _ColorFactorA;

uniform float _ColorFactorB;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : TEXCOORD0;

float2 uv : TEXCOORD1;

};

v2f vert(appdata_base v)

{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

//采樣Dissolve Map

fixed4 dissolveValue = tex2D(_DissolveMap, i.uv);

//小于閾值的部分直接discard

if (dissolveValue.r < _DissolveThreshold)

{

discard;

}

//Diffuse + Ambient光照計(jì)算

fixed3 worldNormal = normalize(i.worldNormal);

fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

fixed3 lambert = saturate(dot(worldNormal, worldLightDir));

fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;

fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;

//這里為了比較方便,直接用color和最終的邊緣lerp了

float lerpValue = _DissolveThreshold / dissolveValue.r;

if (lerpValue > _ColorFactorA)

{

if (lerpValue > _ColorFactorB)

return _DissolveColorB;

return _DissolveColorA;

}

return fixed4(color, 1);

}

ENDCG

SubShader

{

Tags{ "RenderType" = "Opaque" }

Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

上面的模型懂版,我們配置一個(gè)雷電類型的溶解效果鹃栽,兩個(gè)顏色值分別給白色和藍(lán)色。然后噪聲圖給一張過渡更加柔和一些的躯畴,如下圖:

來一張動圖民鼓,先逐漸增大溶解閾值,就是溶解效果私股;然后再減小閾值摹察,就是閃亮登場的效果:

上面的shader雖然比較容易理解,我們直接用了兩個(gè)if進(jìn)行判斷的倡鲸。不過感覺shader里面的分支還是盡量少,畢竟如果有動態(tài)分支(編譯期的有些是可以自動優(yōu)化掉的黄娘,比如我們寫的固定次數(shù)的循環(huán)峭状,這種應(yīng)該是會直接在編譯期展開了)克滴,運(yùn)行時(shí)的shader有動態(tài)分支的話,是會先執(zhí)行一遍A分支优床,然后再去執(zhí)行B分支劝赔,效率就下去了,可以參考知乎大神們的討論胆敞。so...我們還是老老實(shí)實(shí)地寫一發(fā)用值來判斷的(除了discard):

//溶解效果

//by:puppet_master

//2017.5.19

Shader "ApcShader/DissolveEffect"

{

Properties{

_Diffuse("Diffuse", Color) = (1,1,1,1)

_DissolveColor("Dissolve Color", Color) = (0,0,0,0)

_DissolveEdgeColor("Dissolve Edge Color", Color) = (1,1,1,1)

_MainTex("Base 2D", 2D) = "white"{}

_DissolveMap("DissolveMap", 2D) = "white"{}

_DissolveThreshold("DissolveThreshold", Range(0,1)) = 0

_ColorFactor("ColorFactor", Range(0,1)) = 0.7

_DissolveEdge("DissolveEdge", Range(0,1)) = 0.8

}

CGINCLUDE

#include "Lighting.cginc"

uniform fixed4 _Diffuse;

uniform fixed4 _DissolveColor;

uniform fixed4 _DissolveEdgeColor;

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _DissolveMap;

uniform float _DissolveThreshold;

uniform float _ColorFactor;

uniform float _DissolveEdge;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : TEXCOORD0;

float2 uv : TEXCOORD1;

};

v2f vert(appdata_base v)

{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

//采樣Dissolve Map

fixed4 dissolveValue = tex2D(_DissolveMap, i.uv);

//小于閾值的部分直接discard

if (dissolveValue.r < _DissolveThreshold)

{

discard;

}

//Diffuse + Ambient光照計(jì)算

fixed3 worldNormal = normalize(i.worldNormal);

fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

fixed3 lambert = saturate(dot(worldNormal, worldLightDir));

fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;

fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;

//優(yōu)化版本着帽,盡量不在shader中用分支判斷的版本,但是代碼很難理解啊....

float percentage = _DissolveThreshold / dissolveValue.r;

//如果當(dāng)前百分比 - 顏色權(quán)重 - 邊緣顏色

float lerpEdge = sign(percentage - _ColorFactor - _DissolveEdge);

//貌似sign返回的值還得saturate一下,否則是一個(gè)很奇怪的值

fixed3 edgeColor = lerp(_DissolveEdgeColor.rgb, _DissolveColor.rgb, saturate(lerpEdge));

//最終輸出顏色的lerp值

float lerpOut = sign(percentage - _ColorFactor);

//最終顏色在原顏色和上一步計(jì)算的顏色之間差值(其實(shí)經(jīng)過saturate(sign(..))的lerpOut應(yīng)該只能是0或1)

fixed3 colorOut = lerp(color, edgeColor, saturate(lerpOut));

return fixed4(colorOut, 1);

}

ENDCG

SubShader

{

Tags{ "RenderType" = "Opaque" }

Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

效果與上面基本一致移层,所以這次我們換個(gè)顏色再來一發(fā)燃燒溶解效果仍翰,把顏色調(diào)整成黃色和紅色:

再來一發(fā)動圖:

不僅僅是溶解,還要灰飛煙滅

轉(zhuǎn)自:http://m.blog.csdn.net/puppet_master/article/details/72455945

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末观话,一起剝皮案震驚了整個(gè)濱河市予借,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌频蛔,老刑警劉巖灵迫,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異晦溪,居然都是意外死亡瀑粥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門三圆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狞换,“玉大人,你說我怎么就攤上這事嫌术“С海” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵度气,是天一觀的道長割按。 經(jīng)常有香客問我,道長磷籍,這世上最難降的妖魔是什么适荣? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮院领,結(jié)果婚禮上弛矛,老公的妹妹穿的比我還像新娘。我一直安慰自己比然,他們只是感情好丈氓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般万俗。 火紅的嫁衣襯著肌膚如雪湾笛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天闰歪,我揣著相機(jī)與錄音嚎研,去河邊找鬼。 笑死库倘,一個(gè)胖子當(dāng)著我的面吹牛临扮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播教翩,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼杆勇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了迂曲?” 一聲冷哼從身側(cè)響起靶橱,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎路捧,沒想到半個(gè)月后关霸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杰扫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年队寇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片章姓。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡佳遣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凡伊,到底是詐尸還是另有隱情零渐,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布系忙,位于F島的核電站诵盼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏银还。R本人自食惡果不足惜风宁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛹疯。 院中可真熱鬧戒财,春花似錦、人聲如沸捺弦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至骂际,卻和暖如春疗琉,著一層夾襖步出監(jiān)牢的瞬間冈欢,已是汗流浹背歉铝。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凑耻,地道東北人太示。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像香浩,于是被迫代替她去往敵國和親类缤。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容