Unity Shader-紋理采樣流光,溶解茴扁,隱身效果(轉(zhuǎn))

簡介

今天來研究幾個效果铃岔,最近比較忙,所以來弄幾個比較簡單的效果玩一下峭火。不過也是游戲中常用的一些效果毁习,流光效果,按照方向的溶解效果躲胳。其實(shí)這幾個效果主要運(yùn)用的就是世界空間坐標(biāo)或者模型空間坐標(biāo)用于采樣的一個方法蜓洪,總之就是有些非主流的紋理采樣方式纤勒。不多說坯苹,下面進(jìn)入正題。

流光效果

首先來看一下流光效果摇天。流光效果是一個非常常見的效果粹湃,不僅僅是游戲,一些廣告之類的也都會有這種效果泉坐。流光的原理還是比較簡單的:首先就是需要一張流光圖为鳄,這張流光圖的大部分都是黑色,然后有一條亮線腕让,然后我們在采樣的時候孤钦,最終輸出疊加上這張圖的采樣值歧斟,并根據(jù)時間調(diào)整采樣的UV就可以有流光的效果啦。下面是一個比較簡單的流光效果實(shí)現(xiàn):

//流光效果

//by:puppet_master

//2017.7.29

Shader "ApcShader/FlashEffect"

{

Properties

{

_MainTex("MainTex(RGB)", 2D) = "white" {}

_FlashTex("FlashTex", 2D) = "black" {}

_FlashColor("FlashColor",Color) = (1,1,1,1)

_FlashSpeedX("FlashSpeedX", Range(-5, 5)) = 0

_FlashSpeedY("FlashSpeedY", Range(-5, 5)) = 0.5

_FlashFactor ("FlashFactor", Range(0, 5)) = 1

}

CGINCLUDE

#include "Lighting.cginc"

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _FlashTex;

uniform fixed4 _FlashColor;

uniform fixed _FlashSpeedX;

uniform fixed _FlashSpeedY;

uniform fixed _FlashFactor;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : NORMAL;

float2 uv : TEXCOORD0;

float3 worldLight : 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 = UnityObjectToWorldNormal(v.normal);

o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

half3 normal = normalize(i.worldNormal);

half3 light = normalize(i.worldLight);

fixed diff = max(0, dot(normal, light));

fixed4 albedo = tex2D(_MainTex, i.uv);

//通過時間將采樣flash的uv進(jìn)行偏移

half2 flashuv = i.uv + half2(_FlashSpeedX, _FlashSpeedY) * _Time.y;

fixed4 flash = tex2D(_FlashTex, flashuv) * _FlashColor * _FlashFactor;

fixed4 c;

//將flash圖與原圖疊加

c.rgb = diff * albedo + flash.rgb;

c.a = 1;

return c;

}

ENDCG

SubShader

{

Pass

{

Tags{ "RenderType" = "Opaque" }

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

shader比較簡單偏形,flashuv是隨著時間逐漸增大的静袖,這個值肯定會大于1,而正常紋理的范圍是0-1俊扭,所以队橙,要想讓貼圖在采樣時大于0-1也有效果,我們就必須要把貼圖的WrapMode設(shè)置為Repeat萨惑,否則當(dāng)這個值大于1之后捐康,邊緣就被截?cái)嗔耍覀円簿筒粫吹搅鞴庑Ч擞拱W⒁饨庾埽鞴獾馁N圖是一個方向,采樣uv偏移是另一個方向姐仅,比如我的流光圖是水平方向的倾鲫,那么流光運(yùn)動的方向就是豎直方向,效果如下面動圖所示:

更通用的流光效果

我們把流光shader用于一個3D模型萍嬉,效果卻并不像我們預(yù)期的那樣會出現(xiàn)一條掃描線乌昔,而是亮起來的地方讓人捉摸不透,如下圖所示:

為什么會這樣呢壤追?其實(shí)主要是我們采樣的方式導(dǎo)致的磕道,正常的紋理采樣都是使用uv坐標(biāo)進(jìn)行采樣的,也就是說這個坐標(biāo)是與模型有關(guān)行冰,在這個模型上這個點(diǎn)需要采樣紋理的哪部分是由美術(shù)展uv時決定的溺蕉。我們?nèi)绻胾v來進(jìn)行采樣,對于正常的diffuse貼圖或者法線貼圖等是對的悼做,但是對于一些其他特殊的效果疯特,uv采樣不能達(dá)到我們的需求了,所以我們就需要研究一下肛走,用一個其他的東東作為采樣的坐標(biāo)漓雅,這也是本篇文章主要研究的內(nèi)容。

