2D雨水--在地面撒上欢快的音符

接上一篇2D雨水–下一场酣畅淋漓的大雨吧

ripple

前言

在上一篇中,我们已经可以下一场酣畅淋漓的大雨了,但还是觉得缺了点啥,没错,地面没有水花,看起来还是假了些,就好像物体没有影子一样。所以本篇就讲水花,上面截图不知道是否能看清,gif图压缩损失太大,将就看吧,我把雨水隐了,特意把水花亮出来。

原理

说到水花,是不是又是优先想到粒子,这满屏的粒子,数量少了不明显,数量多了就是性能杀手。所以咱不能用,2D游戏,瓶颈都在CPU,咱得让GPU忙起来,所以本篇只需跟一张图较劲,用shader让它动起来。

在开始正文之前,先贴上参考链接:https://zhuanlan.zhihu.com/p/182459720 ,感激巨人的肩膀让我站了一下。我只是借用其中水花的内容

水花图

本篇就是跟它较劲。

采样

采样水花图很简单,只是采样的uv需要控制一下,我们用一个变量控制它的tiling,值越大,水花就越小。
vec2 uv = v_worldPos.xy * _RainRippleTiling;
vec4 rippleCol = texture(_RainRippleTex, uv);
如上代码,_RainRippleTiling就是控制tiling的变量,_RainRippleTex就是我们的水花图。

点变成环

这里借用一下参考文章的图,我们只考虑点的单通道,比如r通道,如图示例,我们只盯着那个圆点,点的中心r是0.9,到边缘逐渐降低到0.05,这里我们用shader内置的一个函数distance,distance的通常用法是求两点的距离,但这里传的是两个浮点值,你也可以用距离的思路去考虑它,比如图上所示,0.9到0.05的距离就是0.85,距离是两个值相减的绝对值,注意是绝对值。

现在想这样一个公式:distance(r, 0.05)
只有当r在(0, 0.1)之间时,值在[0, 0.05),其他都大于等于0.05,注意区分范围标志的小括号和中括号,
这个时候除以0.05,distance(r, 0.05) / 0.05
r范围在(0, 0.1)时,值范围会变成[0, 1),其他都大于等于1,
再用1 - distance(r, 0.05) / 0.05
r范围在(0, 0.1)时,值范围会变成(0, 1],其他都小于等于0,
要的就是这个值,我只要将其Clamp在0到1之间,是不是就做到了只保留r范围在(0, 0.1)之间的像素,并且值变成了(0, 1],这样图上黑色区域还是0,而白点的外围变成了一个小光圈,里面扣成了黑色。

让环动起来

好了,到现在为止,我们成功的生成了一个静态的环,那可不是我们想要的,但我们离真相就一步之遥了,我们现在的目的就是,让白点的r值从内向外,逐渐变化成(0, 0.1),这样就有了逐渐扩大的光圈,动起来就像个水花。
好了,直接上公式吧:t - 1 + r
t是动态的,从0到1变化,减1就是从-1到0变化,r的范围是(0, 1],这样r值越高,就会越先到(0, 0.1),然后向r值低处过度,就可以实现从中心向周围逐渐变化的感觉了。t的模拟很简单:
float t = fract(cc_time.x * _RainRippleSpeed)
fract是shader内置的函数,只截取小数部分,_RainRippleSpeed可以控制速度。
说了这么多,其实代码就三行:

float t = fract(cc_time.x * _RainRippleSpeed);
float col = 1.0 - distance(t - 1.0 + rippleCol.r, 0.05) / 0.05;
col = clamp(col, 0.0, 1.0);

叠加双层采样

以上效果虽然有环的动画了,但效果比较丑,这里我们再叠加一重采样,另一重采样uv偏移0.5,时间上也滞后0.5s。代码如下

WeChat9e2c716bb5b9467f6e1f9825d3fb4883

两个结果做一下混合渐变
float final = mix(col1, col2, abs(0.5 - t1) * 2.0);
这里的混合参数abs(0.5 - t1) * 2.0,将t1从0到0.5,以及0.5到1分成两段,从而使col1和col2此消彼长,实现两层水花环错落变化的感觉。最终的(final, final, final,1)就是我们要的颜色了。

r

交给地面渲染

有了水花图,后面的事情就简单了,还记得上一篇我们自定义了Sprite的shader,我们希望大地有水花,但其他物体不要有,所以给大地一个单独的材质,shader里采样Sprite的color,直接加上采样水花图的颜色即可。

col.rgb += vec3(final, final, final) * _RainRippleIntensity;

这里用_RainRippleIntensity控制一下水花的强弱,然后聪明的你一定想到了,这里要和上一篇雨势渐变联动起来,开始时从弱到强,结束时从强到弱,代码简单,就不写了。最后看一下材质截图

WeChat2b28fa88d2d86772d32fb4dd00f716f9

OK,到这里算是真的结束了,但如果你的游戏里有花草,树木,你甚至可以结合它们的uv,做顶点动画,模拟风的感觉,那效果就更美丽了,哈哈。

最后,这两篇文章已经把雨的制作过程介绍的很详细了,如果实在想参考源码,那就请移步cocos store吧:2D雨水-下一场酣畅淋漓的大雨吧,谢谢支持

往期文章:

2D光影系统-光源一全局方向光
2D光影系统-光源二Sprite光
2D光影系统-阴影
2D描边-内描边
2D描边-外描边
2D基于屏幕的反射

4赞

这么牛逼?还是人吗?

19块,挺便宜,学习一下~

小母牛坐飞机 :+1:

谢谢支持 :pray:

楼主的一系列文章真不错。楼主在cocos creator里复现下面的效果吧
http://www.gamelook.com.cn/2018/11/342650

买下来偷走代码markmark

点个赞:+1::+1: