用 Shader 写个完美的波浪
本文最后更新于:2020年9月7日 凌晨
前言
皮皮最近接到了一个小需求:
👧美术小姐姐:皮皮皮皮,你能不能做奶茶?
😱我:???
👧美术小姐姐:就是那种,奶茶的轮廓加上动态水波纹~
🙄我:吓死我还以为让我做喝的奶茶…
👧美术小姐姐:炒鸡多图片都需要这种效果,用动画的话工作量太大了!
🤓我:波浪效果是吧,小意思,一个月的奶茶就够了,或者扫码提需求~
👧美术小姐姐:皮?🔨🔨🔨
🤪我:卒~
俗话说:遇事不决,量子力学写虽得儿。
根据我多年喝奶茶的经验,像这种效果用 Shader 做就再简单不过了,最终的效果如下:
趁此机会,本篇文章就来与小伙伴们分享动态波浪 Shader 的原理和制作思路吧。
要注意的是,这是一篇偏入门的文章,写得会相对比较详细,尽量让不懂 Shader 的小白也可以看懂,这也是我写文章的一贯风格。
好了,话不多说,进入正题~
正文
🧐整体思路
看到波浪的表现特点我第一时间想到的就是正弦曲线(或者说是正弦波,又让我想起了示波器)。
🔢正弦曲线(Sinusoid)
正弦曲线是三角函数中的一种正弦(Sine)比例的曲线。正弦曲线表现为一条波浪线,形状犹如海上完美的波浪。
标准的正弦函数公式为:
$$
y = \sin(x)
$$
正弦函数属于周期函数,其值域为 [-1, 1]
。
如下图就是一个纯正标准的正弦曲线:
而一般我们常用的正弦曲线公式为:
$$
y = A \cdot \sin(\omega x ± \phi) + k
$$
这条公式比标准公式多了几个常数,含义如下:
A
:振幅(Amplitude),曲线最高点与最低点的差值,表现为曲线的整体高度ω
:角速度(Angular Velocity),控制曲线的周期,表现为曲线的紧密程度φ
:初相(Initial Phase),即当x = 0
时的相位,表现为曲线在坐标系上的水平位置k
:偏距(Offset),表现为曲线在坐标系上的垂直位置
相位(Phase):上方公式中的
ωx±φ
部分称为相位,相位发生在周期性的运动之中,最直接的理解就是角度。
☕稍加思索
有了公式之后,我们可以尝试调整其中的常数来改变函数曲线的形态。
在查看下方的示例时,请尝试将曲线形态的变化与图中右上角公式的变化关联起来。
改变曲线的高度
我们可以调整常数 A
(振幅)来改变曲线的值域(值域为 [-A, A]
):
改变曲线的周期
我们可以调整常数 ω
(角速度)来改变曲线的周期:
改变曲线的水平位置
我们可以调整常数 φ
(初相)来改变曲线的水平位置:
多说一句
其实对于“曲线的水平位置”这个描述是不太准确的,因为初相实际上改变的是当 x = 0
时的相位,也就直接影响函数曲线在 x = 0
处的位置。
所以说曲线的位置并没有真正改变,而只是曲线的形态发生了改变。
但是由于正弦曲线的周期性特点,曲线的这种形态变化看起来像是曲线进行了位移。
改变曲线的垂直位置
我们可以调整常数 k
(偏距)来改变曲线的垂直位置:
🤠动手实现
明白了正弦曲线的特性之后,接下来我们需要做的就是在代码中运用正弦函数。
慢着!正弦曲线确实如海上完美的波浪般优美,但是正弦曲线是静态的,我们要的波浪是动态的啊!
🌊如何让曲线动起来
别慌!还记得我们可以调整初相来改变曲线的“水平位置”吗?
既然如此,我们可以给初相加入时间因素,使得 y 值可以随着时间的增加发生周期性变化,看起来就像是曲线在进行“水平位移”。
就像这样:
得到新的公式
加入时间因素 t
后的曲线公式:
$$
y = A \cdot \sin(\omega x ± \phi t) + k
$$
🧩On Shadertoy
小贴士:由于 GLSL ES 没有办法进行调试,所以写 Shader 时可以先在 Shadertoy 中编写并在线预览,显著提高效率。
一切尽在注释中,简单详细且直观。
主函数代码如下:
1 |
|
预览效果如下(🌊是不是有内味儿了):
🥥On Cocos Creator
我们主要关注片段着色器部分,这里就不展示整个 Effect 文件的代码了,直接上传送门吧。
Effect 文件:https://gitee.com/ifaswind/eazax-ccc/blob/master/resources/effects/eazax-sine-wave.effect
代码核心其实就是套用了公式,我们代码注释一起看吧。
一切尽在注释中,简单详细且直观。
片段着色器代码如下:
1 |
|
运行效果如下:
使用 cc.tween
动态改变高度(偏距)实现波浪进度条:
1 |
|
在线预览:https://ifaswind.gitee.io/eazax-cases?case=sineWave
SineWave 组件:https://gitee.com/ifaswind/eazax-ccc/blob/master/components/effects/SineWave.ts
专题
《一起学 Shader》这个专题断更了一段时间,很对不起小伙伴们,是时候续上了😹
传送门
更多分享
公众号
😺菜鸟小栈
💻我是陈皮皮,这是我的个人公众号,专注但不仅限于游戏开发、前端和后端技术记录与分享。
💖每一篇原创都非常用心,你的关注就是我原创的动力!
Input and output.