FishMan的技术专栏 Game Developer/Technical Artist

中级Shader教程27 水专题04:三种窗前雨滴效果

2018-04-26
Jiepeng Tan

本篇主要技术点有:

栅格化屏幕空间 函数设计技巧:”凑” 2D旋转

.代码实现:

0. 栅格化

float aspectRatio = 4.0;//每一行雨滴的宽高比
float tileNum = 5;//平铺数量
uv *= fixed2(tileNum * aspectRatio,tileNum);//栅格化uv
uv = frac(uv);
uv -=0.5;

1. 绘制主要雨滴

float r = length(uv);
r = smoothstep(0.2,0.1,r);
return float2(r,0.);

uv.y *= aspectRatio;

变形矫正

2. 绘制尾迹

//添加尾迹
float tailTileNum = 3.0;
float2 tailUV =uv *  float2(1.0,tailTileNum);
tailUV.y = frac(tailUV.y) - 0.5;
tailUV.x *= tailTileNum;
float rtail = length(tailUV);
rtail = smoothstep(0.2,0.1,rtail);

3. 尾迹塑形

//在雨滴上面总共有
float rtail = length(tailUV);
//尾迹塑形
rtail *= uv.y;//上面的y值大 使得雨滴形状变小
rtail = smoothstep(0.2,0.1,rtail);
//切除掉大雨滴下面的部分
rtail *= smoothstep(0.2,0.3,uv.y);//0.2以下的部分雨滴太大,切掉

4. 融合大雨滴和尾迹,并给雨滴添加模拟法线

float2 allUV = float2(rtail*tailUV+r*uv);

5. 把雨滴法线用于采样背景贴图

	fixed4 finalColor = tex2D(_MainTex, uv + Rain(uv)*2.);

6. 让整个雨滴动起来

//让雨滴沿y轴向下移动
float ySpd = 0.1;
uv.y += time * ySpd;
uv *= fixed2(tileNum * aspectRatio,tileNum);//栅格化uv

7. 让雨滴滚动起来更有节奏

//这里是屏幕空间
uv.y += time * PI2 /period / tileNum *0.45* 0.55;//加点y轴移动
//other code

float period = 5;//second per circle
float t = time * PI2 /period;
//这里是格子空间
//此处uv值范围为(-0.5,0.5)
uv.y += sin(t+sin(t+sin(t)*0.55))*0.45;
uv.y *= aspectRatio;

我们想让雨滴的Y轴移动的行为像下图,这样会让雨滴先快速移动,然后好像停顿一样,然后继续的感觉

雨滴移动的函数为 y = (sin(x+sin(x+sin(x)0.55)))+x0.55

如你所见,类似的函数有很多,只要能得到你想要的形状,怎么样都可以,如何“凑”出这些形状的函数,请参考我前面的博客的内容

而具体到代码中 令 funcVal = (sin(x+sin(x+sin(x)*0.55))) 本身 范围为[-1,1.0] 而我们格子初始的uv的y值域为[-0.5,0.5] 我们的水滴是通过length来实现的 所以中心在dropCenter=0处,为了消除栅格化导致的明显的空间分割影响,让上下两个水滴拥有碰撞的可能是非常的必要的,在uv.y+= funcVal * 0.45后,dropCenter 的取值范围为[-0.5,0.5],即可以出现在格子的两端,从而在视觉上格子之间的水滴是有可能碰撞的

而代码中的 0.0618 = PI2 /period / tileNum 0.45 0.55

效果如下: 只有大雨滴个之中的移动效果

加上贴图后

8. 加点基于格子的随机值

fixed2 idRand = Rand22(floor(uv));
t += idRand.x * PI2;//添加Y随机值
/////
uv.x += (idRand.x-.5)*.6;//添加x轴随机偏移

9. 添加斜率的变化,模拟风的效果

flaot DEG2RAD = 3.14159 /180;
flaot ratoteDeg = 20.0 * DEG2RAD;
float s = sin(ratoteDeg);
float c = cos(ratoteDeg);
float2x2 rot = float2x2(c, -s, s, c);
uv = mul(rot,uv);

10. 多加几层不同大小的雨滴

rainUV += Rains(uv,152.12,moveSpd);
rainUV += Rains(uv*2.32, 25.23, moveSpd);

最终效果图

本shader原型来自BigWIngs

配套视频


Similar Posts

Comments