本文主要介绍用unity实现雨水滴到屏幕的效果,文章介绍的是基础实现,读完这篇文章再去实现复杂效果会更得心应手些。我们先看更高级效果的图片:
先直接上代码,后面再做介绍:
登录后复制
Shader "Unlit/ScreenWater"
{
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 100
Pass
{
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;
}
// 求伪随机数
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,调整原点为中间
half2 id = floor(uv);
half n = N21(id); // 0 1
t += n * 6.2831; //2PI
half 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) 为了移动
half drop = smoothstep(0.05, 0.03, length(dropPos));
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
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中先贴这段代码看,后面会做详细解析:
下面是实现步骤:
【1】先将uv平铺多次,为后面实现多个雨滴效果。
直接贴片元着色器代码:
登录后复制
half4 frag (v2f i) : SV_Target
{
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(1, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
col.rg = gv;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
下图显示了上面那段代码的效果:
说明:A为从左下角的原点调整为中间的情况, _Size 为平铺多次的情况,读者可边看边在untiy上操作。
登录后复制
half2 aspect = half(2, 1);//长宽比
设置长宽比为2:1后,得到效果:
【2】实现多个雨滴效果
直接贴片元着色器代码:
登录后复制
half4 frag (v2f i) : SV_Target
{
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half drop = smoothstep(0.05, 0.03, length(gv));//画圆, length(gv),可以理解为半径
col += drop;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
下图显示了上面那段代码的效果:
先附上smoothstep的解析,后续有时间会发文介绍glsl相关函数的理解,以及如何使用这些函数去实现复杂的效果。以下是smoothstep的解析:
我们先打开网址 Graphic Caculate,输入如图所示:
smoothstep的公式就是s = k^2*(3 - 2k), 图上所示就是smoothstep(0.4, 0.6, x), 如果是反过来就是smoothstep(0.6, 0.4, x), 得到的就是如图所示:
我们可以直接在 ShaderToy上演示输入如图所示代码:
0.2 ->0.0 可以理解为简单的反向操作如图所示:
【4】水滴移动
直接贴片元着色器代码:
登录后复制
half4 frag (v2f i) : SV_Target
{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half x = 0;
half y = sin(t);//水珠是上下来回移动的
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
col += drop;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
改动下代码,让水滴是往下移动的:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half x = 0;
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
col += drop;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
读者需要按照步骤去实现,更能理解算法表现的效果,帮助理解。上述代码中(2)得到的函数图是:
读者可自行控制算法,调出更好的效果。
【4】水滴拖尾效果,拖尾水滴滑下
1、先画一个拖尾水滴,代码:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half x = 0;
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half trail = smoothstep(0.03, 0.01, length(gv));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, 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、再计算移动,代码:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half x = 0;
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, 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、接下来我们将下部分拖尾水滴清理掉,边移动拖尾边消失,代码:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half x = 0;
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
trail *= smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
col += drop;
col += trail;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
下图显示了上面那段代码的效果:
3、然后将水滴做个渐变,从上到下从无到有,代码:
登录后复制
... ...
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
trail *= smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
trail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-0.5
col += drop;
col += trail;
... ...
下图显示了上面那段代码的效果:
【5】水滴做偏移,得到一种失真的效果,这时我们需要同时对x,y做偏移
1、同样,先贴上简单的效果,先改变下水滴的形状,代码:
登录后复制
half4 frag (v2f i) : SV_Target{
... ...
half x = 0;
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
y -= gv.x * gv.x;//改变水滴形状
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
... ...
return col;
}
下图显示了上面那段代码的效果:
2、对x做偏移,代码如下:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = _Time.y;
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half w = i.uv.y * 10;
half x = sin(3 * w) * pow(sin(w), 6) * 0.45;//对x做些复杂的移动,(1)
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
y -= (gv.x - x) * (gv.x - x);
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
trail *= smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
trail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-0.5
col += drop;
col += trail;
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
return col;
}
(1)中的函数图:
下图显示了上面那段代码的效果:
3、我们需要更随机些的效果,因此引入伪随机数:
登录后复制
// 求伪随机数
half N21(half2 p){
p = frac(p * half2(123.34, 345.45));
p += dot(p, p + 34.345);
return frac(p.x + p.y);
}
先测试下伪随机数,代码:
登录后复制
... ...
if(gv.x > 0.48 || gv.y > 0.49) col = half4(1.0, 0, 0, 1.0); // 辅助线
col *= 0; col += N21(i.uv); //测试代码
... ...
下图显示了上面那段代码的效果:
可以得到噪点图,再把 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);
下图显示了上面那段代码的效果:
我们调整时间处理代码:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = fmod(_Time.y * _T, 7200);//每两个小时重置下,这样不会得到太大的数字,效果不平滑(3)
... ...
}
(3)中如果数字太大会得到如图效果,效果很不好。
4、接下来我们完善下我们的效果,代码:
登录后复制
half4 frag (v2f i) : SV_Target{
half t = fmod(_Time.y * _T, 7200);//每两个小时重置下,这样不会得到太大的数字,效果不平滑(3)
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half2 id = floor(uv);
half n = N21(id); // 0 1
t += n * 6.2831; //2PI
half w = i.uv.y * 10;
half x = (n - 0.5) * 0.8;; // -0.4 - 0.4
x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在边框内摆动
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
y -= (gv.x - x) * (gv.x - x);
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
trail *= smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
trail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-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;
}
下图显示了上面那段代码的效果:
【6】水滴滑动拖尾雾效果
1、先实现第一步效果,代码:
登录后复制
half4 frag(v2f i) : SV_Target{
half t = fmod(_Time.y * _T, 7200);//每两个小时重置下,这样不会得到太大的数字,效果不平滑(3)
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half2 id = floor(uv);
half n = N21(id); // 0 1
t += n * 6.2831; //2PI
half w = i.uv.y * 10;
half x = (n - 0.5) * 0.8;; // -0.4 - 0.4
x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在边框内摆动
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
y -= (gv.x - x) * (gv.x - x);
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
fogTrail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-0.5
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);
return col;
}
下图显示了上面那段代码的效果:
2、我们需要讲上图的两边雾的效果缩小下,代码:
登录后复制
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
fogTrail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-0.5
fogTrail *= smoothstep(0.05, 0.04, abs(dropPos.x));// 两边雾的效果缩小下
trail *= fogTrail;
col += fogTrail * 0.5;
下图显示了上面那段代码的效果, 可以看出两边雾被缩小了:
【7】结合主纹理,得到简答的真实水滴屏幕效果
1、直接贴代码:
登录后复制
half4 frag(v2f i) : SV_Target{
half t = fmod(_Time.y * _T, 7200);//每两个小时重置下,这样不会得到太大的数字,效果不平滑(3)
half4 col = half4(0, 0, 0, 1.0);
half2 aspect = half2(3, 1);//长宽比
half2 uv = i.uv * _Size * aspect;
uv.y += t * 0.25; //水滴周期移动的同时,uv也往下移动,这样就能做到水滴往下移动的效果
half2 gv = frac(uv) - 0.5;//-0.5,将左下角的原点调整为中间
half2 id = floor(uv);
half n = N21(id); // 0 1
t += n * 6.2831; //2PI
half w = i.uv.y * 10;
half x = (n - 0.5) * 0.8;; // -0.4 - 0.4
x += (0.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * 0.45;// 0.4- abs(x), 目的是限制在边框内摆动
half y = -sin(t + sin(t + sin(t) * 0.5)) * 0.45;//将y改为更复杂些的移动(2)
y -= (gv.x - x) * (gv.x - x);
half2 dropPos = (gv - half2(x, y)) / aspect;// 移动水滴,除以aspect是因为之前的uv*aspect
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
trailPos.y = (frac(trailPos.y * 8) - 0.5) / 8; // -0.5是将半圆调整为完整圆
half trail = smoothstep(0.03, 0.01, length(trailPos));//拖尾小水滴
half drop = smoothstep(0.05, 0.03, length(dropPos));//画圆, length(gv),可以理解为半径
half fogTrail = smoothstep(-0.05, 0.05, dropPos.y);//将下部分拖尾水滴清理掉,边移动拖尾边消失
fogTrail *= smoothstep(0.5, y, gv.y);//将水滴做个渐变,从上到下从无到有, 0.5是以gv为坐标的,顶部0.5,底部-0.5
fogTrail *= 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、接下来我们需要对主纹理采样进行处理,得到一种雾屏的效果
代码:
登录后复制
half2 offset = drop * dropPos + trail * trailPos;
half blur = _Blur * 7 * (1 - fogTrail);//这里为啥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、接下来我们需要整理下代码:
登录后复制
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,调整原点为中间
half2 id = floor(uv);
half n = N21(id); // 0 1
t += n * 6.2831; //2PI
half 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) 为了移动
half drop = smoothstep(0.05, 0.03, length(dropPos));
half2 trailPos = (gv - half2(x, t * 0.25)) / aspect; //- half2(x,y) 为了移动
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】现在的雨滴效果还不够,我们需要叠加几层,效果会更丰富些
登录后复制
half4 frag (v2f i) : SV_Target
{
half3 drops = dropLayer(i.uv, _T);
//这里的参数读者可自行测试控制
drops += dropLayer(i.uv * 1.25 + 7.52, _T);
drops += 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;
}
上面得到的效果就是开篇的那种效果了,读者还可以结合抓屏效果去实现更好的效果,性能上这块算法也没比较复杂的指令运算,移动端可以使用的,读者液可自行使用renderdoc等GPU测试工具测试下即可。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删