UE5 材质 雨滴shader

发布时间 2023-05-16 22:38:34作者: 爱莉希雅

潮湿效果

物体表面是如何变湿的?

  • 物体表面吸水使颜色变深
  • 潮湿的颜色会变得暗淡且饱和

实现

  • 增加饱和度且变暗

    image-20230513173223191

潮湿的物体表面的特点

  • 当水作用在材质表面,材质表面的specualr会略微变弱且粗糙度会大幅降低
  • 对于积水的表面,我们设置它的roughness = 0.07, specualr = 0.3,一个value = 1用于控制潮湿程度,最后进行lerp即可

实现

  • 潮湿程度为1的效果
    image-20230513181608801

  • 潮湿程度为0的效果
    image-20230513181639602

  • 加入多孔性

    多孔性也就是吸水性,多孔性越高,颜色越暗
    image-20230516101041004

表面水珠(Rain Drop)效果

本节展示如何实现雨滴效果

雨滴纹理

为了实现表面水珠,我们需要一个雨滴纹理,它的RG通道表示雨滴法线;B通道表示时间偏移mask(使得雨滴在不同时间出现);alpha通道表示静止和动态的雨滴

  • 雨滴法线
    image-20230514131900655

  • 时间偏移
    image-20230514131942747

  • 动静雨滴

    黑点表示静止的雨滴,白色表示动态雨滴
    image-20230514132100620

实现

处理normal

因为在纹理图中normal的范围为[0,1],而归一化normal范围为[-1,1],因此我们需要进行一个转化
image-20230514133359106

处理时间偏移

这里重点在于Frac(),因为G通道值大多各不相同,这样减去时间的增量并取小数部分限制在[0,1]即可实现如下的闪烁效果
image-20230514140939680
image

动态雨滴

只需将时间offset用于A通道即可实现动态雨滴效果

  • 无normal
    "Multiply" "subtract" 是因为这里想提取time offset的白色雨滴(大雨滴)
    image-20230516105019435image-20230514142927044
    image

  • 有Normal

    image-20230514143444298
    image

静态雨滴

  • 因为在A通道中,黑色是静态雨滴,白色是动态雨滴,在处理动态效果时只处理了白色的值,那么在处理静态效果时进行一个反转即可

    注意,这里使用power()是因为我们只想要得到白色和灰色的效果并不想要灰色,但此时范围是[-1,1],因此需要控制一下范围
    image-20230514145447514
    image

控制雨滴效果方向

  • 在现实中,雨水来自天空,肯定只有上面才有雨滴效果,整个物体都有雨滴效果是不科学的,因此我们需要控制雨滴效果的方向——normal方向

    image-20230514150612047
    image

控制水滴的粗糙度

  • 目前已知表面偏向0,雨滴偏向1,而我们想要的效果是雨滴光滑表面粗糙,因此可以将之前得到的值进行反转然后作用域roughness即可

    image-20230514151942925
    image

流淌雨滴(Rain Drip)效果

流淌雨滴纹理

和雨滴效果相同,流淌雨滴纹理由法线贴图(RG)、mask(B)、time offset(A)组成

映射到世界空间

  • 为了应对物体从局部空间变化到世界空间的状况,需要将纹理映射到世界空间,这样无论物体进行任何矩阵运算,雨滴的流淌总是正确的

  • 使用世界空间的位置作为采样的纹理坐标,只需提取RB

    这里的Multiply()是为了正确的比例,乘以的value越小,采样得到的图像越大;value越大,采样得到的图像越小

    为什么还有负号呢?因为这样可以对采样方向取负
    image-20230514204942848

  • 采样侧面

    这里改变正负号是为了让物体的侧面和正面不再相同
    image-20230514205004241

  • 混合正侧面

    采样两次纹理进行合并是很简单的,但只采样一次又该如何实现呢?

    在这里采用世界空间的法线作为物体面的判断基准
    image-20230514214819917
    image-20230514214841026
    image-20230514222713735

制作动画的mask纹理

它的rgb通道都是相同的,a通道没有使用

image-20230514223342299

实现流淌雨滴

  • 将mask纹理映射至世界空间

    下图中,可以将白色部分视为雨滴,基于这个实现动画即可
    image-20230514223912200

  • 初步雨滴动画

    image-20230514224452782
    image

  • 控制雨滴速度

    雨滴在不同物体上的滑落速度是不一样的,因此我们还需要让这些雨滴的速度有所差异

    image-20230514232345853
    image

  • 雨滴法线
    image
    image

  • 将雨滴效果控制在物体侧面

    3.5用于控制正方向的白色范围,-1,5用于控制负方向的白色范围
    image-20230514234602091
    image

雨滴涟漪(Rain Ripple)效果

本节将展示如何实现雨滴打到水面产生的波纹效果