如果不用uv進(jìn)行采樣朽色,那么我們就需要一些其他的值作為采樣值邻吞,之前的文章我們也有使用過類似的方法,比如在熱空氣扭曲效果中我們使用了屏幕空間采樣葫男,采樣時計(jì)算該點(diǎn)在屏幕空間的坐標(biāo)值反過來去采樣全屏GrabPass圖抱冷。不過這里我們不需要屏幕空間,畢竟這樣的話這個流動效果就會隨著我們觀察的角度而變化梢褐,所以我們選擇用世界空間采樣:

//流光效果

//by:puppet_master

//2017.7.30

Shader "ApcShader/FlashEffect"

{

Properties

{

_MainTex("MainTex(RGB)", 2D) = "white" {}

_FlashTex("FlashTex", 2D) = "black" {}

_FlashColor("FlashColor",Color) = (1,1,1,1)

_FlashFactor("FlashFactor", Vector) = (0, 1, 0.5, 0.5)

_FlashStrength ("FlashStrength", Range(0, 5)) = 1

}

CGINCLUDE

#include "Lighting.cginc"

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _FlashTex;

uniform fixed4 _FlashColor;

//改為一個vector4旺遮,減少傳參次數(shù)消耗

uniform fixed4 _FlashFactor;

uniform fixed _FlashStrength;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : NORMAL;

float2 uv : TEXCOORD0;

float3 worldLight : TEXCOORD1;

float4 worldPos : TEXCOORD2;

};

v2f vert(appdata_base v)

{

v2f o;

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

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

//頂點(diǎn)轉(zhuǎn)化到世界空間

o.worldPos = mul(unity_ObjectToWorld, v.vertex);

o.worldNormal = UnityObjectToWorldNormal(v.normal);

o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

half3 normal = normalize(i.worldNormal);

half3 light = normalize(i.worldLight);

fixed diff = max(0, dot(normal, light));

fixed4 albedo = tex2D(_MainTex, i.uv);

//通過時間偏移世界坐標(biāo)對flashTex進(jìn)行采樣

half2 flashuv = i.worldPos.xy * _FlashFactor.zw + _FlashFactor.xy * _Time.y;

fixed4 flash = tex2D(_FlashTex, flashuv) * _FlashColor * _FlashStrength;

fixed4 c;

//將flash圖與原圖疊加

c.rgb = diff * albedo + flash.rgb;

c.a = 1;

return c;

}

ENDCG

SubShader

