简单聊聊 Perlin 噪声(下篇)

程序开发中总会用到随机方法,一般的随机方法虽然通用,但是产生的随机数又因为过于"随机",不适合用来生成平滑连续的随机数据(譬如自然地形的高度),这个时候我们便需要使用特殊的随机方法了, Perlin 噪声便是一种能够产生平滑(随机)数值的随机方法.

Perlin 噪声

理解了二维的 Value 噪声,我们就可以进一步来看 二维的 Perlin 噪声了.

二维 Perlin 噪声的生成方式和 二维 Value 噪声的生成方式大体相同,二维 Perlin 噪声也是根据给定的坐标选取对应的正方形,并将该正方形的四个顶点作为插值端点,但是在 Perlin 噪声中,端点并不是直接对应一个随机值,而是对应一个二维(梯度)向量,另外我们再取端点到给定坐标的方向(距离)向量,这两个向量的点积才是我们用来插值的随机值,说的有些抽象,我们可以看看下面的示意图(蓝色向量为梯度向量,红色向量为距离向量):

简单聊聊 Perlin 噪声(下篇)

除此之外, 二维 Perlin 噪声的生成过程就和 二维 Value 噪声的生成过程就没有什么不同了(ar,br,cr,drar, br, cr, dr 为四个端点对应的梯度向量, av,bv,cv,dvav, bv, cv, dv 为四个端点与给定坐标形成的距离向量,uuxx 轴原始的线性插值系数, vvyy 轴原始的线性插值系数(实际上,通过 uu, vv 我们就能得到 av,bv,cv,dvav, bv, cv, dv) ):

u=6u515u4+10u3v=6v515v4+10v3a=dot(ar,av)b=dot(br,bv)c=dot(cr,cv)d=dot(dr,dv)e=(1u)a+ubf=(1u)c+udr=(1v)e+vf u' = 6u^5 - 15u^4 + 10u^3 \\ v' = 6v^5 - 15v^4 + 10v^3 \\ a = dot(ar, av) \\ b = dot(br, bv) \\ c = dot(cr, cv) \\ d = dot(dr, dv) \\ e = (1 - u')a + u'b \\ f = (1 - u')c + u'd \\ r = (1 - v')e + v'f

下面是二维 Perlin 噪声的示意图(其中各个坐标点的明暗程度代表了相应的随机值):

简单聊聊 Perlin 噪声(下篇)

(注:上图展示的是实际生成的二维 Perlin 噪声数据,显示上没有做额外的插值处理,所以看起来会有明显的边界)

Simplex 噪声

Simplex 噪声是 Perlin 噪声的改进版,(二维)Perlin 噪声通过选取对应的正方形(方形)来获取插值端点,(二维)Simplex 噪声则是选取对应的三角形(单形)来获取插值端点.这样做的好处是单形的顶点数是随着维度线性增长的,而方形的顶点数是随着维度指数增长的,基于此,Simplex 噪声的计算复杂度要比 Perlin 函数低不少,但另一方面,在 Perlin 噪声中,从给定坐标获取对应的方形非常简单,只需要对坐标取底(floor)即可,但在 Simplex 噪声中,从给定坐标获取对应的单形则比较复杂.

简单聊聊 Perlin 噪声(下篇)
(二维单形示例)

Simplex 噪声中随机值的生成也和 Perlin 噪声有所不同,有兴趣进一步了解的朋友可以从这里看起~

多维 Perlin 噪声

从 二维 Perlin 噪声扩展到 多维 Perlin 噪声还是比较简单的,譬如 三维 Perlin 噪声,使用的是立方体(三维中的方形)的 8 个顶点作为插值端点,更高维度的话,则是使用 超立方体 的各个端点作为插值端点,端点个数与维度(DD)呈指数关系(2D2^D)

一维 Perlin 噪声

说了多维 Perlin 噪声,那 一维 Perlin 噪声如何生成呢(毕竟一维坐标下并没有向量的概念)? 实际上,我们还是可以在一维坐标上"定义"二维向量,只需要将该二维向量的 yy 轴数值设置为 00 即可,同样的,我们也可以依此计算出距离向量, 这样我们就可以沿用 二维 Perlin 噪声 的生成方法来生成 一维 Perlin 噪声了.

这里有一份相关的代码实现,有兴趣的朋友可以看看~

分形噪声

很多讲解 Perlin 噪声的文章也会提到 分形噪声,不过分形噪声本质上并不是某种特定类型的噪声(自然也不是 Perlin 噪声),而更应该说是一种噪声的叠加方法,他是将很多个不同频率,不同振幅的基础噪声(譬如 Value噪声, Perlin噪声 等等)相互叠加,最后形成的一种噪声(统称为分形噪声).

更多细节可以从这里开始了解~

更多资料