纹理

  • 动画mask纹理(渐变纹理)

    用该纹理可以实现圆从无到有,从小到大,最后渐渐消散
    image-20230515140948573

  • 法线纹理
    该纹理的R通道是动画mask纹理,GB通道是法线信息

    image-20230515150052144
    image-20230515150815395
    image-20230515150823539

  • 多个涟漪纹理

    alpha通道包含time offset
    image-20230515153639528
    image-20230515154254661

波纹效果

  • 实现纹理动画都需要Time节点。很容易实现以下内容
    image-20230515142542777
    image

  • 控制波纹边缘的锐度(让波纹边缘不再是渐变色)
    image-20230515143232071
    image

  • 初步实现波纹

    因为水波纹属于正弦函数,因此在这里我们使用一个sin,并让他在一个周期内产生五个波纹(因为UE5的sin函数默认周期为1)
    image-20230515143607191
    image

  • 标准的sin函数

    UE5中的sin函数并不是标准的sin函数(一个周期为2Π),它的默认周期为1,因此我们需要将其改为6.283185
    image-20230515144750434

  • 放大淡出效果

    目前我们实现的效果是到最大然后消失,但我们希望的是放大淡出。目前的效果是因为能量是从0到1,而放大淡出的效果应该是从1到0

    image-20230515145646448
    image

法线

image-20230515153015333

image

多个涟漪

  • 为每个涟漪赋予单独的Time
    image-20230515155215443
    image

多个涟漪相互叠加

  • 目前的效果只是在固定位置不同时间段产生波纹,但没有展现波纹的叠加效果

  • 首先,我们需要对"1-x"进行修改,添加力的因素

    • "Multiply 0.8"是因为需要考虑力的因素,让涟漪的初始能量不为1
    • "Add 0.2"是因为需要考虑雨滴重量不能为0的情况

    image-20230515174236068

  • 涟漪的叠加

    总体思路是使用四个不同的涟漪效果——不同的时间,不同的涟漪强度,对采样结果进行叠加

    • 求取四个不同的时间

      image-20230515171032517

    • 求取四个不同的uv

      image-20230515172511389

    • 求取四个不同的雨滴重量
      image-20230515175222642

    • normal混合
      image-20230515181855802

最终效果

image

水坑(Rain Puddle)效果

纹理

  • 扭曲纹理,
    对于扭曲纹理,我们将该纹理设置为"Linear Color"且无"sRGB",因为它只包含灰度值。第二张中,我们把该图的黑色部分视为水坑,部分有水坑部分没有符合现实常理(后面处理会进行"1-x"运算,将白色部分看成水坑)

    image-20230515204222476
    image-20230515205028508

映射至世界空间

  • 初步映射
    image-20230515205000018

  • 控制水坑大小

    这是一个灰度图,通过做减法即可放大水坑,但这里采用一种更加灵活的方式——lerp
    image-20230515212321145

  • 控制水坑位置

    让上图可以看到水坑的纹理延申到了其他面,但正常来说应该只有上面才会出现水坑,因此需要想办法让水坑只出现在物体上面
    image-20230515214239907

  • 确保水坑只有白色
    image-20230515214428743
    从上图可以得知,有些部分是灰色的。因此我们需要再"Multiply"确保只存在白色和黑色
    image-20230515214816344

normal

  • 水坑的涟漪不仅仅在水滴落下时会产生,当被风吹时也会产生。水滴落下的效果在之前已经实现了,对于风吹的涟漪我们采用UE5提供的纹理
    image-20230515221843332
    image

  • image

    image-20230515223411253
    image

  • 控制涟漪位置
    本小节的实现是水坑,那肯定是在水坑处产生涟漪啊!
    image
    image

融合所有效果

  • 将以上所有效果融合即可实现一个完整的雨天shader
  • 你可能不是很清楚,这里的mask究竟代表什么含义。仔细观察下图,不难发现mask其实就是我们所实现的效果
    image-20230516113552021
    image-20230516113628772
    image-20230516113653809

normal 混合

混合表面水珠normal 和流淌雨滴normal

image-20230516164640990

  • 采用Rain Drip作为alpha的原因:假定我们只考虑alpha为1/0的情况,若alpha为1,我们希望只有RainDrip效果没有RainDrop,以Lerp效果来说确实如此;若alpha为0,我们希望只有RainDrop效果没有RainDrop,从Lerp效果来说确实如此。但若以RainDrop作为alpha则不符合我们的条件

混合外部normal

  • 因为目前这两个normal只是内部实现的material function的normal,还需要与欲使用的材质的normal进行blend
    image-20230516200218640

水坑

image-20230516201231935

湿度控制

  • max():因为这三个效果是各自独立的材质函数,如果分开运算会使得这三效果不一致,我们需要求得以这三之一的max以达到最好且一致的效果

image-20230516201726278

吸水性

image-20230516204848047

reference

Rustling Leaves Shader - UE4 Materials 101 - Episode 12 - YouTube