柏林雜訊(Perlin noise)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值。 在电子游戏领域中可以透过使用Perlin噪声生成具连续性的地形;或是在艺术领域中使用Perlin噪声生成图样。由于Perlin本人的失误,Perlin噪声这个名词现在被同时用于指代两种有一定联系的的噪声生成算法。这两种算法都广泛地应用于计算机图形学,因此人们对这两种算法的称呼存在一定误解。下文中的Simplex噪声和分形噪声都曾在严肃学术论文中被单独的称作Perlin噪声。
本文仅讨论灰度图的情况。对于彩色图像的噪声生成,只要将同样的方法分别应用于各个颜色分量上,再加以合成即可。
Simplex噪声
生成噪声最通常的想法是为每个像素赋予一个随机的灰度值。如此产生的图像如下图左。
File:RandomNoise2D.png|使用随机方法产生的白噪声
File:RandomNoise2DFFT.png|左图的频谱
File:RandomNoiseSmoothed2D.png|对随机噪声进行柔化
File:RandomNoiseSmoothed2DFFT.png|左图的频谱
用随机法产生的噪声图像和显然自然界物体的随机噪声有很大差别,不够真实。1985年Ken Perlin指出;事实上,只要是在区间[0,1]内连续的函数f,有f(0)=1,f(1)=0且f'(0)=f'(1)=0的函数皆可做为插值函数。实际应用如下:设f为插值函数,插值结果为c_0f(1-t) + c_1f(t)。
对于二维的情况,可以将上述算法进行推广,即:
为所有坐标为 (x, y) 且 x, y 都是整数的点指定一个值,同时指定一个梯度,这些点将空间分成方格;
对于坐标轴为整数的点,即上述方格的顶点,将为它指定的值作为该点的值;对于某个方格内部的点 (x, y),用所在方格四个顶点的值和梯度进行插值。
例如,对于点 (x, y),令 i = \lfloor x \rfloor, j = \lfloor y \rfloor 它所在方格的四个顶点分别为: (i, j)、(i+1, j)、(i+1, j+1)、(i, j+1)。令 u=x-i, v = y-j,这四个顶点对点 (x, y) 的贡献可以用它们的梯度(g_{00}, g_{10}, g_{11}, g_{01})和 (x, y) 点与这四个顶点的方向((u, v)、(u-1, v)、(u-1, v-1)、(u, v-1))进行点积获得。但是在二维的情况下,插值更为复杂。首先需要对 (i, j) 和 (i+1, j) 两点在 x 方向插值,得到点 (x, j) 的值;之后对 (i, j+1) 和 (i+1, j+1) 两点在x方向插值,得到点 (x, j+1) 的值;最后对 (x, j) 和 (x, j+1) 在 y 方向插值,得到 (x, y) 的值。
在三维的情况下,需要进行七次插值。可以证明,插值次数随着维数的增长指数增长。
经典Perlin噪声基本满足Perlin提出的噪声条件。但是由于 3t^2 - 2t^3 导数中含有线性分量,在计算相邻点差时会体现出人工效果,不够自然。经典Perlin噪声在进行下文的分形和运算后效果不够自然
Simplex噪声
File:SimplexNoise2D.png|使用Simplex方法产生噪声
File:SimplexNoise2DFFT.png|左图的频谱
为了简化计算,方便使用硬件实现,Ken Perlin在2002年对他的方法进行了改进,改进的方法称为 Simplex 噪声。Simplex 噪声使用 6t^5-15t^4+10t^3作为插值函数,杜绝了导数中的线性部分。另外,Simplex 噪声算法有效地降低了插值次数。
如上文,二维经典Perlin噪声将二维空间用正方形填充,用四个顶点进行3次插值,而Simplex噪声将二维空间用等边三角形填充,使用三个顶点进行插值。三维经典Perlin噪声将三维空间用立方体进行填充,使用8个顶点进行7次插值,三维Simplex噪声使用正四面体填充空间,用4个顶点进行插值。对于更高维(N维)的情况,经典Perlin噪声将空间用超立方体填充,顶点数目是2^N,而Simplex噪声使用高维正三角形(称为Simplex)进行填充,顶点数目为N+1。Simplex噪声插值次数随维数增长线性增长。
对于二维的情况,使用正三角形填充空间使得直接判断某点落在哪个正三角形中,计算该三角形的顶点位置变得复杂。在实现上通常通过坐标变换将正三角形映射成直角三角形。使用该方法进行变换可以使用和经典Perlin噪声相同的方法对顶点进行求值]]
Perlin噪声可以用来模拟自然界中的噪声现象。由于它的连续性,如果将二维噪声中的一个轴作为时间轴,得到的就是一个连续变化的一维函数。同样的也可以得到连续变化的二维图像。该噪声可以用来模拟人体的随机运动,蚂蚁行进的线路等。另外,还可以通过计算分形和模拟云朵,火焰等非常复杂的纹理。。
Perlin噪声对各个点的计算是相互独立的,因此非常适合使用图形处理器进行计算。OpenGL在GLSL中定义了一维至四维的噪声函数noise1、noise2、noise3、noise4,在该规范中噪声的性质与上述Perlin提出的性质相同。在Mesa 3D实现中,这一组函数是使用Simplex算法实现的。在硬件的实现中,噪声的生成可以达到实时效果。
分形噪声
分形噪声是上述Perlin 1985年的文章中提出的将符合上文所述三条件的噪声通过计算分形和构造更复杂效果的算法。
分形噪声可以用来模拟自然界的自相似过程,包括海岸线,地形,海浪等。分形噪声的原理是利用Perlin噪声频率受限的特性,通过不断叠加更高频率的Perlin噪声达到自相似的效果。
一维分形噪声
在一维的情况下,设噪声函数为noise(x),则通过noise(2x), noise(4x)等就可以构造更高频率的噪声。
下图左边是一维Perlin噪声频率频率在不断倍增,振幅不断倍减的情况,右图是左边这些函数求和的图像。
File:PerlinNoise1D1x-32x.png|6条频率倍增的一维Perlin噪声
File:PerlinNoise1DFacalSum.png|一维Perlin噪声分形和右边的图像是自相似的,将它放大会得到和原图相似的效果。
从数学上描述分形噪声,则是:
\sum_t{\frac{\text{Noise}(2^i \text{point})}{2^i}}
分形噪声有时也被称作1/f噪声。
二维分形噪声
对于二维的情况,可以使用类似的方法进行分形和运算,产生的效果类似于云层,如下图所示。
File:PerlinNoise2D1x.png|二维Simplex噪声原函数
File:PerlinNoise2D1x2x.png|二维Simplex噪声叠加2倍频
File:PerlinNoise2D1x2x4x.png|二维Simplex噪声叠加到4倍频
File:PerlinNoise2D1x2x4x8x16x32x64x128x.png|二维Simplex噪声叠加到128倍频
对分形和函数进行一些小修改可以模拟各种复杂效果。
{2^i}} ||
|-
| \sin(x + \sum_t{+ \frac{\left|Noise(2^i point)\right|}{2^i}}) ||
|-
|}
同上,将三维分形噪声中的一个轴作为时间轴,可以构造连续动态的噪声效果。
参考文献
外部链接
- [http://portal.acm.org/citation.cfm?id=325247 An image synthesizer] Ken Perlin在1985年研究像素渲染器时提出了噪声的性质
- [http://www.cs.umbc.edu/~olano/s2002c36/ch02.pdf Noise Hardware] Ken Perlin在2002年研究用硬件发生噪声时改进了原有的噪声生成算法,新算法称为Simplex噪声
- [http://staffwww.itn.liu.se/%7Estegu/simplexnoise/simplexnoise.pdf Simplex noise demystified]对Simplex noise进行详细的介绍
- [https://web.archive.org/web/20081003235153/http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html Implementing Improved Perlin Noise] Ken Perlin为NVIDIA GPU Gems第一版撰写了一篇关于Perlin噪声的短文
- [https://web.archive.org/web/20081004125133/http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter26.html Implementing Improved Perlin Noise] NVIDIA GPU Gems第二版中给出的使用Cg生成Perlin噪声的程序
- [https://web.archive.org/web/20080724063449/http://freespace.virgin.net/hugo.elias/models/m_perlin.htm Perlin Noise]关于一维Perlin噪声和分形噪声的简单介绍
- [http://mrl.nyu.edu/~perlin/ Ken Perlin的主页]
评论 (0)