文章目錄
- 前言
- 一、實(shí)現(xiàn)過(guò)程
- 總結(jié)
- 參考
前言
本文主要介紹用unity實(shí)現(xiàn)雨水滴到屏幕的效果,文章介紹的是基礎(chǔ)實(shí)現(xiàn),讀完這篇文章再去實(shí)現(xiàn)復(fù)雜效果會(huì)更得心應(yīng)手些。我們先看更高級(jí)效果的圖片:
一、實(shí)現(xiàn)過(guò)程
1.代碼
先直接上代碼,后面再做介紹:
Shader "Unlit/RainDrop"
{Properties{_MainTex ("Texture", 2D) = "white" {}_Size("Size", Range(0, 100)) = 1.0_T("Time", Float) = 1.0_Distortion("Distortion", Float) = -5_Blur("Blur", Range(0, 1)) = 0.0}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;half _Size;half _T;half _Distortion;half _Blur;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}// 求偽隨機(jī)數(shù)half N21(half2 p){p = frac(p * half2(123.34, 345.45));p += dot(p, p + 34.345);return frac(p.x + p.y);} half3 layer(half2 UV, half T){half t = fmod( _Time.y + T, 3600);half4 col = half4(0, 0, 0, 1.0);half aspect = half2(2, 1);half2 uv = UV * _Size * aspect;uv.y += t * 0.25;half2 gv = frac(uv) - 0.5;//-0.5,調(diào)整原點(diǎn)為中間half2 id = floor(uv);half n = N21(id); // 0 1t += n * 6.2831; //2PIhalf w = UV.y * 10;half x = (n - 0.5) * 0.8;x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect; //- half2(x,y) 為了移動(dòng)half drop = smoothstep(0.05, 0.03, length(dropPos));half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8;half trail = smoothstep(0.03, 0.01, length(trailPos));half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);// 拖尾小水滴慢慢被拖掉了fogTrail *= smoothstep(0.5, y, gv.y);// 拖尾小水滴漸變消失fogTrail *= smoothstep(0.05, 0.04, abs(dropPos.x));trail *= fogTrail;//col += fogTrail * 0.5;//col += trail;//col += drop;//if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線half2 offset = drop * dropPos + trail * trailPos;return half3(offset, fogTrail);}half4 frag (v2f i) : SV_Target{half3 drops = layer(i.uv, _T);drops += layer(i.uv * 1.25 + 7.52, _T);drops += layer(i.uv * 1.35 + 1.54, _T);drops += layer(i.uv * 1.57 - 7.52, _T); half blur = _Blur * 7 * (1 - drops.z);half4 col = tex2Dlod(_MainTex, half4(i.uv + drops.xy * _Distortion, 0, blur));return col;}ENDCG}}}
下圖顯示了上面那段代碼的效果,讀者可自行在unity中先貼這段代碼看,后面會(huì)做詳細(xì)解析:
2.代碼分步解析
下面是實(shí)現(xiàn)步驟:
【1】先將uv平鋪多次,為后面實(shí)現(xiàn)多個(gè)雨滴效果。
直接貼片元著色器代碼:
half4 frag (v2f i) : SV_Target{half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(1, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間col.rg = gv;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
下圖顯示了上面那段代碼的效果:
說(shuō)明:A為從左下角的原點(diǎn)調(diào)整為中間的情況, _Size 為平鋪多次的情況,讀者可邊看邊在untiy上操作。
half2 aspect = half(2, 1);//長(zhǎng)寬比
設(shè)置長(zhǎng)寬比為2:1后,得到效果:
【2】實(shí)現(xiàn)多個(gè)雨滴效果
直接貼片元著色器代碼:
half4 frag (v2f i) : SV_Target{half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half drop = smoothstep(0.05, 0.03, length(gv));//畫(huà)圓, length(gv),可以理解為半徑col += drop;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
下圖顯示了上面那段代碼的效果:
先附上smoothstep的解析,后續(xù)有時(shí)間會(huì)發(fā)文介紹glsl相關(guān)函數(shù)的理解,以及如何使用這些函數(shù)去實(shí)現(xiàn)復(fù)雜的效果。以下是smoothstep的解析:
我們先打開(kāi)網(wǎng)址
Desmos | 圖形計(jì)算器?www.desmos.com
,輸入如圖所示:
smoothstep的公式就是s = k^2*(3 - 2k), 圖上所示就是smoothstep(0.4, 0.6, x), 如果是反過(guò)來(lái)就是smoothstep(0.6, 0.4, x), 得到的就是如圖所示:
我們可以直接在
Shadertoy BETA?www.shadertoy.com
上演示輸入如圖所示代碼:
0.2 ->0.0 可以理解為簡(jiǎn)單的反向操作如圖所示:
【4】水滴移動(dòng)
直接貼片元著色器代碼:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half x = 0;half y = sin(t);//水珠是上下來(lái)回移動(dòng)的half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑col += drop;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
改動(dòng)下代碼,讓水滴是往下移動(dòng)的:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half x = 0;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑col += drop;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
讀者需要按照步驟去實(shí)現(xiàn),更能理解算法表現(xiàn)的效果,幫助理解。上述代碼中(2)得到的函數(shù)圖是:
讀者可自行控制算法,調(diào)出更好的效果。
【4】水滴拖尾效果,拖尾水滴滑下
1、先畫(huà)一個(gè)拖尾水滴,代碼:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half x = 0;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf trail = smoothstep(0.03, 0.01, length(gv));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑col += drop;col += trail;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
下圖顯示了上面那段代碼的效果:
2、再計(jì)算移動(dòng),代碼:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half x = 0;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑col += drop;col += trail;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
下圖顯示了上面那段代碼的效果:
3、接下來(lái)我們將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失,代碼:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half x = 0;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑trail *= smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失col += drop;col += trail;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
下圖顯示了上面那段代碼的效果:
3、然后將水滴做個(gè)漸變,從上到下從無(wú)到有,代碼:
... ...
half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑
trail *= smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失
trail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5
col += drop;
col += trail;
... ...
下圖顯示了上面那段代碼的效果:
【5】水滴做偏移,得到一種失真的效果,這時(shí)我們需要同時(shí)對(duì)x,y做偏移
1、同樣,先貼上簡(jiǎn)單的效果,先改變下水滴的形狀,代碼:
half4 frag (v2f i) : SV_Target{... ... half x = 0;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)y -= gv.x * gv.x;//改變水滴形狀half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspect ... ... return col;}
下圖顯示了上面那段代碼的效果:
2、對(duì)x做偏移,代碼如下:
half4 frag (v2f i) : SV_Target{half t = _Time.y;half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half w = i.uv.y * 10;half x = sin(3 * w) * pow(sin(w), 6) * 0.45;//對(duì)x做些復(fù)雜的移動(dòng),(1)half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑trail *= smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失trail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5col += drop;col += trail;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線return col;}
(1)中的函數(shù)圖:
下圖顯示了上面那段代碼的效果:
3、我們需要更隨機(jī)些的效果,因此引入偽隨機(jī)數(shù):
// 求偽隨機(jī)數(shù)half N21(half2 p){p = frac(p * half2(123.34, 345.45));p += dot(p, p + 34.345);return frac(p.x + p.y);}
先測(cè)試下偽隨機(jī)數(shù),代碼:
... ...
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線
col *= 0; col += N21(i.uv); //測(cè)試代碼
... ...
下圖顯示了上面那段代碼的效果:
可以得到噪點(diǎn)圖,再把 col += N21(i.uv); 改為col += N21(id); 代碼如下:
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線
col *= 0; col += N21(id);
下圖顯示了上面那段代碼的效果:
我們調(diào)整時(shí)間處理代碼:
half4 frag (v2f i) : SV_Target{//每?jī)蓚€(gè)小時(shí)重置下,這樣不會(huì)得到太大的數(shù)字,效果不平滑(3)half t = fmod(_Time.y * _T, 7200);... ...
}
(3)中如果數(shù)字太大會(huì)得到如圖效果,效果很不好。
4、接下來(lái)我們完善下我們的效果,代碼:
half4 frag (v2f i) : SV_Target{half t = fmod(_Time.y * _T, 7200);//每?jī)蓚€(gè)小時(shí)重置下,這樣不會(huì)得到太大的數(shù)字,效果不平滑(3)half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half2 id = floor(uv);half n = N21(id); // 0 1t += n * 6.2831; //2PIhalf w = i.uv.y * 10;half x = (n - 0.5) * 0.8;; // -0.4 - 0.4x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在邊框內(nèi)擺動(dòng)half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑trail *= smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失trail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5col += drop;col += trail;if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線//col *= 0; col += N21(id);return col;}
下圖顯示了上面那段代碼的效果:
【6】水滴滑動(dòng)拖尾霧效果
1、先實(shí)現(xiàn)第一步效果,代碼:
half4 frag(v2f i) : SV_Target{half t = fmod(_Time.y * _T, 7200);//每?jī)蓚€(gè)小時(shí)重置下,這樣不會(huì)得到太大的數(shù)字,效果不平滑(3)half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half2 id = floor(uv);half n = N21(id); // 0 1t += n * 6.2831; //2PIhalf w = i.uv.y * 10;half x = (n - 0.5) * 0.8;; // -0.4 - 0.4x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在邊框內(nèi)擺動(dòng)half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失fogTrail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5trail *= fogTrail;col += fogTrail * 0.5;col += drop;col += trail;if (gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線//col *= 0; col += N21(id);return col;
}
下圖顯示了上面那段代碼的效果:
2、我們需要講上圖的兩邊霧的效果縮小下,代碼:
half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑
half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失
fogTrail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5
fogTrail *= smoothstep(0.05, 0.04, abs(dropPos.x));// 兩邊霧的效果縮小下
trail *= fogTrail;
col += fogTrail * 0.5;
下圖顯示了上面那段代碼的效果, 可以看出兩邊霧被縮小了:
【7】結(jié)合主紋理,得到簡(jiǎn)答的真實(shí)水滴屏幕效果
1、直接貼代碼:
half4 frag(v2f i) : SV_Target{half t = fmod(_Time.y * _T, 7200);//每?jī)蓚€(gè)小時(shí)重置下,這樣不會(huì)得到太大的數(shù)字,效果不平滑(3)half4 col = half4(0, 0, 0, 1.0);half2 aspect = half2(3, 1);//長(zhǎng)寬比half2 uv = i.uv * _Size * aspect;uv.y += t * 0.25; //水滴周期移動(dòng)的同時(shí),uv也往下移動(dòng),這樣就能做到水滴往下移動(dòng)的效果half2 gv = frac(uv) - 0.5;//-0.5,將左下角的原點(diǎn)調(diào)整為中間half2 id = floor(uv);half n = N21(id); // 0 1t += n * 6.2831; //2PIhalf w = i.uv.y * 10;half x = (n - 0.5) * 0.8;; // -0.4 - 0.4x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在邊框內(nèi)擺動(dòng)half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//將y改為更復(fù)雜些的移動(dòng)(2)y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect;// 移動(dòng)水滴,除以aspect是因?yàn)橹暗膗v*aspecthalf2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是將半圓調(diào)整為完整圓half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴half drop = smoothstep(0.05, 0.03, length(dropPos));//畫(huà)圓, length(gv),可以理解為半徑half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//將下部分拖尾水滴清理掉,邊移動(dòng)拖尾邊消失fogTrail *= smoothstep(0.5, y, gv.y);//將水滴做個(gè)漸變,從上到下從無(wú)到有, 0.5是以gv為坐標(biāo)的,頂部0.5,底部-0.5fogTrail *= smoothstep(0.05, 0.04, abs(dropPos.x));trail *= fogTrail;col += fogTrail * 0.5;col += drop;col += trail;//if (gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線//col *= 0; col += N21(id);half2 offset = drop * dropPos + trail * trailPos;half4 finalColor = tex2D(_MainTex, i.uv + offset * _Distortion);return finalColor;
}
下圖顯示了上面那段代碼的效果:
2、接下來(lái)我們需要對(duì)主紋理采樣進(jìn)行處理,得到一種霧屏的效果
代碼:
half2 offset = drop * dropPos + trail * trailPos;
//這里為啥1-fogTrail,讀者可去試下,得到拖尾霧效果是相反的
half blur = _Blur * 7 * (1 - fogTrail);
//直接將tex2D改為tex2dlod, _Blur控制模糊程度
//tex2Dlod(ref: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509680%28v=vs.85%29.aspx)
half4 finalColor = tex2Dlod(_MainTex, half4(i.uv + offset * _Distortion, 0, blur ));
下圖顯示了上面那段代碼的效果:
3、接下來(lái)我們需要整理下代碼:
half3 dropLayer(half2 UV, half T){half t = fmod( _Time.y + T, 3600);half4 col = half4(0, 0, 0, 1.0);half aspect = half2(2, 1);half2 uv = UV * _Size * aspect;uv.y += t * 0.25;half2 gv = frac(uv) - 0.5;//-0.5,調(diào)整原點(diǎn)為中間half2 id = floor(uv);half n = N21(id); // 0 1t += n * 6.2831; //2PIhalf w = UV.y * 10;half x = (n - 0.5) * 0.8;x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;y -= (gv.x - x) * (gv.x - x);half2 dropPos = (gv - half2(x, y)) / aspect; //- half2(x,y) 為了移動(dòng)half drop = smoothstep(0.05, 0.03, length(dropPos));half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 為了移動(dòng)trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8;half trail = smoothstep(0.03, 0.01, length(trailPos));half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);// 拖尾小水滴慢慢被拖掉了fogTrail *= smoothstep(0.5, y, gv.y);// 拖尾小水滴漸變消失fogTrail *= smoothstep(0.05, 0.04, abs(dropPos.x));trail *= fogTrail;//col += fogTrail * 0.5;//col += trail;//col += drop;//if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 輔助線half2 offset = drop * dropPos + trail * trailPos;return half3(offset, fogTrail);}half4 frag (v2f i) : SV_Target{half3 drops = dropLayer(i.uv, _T); half blur = _Blur * 7 * (1 - drops.z);half4 col = tex2Dlod(_MainTex, half4(i.uv + drops.xy * _Distortion, 0, blur));return col;}
【8】現(xiàn)在的雨滴效果還不夠,我們需要疊加幾層,效果會(huì)更豐富些
half4 frag (v2f i) : SV_Target{half3 drops = dropLayer(i.uv, _T);//這里的參數(shù)讀者可自行測(cè)試控制drops += dropLayer(i.uv * 1.25 + 7.52, _T);rops += dropLayer(i.uv * 1.35 + 1.54, _T);drops += dropLayer(i.uv * 1.57 - 7.52, _T); half blur = _Blur * 7 * (1 - drops.z);half4 col = tex2Dlod(_MainTex, half4(i.uv + drops.xy * _Distortion, 0, blur));return col;}
上面得到的效果就是開(kāi)篇的那種效果了,讀者還可以結(jié)合抓屏效果去實(shí)現(xiàn)更好的效果,性能上這塊算法也沒(méi)比較復(fù)雜的指令運(yùn)算,移動(dòng)端可以使用的,讀者液可自行使用renderdoc等GPU測(cè)試工具測(cè)試下即可。
總結(jié)
本文實(shí)現(xiàn)的雨水滴到屏幕效果相對(duì)來(lái)說(shuō)還是不夠豐富的,如果讀者想實(shí)現(xiàn)更復(fù)雜的效果可以參考
raindrop?github.comShaderToy鏈接?www.shadertoy.com
通過(guò)學(xué)習(xí)筆者寫(xiě)的,再去理解更復(fù)雜的效果會(huì)容易上手些。后續(xù)筆者會(huì)繼續(xù)推出更多有詳細(xì)解析的文章。(備注:知乎上代碼排版比較不方便,看著沒(méi)那么好看)
總結(jié)
以上是生活随笔為你收集整理的unity 模型渐变消失_Unity 雨水滴到屏幕效果的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。