教程原链接
https://zhuanlan.zhihu.com/p/182459720
https://deepspacebanana.github.io/deepspacebanana.github.io/blog/shader/art/unreal%20engine/Rainy-Surface-Shader-Part-1
涟漪效果
fixed4 frag (v2f i) : SV_Target
{
float t = frac(_Time.y * _Speed);
fixed3 col = fixed3(t,t,t);
UNITY_APPLY_FOG(i.fogCoord, col);
return fixed4(col,1);
}
这样可以实现这样的一个渐变效果:
![](https://img.haomeiwen.com/i17546328/851ece8589bca6fd.png)
![](https://img.haomeiwen.com/i17546328/214d390bf654eadc.gif)
然后思考一下我们怎么做成这样的效果:
![](https://img.haomeiwen.com/i17546328/d532ce67a3d58ea2.gif)
我们可以看到这个点点的贴图,作者是放在了一张贴图的红色通道里面:
![](https://img.haomeiwen.com/i17546328/83f4ccd97f3d0fc1.png)
先按下面的写法提出红色通道的图:
fixed3 texColor = tex2D(_MainTex,i.uv);![4.gif](https://img.haomeiwen.com/i17546328/23f30d159431988e.gif?imageMogr2/auto-orient/strip)
col = fixed3(texColor.r,texColor.r,texColor.r);
![](https://img.haomeiwen.com/i17546328/c652350985e18a59.png)
![](https://img.haomeiwen.com/i17546328/f69a0de23a266ebd.png)
可以看到代码提出来的红色通道失真非常严重(目前不知道为什么,开了抗锯齿和双线性插值都不行),但目前不影响我们继续,合理想象一下,我们需要白点从 0 - 1,然后骤降到 0。所以按下面的写法就完成了:
fixed4 frag (v2f i) : SV_Target
{
float t = 1-frac(_Time.y * _Speed);
fixed3 col = fixed3(t,t,t);
fixed3 texColor = tex2D(_MainTex,i.uv);
col = fixed3(texColor.r,texColor.r,texColor.r)-t;
UNITY_APPLY_FOG(i.fogCoord, col);
return fixed4(col,1);
}
可以看到效果好像是从每个圆中间逐渐向周围出现的,但其实这个是因为本身贴图的每个圆都是中间最白,逐渐变黑。此时此刻,黑色部分是从 0~-1(只是因为小于 0 的话,显示出来的还是黑色,所以看不出来而已,但需要记住黑色的 rgb 值也是有变化的),而白色小圆圈是从 0~1;此时想要做出这种效果,我们可以想到其实就是把黑白边界给做出来,那我们只要计算每个像素跟 0.05(这个大小可以自动调节,但不能太大,最后圆环的宽度应该是这个值的两倍)的距离就可以把边界用两条黑线给画出来。
fixed4 frag (v2f i) : SV_Target
{
float t = 1-frac(_Time.y * _Speed);
fixed3 col = fixed3(t,t,t);
fixed3 texColor = tex2D(_MainTex,i.uv);
float dis = saturate(distance(texColor.r - t,0.05)/0.05);
col = fixed3(dis,dis,dis);
UNITY_APPLY_FOG(i.fogCoord, col);
return fixed4(col,1);
}
![](https://img.haomeiwen.com/i17546328/22b68ccb1b99b6da.gif)
因为外面也在闪烁,所以不是很清楚的看出来,黑色圆环其实是中间两个连着很近的黑线,然后逐渐向两边减淡的样子。可以思考一下,除了小圆点之外的为什么也开始闪烁了,其实它原本应该是从 -1~0 的状态,计算了距离之后,就是从 0.95~0.05 的状态了,我们怎么让他保持不变呢,可以发现他的最小值也是 0.05,那只要用它去除 0.05,得到的值就是 1-19,而大于 1 的部分显示为颜色都是白色。再验证一下黑色圆环的部分是否会受到影响,它的范围应该是 0-0.05,那么除下来结果为 0 ,没有问题。再验证一下小圈圈内的部分是否会受到影响,它的范围是 0.05-0.95,也没有问题。ok,最后用 saturate
把值都限制在 0-1 就 ok 了(不写这个也没关系)
![](https://img.haomeiwen.com/i17546328/fb804d103906c196.gif)
现在就是只有黑白,没有过渡的小圆圈的涟漪效果了。看起来有点密,还有点脏(暂时不知道为什么,既然有的小圆圈是不脏的,那应该是贴图的问题吧,就是 0-1 的过渡不是线性的话就会出现脏脏的效果)。
现在再复制一份,然后让 uv 和时间都交错一点,顺便给它换成黑底的,话说程序员是不是对深色都比较情有独钟, 前 leader 就说过我能不能把 mac 初始的白色终端换个颜色。
![](https://img.haomeiwen.com/i17546328/be40a84b7863379c.gif)
![](https://img.haomeiwen.com/i17546328/1f9f69257a0d07d2.gif)
fixed4 frag (v2f i) : SV_Target
{
float lerp_t = frac(_Time.y * _Speed);
float t = 1 - lerp_t;
float t2 = 1 - frac((_Time.y) * _Speed + 0.5); // 时间偏移一点点
fixed3 col = fixed3(t,t,t);
fixed3 col2 = fixed3(t,t,t);
fixed3 texColor = tex2D(_MainTex,i.uv);
fixed3 texColor2 = tex2D(_MainTex,i.uv + float2(0.5,0.5)); // uv 偏移一点点
float dis = saturate(1-distance(texColor.r - t,0.05)/0.05);
float dis2 = saturate(1-distance(texColor2.r - t2,0.05)/0.05);
col = fixed3(dis,dis,dis);
col2 = fixed3(dis2,dis2,dis2);
fixed3 finalCol = lerp(col,col2,lerp_t); // 1的圈圈越大越偏向2,这样就有涟漪越大,越淡的效果了
UNITY_APPLY_FOG(i.fogCoord, finalCol);
return fixed4(finalCol,1);
}
这样乍一看没什么问题,但其实第二张图从 0.5 会有一个骤变,所以思考一下,图 1 和图 2 相差了 0.5s 的时间,,但还是要保证对于每个图来说,都是要从 1-0,画个简单的图就会发现这是不可能的,因为在图 1 在 0.5 的时候要求图 2 是1。那退而求其次,对每一个图来说都要从 0-1-0。像下面这个图一样:
![](https://img.haomeiwen.com/i17546328/0f41417c15a71324.png)
会发现正好满足我们需求,对于图 1 和图 2 的每一个周期来说都是从 0-1-0,代码如下:
fixed4 frag (v2f i) : SV_Target
{
float lerp_t = frac(_Time.y * _Speed);
float t = 1 - lerp_t;
float t2 = 1 - frac((_Time.y) * _Speed + 0.5); // 时间偏移一点点
fixed3 col = fixed3(t,t,t);
fixed3 col2 = fixed3(t,t,t);
fixed3 texColor = tex2D(_MainTex,i.uv);
fixed3 texColor2 = tex2D(_MainTex,i.uv + float2(0.5,0.5)); // uv 偏移一点点
float dis = saturate(1-distance(texColor.r - t,0.05)/0.05);
float dis2 = saturate(1-distance(texColor2.r - t2,0.05)/0.05);
col = fixed3(dis,dis,dis);
col2 = fixed3(dis2,dis2,dis2);
float lerp_t2 = sin(lerp_t * 3.14159); // 把 [0,1] 映射到 [0,3.14159] 得到 sin 的半个周期,所以并不需要 abs
fixed3 finalCol = lerp(col2,col,lerp_t2);
UNITY_APPLY_FOG(i.fogCoord, finalCol);
return fixed4(finalCol,1);
}
顺便说一下之前觉得雨点很脏,很密集的问题,是因为雨点确实很多,所以在面板上将大小设置为 0.5 就好了,只使用四分之一的大小。
![](https://img.haomeiwen.com/i17546328/5890bdeaaeddd962.png)
![](https://img.haomeiwen.com/i17546328/b5bdba2149371055.gif)
网友评论