{

Pass

{

Tags{ "RenderType" = "Opaque" }

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

好了赵讯,下面我們找個帥帥噠模型,看一下修改之后的流光效果:

然后我們也可以換一張貼圖耿眉,再調(diào)整一下參數(shù)瘦癌,讓流光換個方向:

按照方向消失或重現(xiàn)效果

我們再來看一個用模型空間坐標(biāo)作為采樣的uv的栗子,也是一種比較好玩的效果跷敬。比如我們需要一個模型身體按照一定的方向逐漸消失讯私,直至全部消失掉的一個效果。下面說一下思路西傀,與世界空間采樣的流光效果一樣斤寇,我們在vertex階段記錄一下vertex坐標(biāo),傳遞給fragment階段拥褂,在fragment階段用這個值和一個設(shè)定好的閾值進(jìn)行比較娘锁,不滿足條件的像素點(diǎn)直接discard,逐漸調(diào)整閾值饺鹃,就可以得到讓模型按照某個方向消失的效果了莫秆。代碼如下:

//按照方向消失的效果

//by:puppet_master

//2017.8.10

Shader "ApcShader/DissolveEffectX"

{

Properties

{

_MainTex("MainTex(RGB)", 2D) = "white" {}

_DissolveVector("DissolveVector", Vector) = (0,0,0,0)

}

CGINCLUDE

#include "Lighting.cginc"

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform float4 _DissolveVector;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : NORMAL;

float2 uv : TEXCOORD0;

float3 worldLight : TEXCOORD1;

float4 objPos : TEXCOORD2;

};

v2f vert(appdata_base v)

{

v2f o;

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

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

//頂點(diǎn)轉(zhuǎn)化到世界空間

o.objPos = v.vertex;

o.worldNormal = UnityObjectToWorldNormal(v.normal);

o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

half3 normal = normalize(i.worldNormal);

half3 light = normalize(i.worldLight);

fixed diff = max(0, dot(normal, light));

fixed4 albedo = tex2D(_MainTex, i.uv);

//不滿足條件的discard

clip(i.objPos.xyz - _DissolveVector.xyz);

fixed4 c;

c.rgb = diff * albedo;

c.a = 1;

return c;

}

ENDCG

SubShader

{

Pass

{

Tags{ "RenderType" = "Opaque" }

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

還是上面的模型,我們逐漸調(diào)整X,Y,Z軸三個方向的閾值悔详,就可以有逐漸消失或者出現(xiàn)的效果啦镊屎,如下面動圖所示:

在這里,我們沒有像流光效果那樣使用世界空間坐標(biāo)采樣茄螃,而是使用了模型空間坐標(biāo)采樣缝驳,其實(shí)還可以使用屏幕空間坐標(biāo)或者視口空間坐標(biāo)采樣等等,幾種方式各有各的優(yōu)點(diǎn)和缺點(diǎn)归苍。使用世界空間采樣用狱,消失的方向是絕對的,比如是從上向下拼弃,那么這個模型如果趴在地上夏伊,消失的方向就會是從模型后背到前胸的方向,而且坐標(biāo)閾值會隨著模型處于世界中的位置不同而不同吻氧;使用模型空間采樣溺忧,消失的方向與模型本身有關(guān),比如站著的話消失方向是從頭到腳医男,那么趴著也是從頭到腳砸狞,而且坐標(biāo)的閾值與模型的高矮胖瘦有關(guān)(也與模型的原點(diǎn)位置有點(diǎn)關(guān)系)捻勉;使用屏幕空間采樣的話镀梭,消失的方向就可能會與我們觀察的方向有關(guān),這種可能不太可控踱启。

還有一個小問題报账,其實(shí)上圖中的例子里面研底,模型從上到下,理想情況應(yīng)該是調(diào)整Y軸透罢,不過例子里面調(diào)整的確實(shí)X軸榜晦,原因應(yīng)該與Unity導(dǎo)入之后會繞著X軸旋轉(zhuǎn)90度有關(guān),也就是原本在max里面的Y軸變成Unity里面的X軸羽圃。

下面乾胶,我們再看一下增加了邊緣高亮的消失效果,為了讓模消失的型邊緣高亮朽寞,我們通過將用于clip的factor值與另一個高亮閾值值進(jìn)行比較识窿,如果factor小于高亮閾值,則返回一個高亮的顏色值脑融,否則正常渲染喻频。這樣模型就總共有三種顯示狀態(tài):clip狀態(tài),高亮狀態(tài)肘迎,正常狀態(tài)甥温。代碼如下:

//消失效果

//by:puppet_master

//2017.8.11

Shader "ApcShader/DissolveEffectX"

{

Properties{

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

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

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

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

_DissolveThreshold("DissolveThreshold", Float) = 0

}

CGINCLUDE

#include "Lighting.cginc"

uniform fixed4 _Diffuse;

uniform fixed4 _DissolveColor;

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform float _ColorFactor;

uniform float _DissolveThreshold;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : TEXCOORD0;

float2 uv : TEXCOORD1;

float4 objPos : TEXCOORD2;

};

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);

o.objPos = v.vertex;

return o;

}

fixed4 frag(v2f i) : SV_Target

{

float factor = i.objPos.x - _DissolveThreshold;

clip(factor);

//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;

//等價(jià)于下面注釋代碼的操作

fixed lerpFactor = saturate(sign(_ColorFactor - factor));

return lerpFactor * _DissolveColor + (1 - lerpFactor) * fixed4(color, 1);

/*

if (factor < _ColorFactor)

{

return _DissolveColor;

}

return fixed4(color, 1);*/

}

ENDCG

SubShader

{

Tags{ "RenderType" = "Opaque" }

Pass

{

//不讓模型穿幫,關(guān)掉了背面裁剪

Cull Off

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

這一次我們只讓模型在上下方向上逐漸消失妓布,調(diào)整ColorFactor可以控制高亮區(qū)域的高度:

溶解效果進(jìn)階版

之前的文章里姻蚓,我們研究過溶解效果,不過這個效果是基于全身的匣沼,我們來嘗試一下史简,把上面按照方向消失的效果與溶解效果結(jié)合起來,做成一個按照某個方向逐漸溶解的效果肛著。要得到隨機(jī)的溶解效果圆兵,我們需要采樣一張?jiān)肼晥D,然后在原本會直接clip掉的部分根據(jù)采樣的噪聲圖進(jìn)行clip枢贿,就能得到按照方向的溶解效果啦殉农。

//溶解效果

//by:puppet_master

//2017.8.11

Shader "ApcShader/DissolveEffectX"

{

Properties{

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

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

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

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

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

_DissolveSpeedFactor("DissolveSpeed", Range(0,5)) = 2

_DissolveControl("ColorFactorB", Float) = 0

}

CGINCLUDE

#include "Lighting.cginc"

uniform fixed4 _Diffuse;

uniform fixed4 _DissolveColor;

uniform sampler2D _MainTex;

uniform float4 _MainTex_ST;

uniform sampler2D _DissolveMap;

uniform float _DissolveThreshold;

uniform float _DissolveSpeedFactor;

uniform float _DissolveControl;

struct v2f

{

float4 pos : SV_POSITION;

float3 worldNormal : TEXCOORD0;

float2 uv : TEXCOORD1;

float4 objPos : TEXCOORD2;

};

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);

o.objPos = v.vertex;

return o;

}

fixed4 frag(v2f i) : SV_Target

{

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

//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;

float factor = i.objPos.x - _DissolveControl;

if(factor < 0)

{

clip(_DissolveThreshold - dissolve.r * abs(factor) * _DissolveSpeedFactor);

}

return fixed4(color, 1);

}

ENDCG

SubShader

{

Tags{ "RenderType" = "Opaque" }

Pass

{

Cull Off

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

ENDCG

}

}

FallBack "Diffuse"

}

效果如下:

當(dāng)然,也可以參考之前溶解效果局荚,增加溶解描邊高亮的效果:

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末超凳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子耀态,更是在濱河造成了極大的恐慌轮傍,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件首装,死亡現(xiàn)場離奇詭異创夜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仙逻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門驰吓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涧尿,“玉大人,你說我怎么就攤上這事檬贰」昧” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵翁涤,是天一觀的道長桥言。 經(jīng)常有香客問我,道長葵礼,這世上最難降的妖魔是什么限书? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮章咧,結(jié)果婚禮上倦西,老公的妹妹穿的比我還像新娘。我一直安慰自己赁严,他們只是感情好扰柠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疼约,像睡著了一般卤档。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上程剥,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天劝枣,我揣著相機(jī)與錄音,去河邊找鬼织鲸。 笑死舔腾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搂擦。 我是一名探鬼主播稳诚,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瀑踢!你這毒婦竟也來了扳还?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤橱夭,失蹤者是張志新(化名)和其女友劉穎氨距,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棘劣,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俏让,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舆驶。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡橱健,死狀恐怖而钞,靈堂內(nèi)的尸體忽然破棺而出沙廉,到底是詐尸還是另有隱情,我是刑警寧澤臼节,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布撬陵,位于F島的核電站,受9級特大地震影響网缝,放射性物質(zhì)發(fā)生泄漏巨税。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一粉臊、第九天 我趴在偏房一處隱蔽的房頂上張望草添。 院中可真熱鬧,春花似錦扼仲、人聲如沸远寸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驰后。三九已至,卻和暖如春矗愧,著一層夾襖步出監(jiān)牢的瞬間灶芝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工唉韭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夜涕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓属愤,卻偏偏與公主長得像钠乏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子春塌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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