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

smallRain

storm

前言

说到下雨效果,是游戏中常见的一种天气表现,各种教程中,常见用粒子来模拟雨水,效果虽好,但属实是不敢用在对性能要求比较高的移动端设备上,而2D手游上最常见的,是用uv动画来做雨水效果,这也是本文的重点,但怎样做的逼真,怎样做成编辑器模拟各种雨势,就是细节功夫了。

原理

我们这里只讨论2D的雨效,如上所说,雨水效果是用uv动画实现的,但简单的uv动画又缺乏层次感,毕竟雨点会有近大远小的感觉,嗯,那就不妨多来几种uv动画叠加显示。雨势怎么区分,想想现实的雨水,雨滴掉落速度,倾斜角度,天色暗淡程度等,是不是都可以增加雨势强弱的感觉。那雷雨的闪电怎么模拟,因为是俯视角,闪电的感觉全来自场景的快速闪白效果,我们用曲线编辑器模拟一下。最后有个事别忘了,天上下雨,地面就要有水花,不然就像地上的物体没有影子一样缺乏真实感。

一、雨水shader(实现雨水的uv动画)

uv动画的shader是很简单的,毕竟下雨只是雨水的图按uv的y方向向下滚动的效果,我截了部分雨图如下:

为了做无限滚动的效果,雨图要做成四方连续的。上图为了看清雨点,背景有了颜色,实际上是透明的,也就是Alpha是0,最后别忘了Wrap Mode是Repeat,不然也就无法滚动了。

shader很简单,主要是uv的操作,我们拿内置的Sprite的shader稍微改改就行了,顶点着色器的核心代码就一句:
v_uv -= vec2(0, _FallSpeed) * cc_time.x;
就是每帧在uv的y值上减去_FallSpeed,这个_FallSpeed就是uv滚动的速度,也就是雨点掉落的快慢。
片段着色器更简单,
vec4 col = texture(cc_spriteTexture, v_uv);
col = col * _col.a;
混合模式那里,源和目标都设置成one
blendSrc: one
blendDst: one

二、制作Sprite

我们把上述shader,赋予材质,就准备就绪了。然后创建个Sprite,把材质付给他。Type要改成SLICED,运行看看,你应该就能看到一个简单的下雨的Sprite了。

WeChatbc6c716ac880c60289cb9c4728bee79f

哇塞,是不是这样就可以交差了。。。如果你不在乎策划,美术暗地里骂你的话。

三、层次空间感

为了避免被骂,我们还得再细化一些,想想3D空间的雨滴,是近大远小的,并且由于视野的不同,会有近快远慢,近疏远密的感觉,那2D效果怎么去模拟空间感呢。
说的那么复杂,其实特别简单,我们还是在uv上做手脚,在同一块幕布上,uv值越大,平铺的Sprite就越多,每个Sprite图就越小,所以我们只要给uv一个相乘的系数就可以控制图的大小了。顶点着色器里只需加一句:
v_uv = a_texCoord * _RepeatTimes;
这个_RepeatTimes就是我们想要的东西,值越大,平铺的数量就越多,视觉上图就越小越密。

OK,我们终于可以控制雨滴的大小疏密了,但我要的不是整体的变大变小,而是近大远小,也就是说有层次感,可是2D空间没有z轴,那我们不妨用几层Sprite来模拟一下。
这里我做了3层Sprite,分别模拟近处,不远处以及远处。用不同的RepeatTimes控制大小疏密,再用不同的_FallSpeed控制雨速(近快远慢),甚至在片段着色器中加了个颜色的强度加成,做到近处雨清晰,远处雨朦胧的感觉。
col.rgb = col.rgb * _Intensity;

看一下最终的shader

顶点着色器
WeChat12eea42e19952ef5d29cca24b058fa87

片元着色器
WeChatfa0054925157657faf0e6ebf05bfb2b5

近处雨的材质
WeChat901ca794ed208f1cb98d2fe64762e1cf

中部和远处的材质用不同的值去尝试,以达到自己想要的效果。
然后将它们放在一起,充满全屏,这个效果比之前好看多了。

四、雨水编辑器

为了让策划美术们再开心些,我们不妨做个编辑器,把这些参数放一起,省的他们一个一个去编辑。编辑器把近,中,远的雨水参数放在一起编辑,然后分别赋予自己的材质属性,代码很简单,就不展开了,看一下编辑器。

WeChatf14616c4c98e4b96f3254a8ffa148b75

这里面的Distance就对应材质里的_RepeatTimes,用Distance做名称比较好理解。

我创建了一个父物体,把近中远三层Sprite作为子,然后把编辑器代码拖到父物体上,分别控制子物体的材质。

WeChatb8775563ec7f167edf2b57b0708d9e5d

五、雨水角度

再进一步,我们前面说过,要模拟雨势强弱,雨水角度是个不错的参数。就好像大雨伴随大风。那角度怎么做呢,说来也容易,给Sprite的Rotation一个值就行了。雨水角度是个公共值,三层Sprite分别设置这个公共值即可。

