Perlin 噪声
KenPerlin(1985a,2002)KenPerlin(1985a,2002) 定义的噪声函数是最常用的噪声函数,称为 Perlin 噪声。PerlinPerlin 噪声在全部 (x,y,z)(x,y,z) 整形顶点处的参数值都为 00,变化源自各顶点间的梯度向量,然后再进行平滑插值。
计算四个顶点的导数,再进行平滑的表面插值
perlin噪声应当满足的性质:
- 1. 旋转统计不变性。(不管我们怎么旋转它的域,它都有同样的统计特性)
- 2. 频率带通有一定界限。(它没有明显的大或者小的特征,而是在一定范围内)
- 3. 平移统计不变性。(不管我们如何平移它的域,它都有同样的统计特性)
计算方法
1.预处理:考虑x,y,z空间中所有点的集合(坐标为整数),我们称这个集合为整数格。现在我们为整数格的每个点附一个(x,y,z)上的伪随机梯度值,也就是一个向量,并且要将其 处理成单位向量。
2.如果(x,y,z)处在整数格上,那么此处的噪声就是d。
3.如果(x,y,z)不在整数格上,我们计算光滑插值系数。
具体的插值方法如下,以二维为例,我们要找到这个点周围的四个整数点,然后我们得到四个值,横坐标为bx0 ~ bx1,纵坐标为by0 ~ by1。点到bx0在x轴上的距离为rx0,到by0在y轴上的距离为ry0。perlin给出了一个缓和曲线使得线性插值连贯。能使得一阶导数连续的缓和曲线函数 (最初的版本) : s_curve(t) ( t * t * (3. - 2. * t) )之后分别将rx0和ry0传入缓和曲线,得到一个新的值sx和sy。
接下来做一个双线性插值,sx和sy就是第一步线性插值的系数,但是计算得到系数之后,我们还需要插值的起点和终点。他们的计算方法如下:
- 求(rx0,ry0)与左上角点的梯度b00的点乘,得到起点u,求(rx0 + 1,ry0)与右上角点的梯度b10的点乘,得到终点v,以uv为两端,sx为插值系数,做线性插值,得到a
- 求(rx0,ry0 + 1)与左下角点的梯度b01的点乘,得到起点u,求(rx0 + 1,ry0 + 1)与右下角点的梯度b11的点乘,得到终点v,以uv为两端,sx为插值系数,做线性插值,得到b
- 最终,对a和b进行线性插值,插值系数为sy,得到最终的结果。
以上算法步骤中,先对x轴还是先对y轴插值其实是无所谓的。最终得到的柏林噪声分布在 -1 ~ 1之间,我们可以把它映射到我们需要的颜色区别(比如0 ~ 255 或 0 ~ 1)得到对应的颜色。
二维拓展到三维,柏林噪声的生成方法伪代码可以概括如下:
Float Noise(Float x, Float y, Float z) {
<计算八个顶点整数坐标,以及偏移量>
<计算梯度权值>
<权重进行三线性插值>
}
GEM这篇文章提到的改进点概括起来是两点:
1.更换曲线函数为二次偏导连续的:s_curve(t) ( t * t * t * (6 * t * t - 15 * t + 10) ),从而解决使用噪声的导数时出现失真的视觉效果,例如制作凹凸贴图时。
2.将256大小的伪随机查找表改成大小为12,值为立方体12条边中点。从而解决噪声函数的结果中产生不希望的高频