LWDW!

Learn the work from doing the work🍺

柏林噪声(perlin noise)都是怪物么!
Posted on 2018-03-30

前言

不知道各位有没有见过这样歪歪扭扭的动画效果,非常有趣不是么:

image.png

所以要如何实现这样的效果呢——“随机!”,是的,我反正是这么想的,于是一个Math.random()怼上去,结果是线条像抽风一样扭成一团.....自然,线条是由控制点连接起来的,对其叠加一个随机数,前后联系的线条自然会显得支离破碎,或者说:“不自然”。就如同现实中的海浪、云朵、山脉地形一样,他们看起来都是随机的,却又有一种连续性!但是,为了应用到计算机图像中,我们要如何抽象这样的现象呢!

柏林噪声(perlin noise)与分形噪声!

如果你想看的话,这里是柏林噪声的定义

看得懂吗?看不懂吧,到了俺的画画时间!

一维曲线

上面有三张图,姑且称为图一(左上)图二(左下)图三(右)好了(画的时候怎么不标好啊!)。

图一是这样画出来的:在一维坐标轴上,选择等距的无穷个点(这里就假设为整数啦),将空间划分为等长的线段,为每个点随机指定一个值(这个值的范围就是振幅amplitude)和一个梯度(在一维上,梯度就是斜率没错!)。然后“对于坐标值为整数的点,将该点对应的值作为噪声图像上该点的值;对于坐标值不为整数的点,将相邻两点的值和根据梯度进行插值运算,获得该点的值”——这个图像在地球人看来,就是一堆点舒舒服服地给他们平滑连接起来。而这,就是一维柏林噪声图像,全剧终。

喂等等!标题不是这么写的啊!!

好吧,图二也一样是柏林噪声的一维图像,只不过取点的间隔更小(也就是频率更高),振幅也更小而已,但是你也看到那张融合卡了吧!没错,通过叠加更高频率的柏林噪声,我们就可以得到图三那样效果更复杂的图像,也更加符合自然界中海岸线,地形,海浪等特征,顺带一提,我们一直形容的很模糊的特征有个术语,叫自相似

自相似科赫曲线

二维

关于具体算法,仍是在一维的基础上进行衍生:

  1. 为所有坐标为(x, y)x, y都是整数的点指定一个值,同时指定一个梯度,这些点将空间分成方格;
  2. 对于坐标轴为整数的点,即上述方格的顶点,将为它指定的值作为该点的值;对于某个方格内部的点(x, y),用所在方格四个顶点的值和梯度进行插值。

但没人看得懂这玩意儿不是么,那直接感受下:

See the Pen perlin noise-two dimensional by Zhouyi (@padfoot_07) on CodePen.

左侧是二维柏林噪声,右侧是纯随机,所以二维图像中的每个点看起来都受其周围点的影响,这有些类似于云不是么233

让我见识一下吧,noise的性能

不要被上述图像束缚了思考,经典柏林噪声建议使用作为插值函数,但这并不妨碍俺们使用其他函数,如(图像来源:不只是噪音):

使用指数插值

指数插值

使用三角函数插值

三角函数插值

我们还可以对其进行叠加,总之可能性是无限的啊!

实际运用

以上我们仅仅是对噪声数值本身进行了可视化,事实上对于其特性的使用,完全可以放飞自我啊!

(以下建议使用pc浏览)

比如将其作为速度场影响粒子流动:

See the Pen perlin noise-flow by Zhouyi (@padfoot_07) on CodePen.

模拟波浪:

See the Pen Water shader by Arnaud Rocca (@arnaudrocca) on CodePen.

浮夸的滤镜:

See the Pen Fun with perlin by Thibaut (@Thibka) on CodePen.

为了各位的流量考虑就不再多放辣,总之是很有搞头,相信都get到那个点了。


当初想要实现这样的效果折腾了几天也没搞定,到底还是没能摸清其本质特征啊orz,好个大坑慢慢填......