我们继续扩展一下上面的编辑器,把角度也加上,然后代码里读取这个角度,分别赋给三个Sprite的Rotation。

六、天色变化

既然是下雨,那就该阴天,并且阴的程度跟雨势相关,可是怎么展示阴天呢,我的俯视角看不到天空,那就让场景上的所有物体暗淡一些吧

我们这里先简单的修改场景所有Sprite的Color值,来模拟阴天的感觉,还是在编辑器里加一个天色的Color属性,然后场景所有Sprite的Color都读取这个天色值即可,代码简单,就不详细介绍了。

七、下雨时长

我们给下雨设定个时长,比如60秒,既然有时间,那就该有雨效开始和结束的渐变效果,比如开始阶段天色从晴逐渐到阴,雨势从小到大,结束阶段则相反。好在上面所有的属性都已具备,我们变化些参数就可以模拟这种渐变了。

首先在编辑器里加上雨水的总时长,再加上开始和结束的时长,这样把下雨分成三个阶段,开始阶段,中间阶段和结束阶段。
然后在编辑器代码的Update里判断当前时间,是在下雨的哪个阶段,如果是在开始或结束阶段,我们就要根据这个时间算个比值,比如开始阶段时长是10s,当前到了5s,那比值就是0.5。
雨效渐变影响两个参数,一个是天色,一个是雨的强度,这两个参数我们上面都已经有了,我们用上面得到的比值去做它们的插值,就可以得到当前的天色和雨的强度。


WeChat5b6624df5ab7ff0f195867656d1d0d67

上面代码,_CurTime就是当前时间,_startToMaxTime是开始阶段时间,_stopToEndTime是结束阶段时间,所以 t 就是在计算插值,intensity是雨的强度,通过插值去计算当前强度。sunColor是天色,也是通过插值去计算。

startRain

上述属性的编辑器截图

WeChat938130b4e3a7684ace836edbc2d20dde

如上,总时长60s,开始和结束分别10s,下面是天色和雨水角度

八、闪电

做到以上阶段,下雨的属性就基本都满足了,想做多大的雨就调多大的雨,只是暴雨没有闪电,效果不够惊艳。

闪电嘛,我这里是看不到的,没有天空,2D游戏时常是俯视角,这种情况下怎么做闪电呢。想想你住楼上,闪电时你看楼下是啥样,闪白就好了。

说到闪白,可能有人想到,那就接着改场景Sprite的颜色,你可以改改试试,Sprite的Color默认是白色,就是自己的原色,可是闪电啊,原色可不够,我要它白一点,再白一点,只要不闪瞎我的眼。这样的话,恐怕Sprite默认的材质就不行了。那就造个轮子吧,其实也简单,在Sprite的shader里做个颜色的加成即可。

如上代码,_LightStrength就是干这个的,默认是1,闪电时变大即可。天色我也通过_RainColor来传递了。RAIN_EFFECT是下雨的Keyword。

这里要吐个槽,Unity可以动态开关Keyword,但Cocos不提供,所以只能用换材质的方法。不下雨就用系统内置的材质,下雨就换这个新建的材质。

接受闪白的材质有了,控制闪白怎么搞呢,也就是怎么给_LightStrength传值呢,不绕弯子了,用Cocos自带的曲线编辑器RealCurve。

WeChatd28cba27610fb2aa4ad5950b6f41d44a

啊。。。我不得不再吐一次槽,Cocos的曲线编辑器也不好用啊,我这是3.8.3的版本了,曲线编辑器不能拖动,不能放大,我用的是Mac版本,不知道Windows有没有这个问题,最可惜的是x轴只能从0到1,不能直观的代表时间,这样是无法精准的设计闪电时长的,只能调着来。希望官方后续能把它做的完善些。

书归正文,上面截图就是调的一版曲线,x代表时间,y代表闪白加成值,可以看出每次闪电时间短暂,曲线峰值尖锐,波峰波谷瞬变,这样就会有快速忽闪的效果。

上面说了,Cocos的曲线x只能从0到1,所以要做个时间的转换,然后采样曲线,传给材质的_LightStrength参数。

闪电效果看开篇的gif图即可

编辑器的闪电编辑如图

WeChat1e530a3a9553c8fd977527008c534790

做到这,有关雨的部分就做全了,但要想做的逼真,就要场景物体跟着造势,比如地面水花,留给下一篇介绍吧,本文已经太长了,多谢你耐心看完。

往期文章:

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

37赞

可能已经会用到 先插眼吧

markmark

markmark

mark mark

雨水markmark

论坛有你更精彩 MARK

跪拜大佬 :3:

插眼插眼插眼

有源码demo就更佳了

要是有2.x的demo就更香了 只能mark一下以后有用到再研究

markmark

markmark

小母牛坐飞机 :+1:

什么时候挂Store~

mark~

雨的话 用粒子发射器 就能实现吧。

我mark

6666 old big big big

那么 在哪里才能买得到呢?