佩林噪声不同的实现方式

时间:2020-11-11 06:32:58

标签: math perlin-noise

我已经阅读了一些有关Perlin噪声的文章,但是每篇文章似乎都有自己的实现方式:

  1. this文章中,梯度函数返回单个double值。

  2. this文章中,渐变是作为3D向量生成的。

  3. this文章中,生成了256个随机梯度向量的静态数组,并使用置换表选择了一个随机的梯度向量,然后讨论了球形梯度的更复杂的细节。

这些只是我看到的几篇文章。在使用同一算法的所有这些变体中,我应该使用哪一种,或者哪种才适合于什么目的?

我使用每种技术都生成了地形和高度图,它们各自的输出在各自的方式上存在很大差异,我无法确定我是否做对了,因为我不知道在输出中寻找什么(因为最后只是随机值)

我只是在寻找何时使用什么的背景,因此任何见解都将非常有用

1 个答案:

答案 0 :(得分:1)

有多种方法可以实现相同的算法,有些方法比其他方法更快或更慢,有些则更容易理解。单看The original implementation by Ken Perlin很难理解。因此,您链接的某些文章(包括我写的#2,是的!)试图简化实现,使其更易于理解。

但是最后,它的算法完全相同:

  1. 接受输入,计算包含输入点的正方形的4个角的坐标(对于2D Perlin噪波,如果使用3D版本,则为立方体)
  2. 计算所有这四个变量的随机值(首先为每个变量分配一个随机梯度矢量(2D中有4种可能性:(+ 1,+1),(-1,+1),(-1 ,-1)和(+1,-1)),然后计算此随机梯度向量与从正方形角到输入点的向量之间的点积)
  3. 最后,在这4个随机值之间进行平滑插值以获得最终值

在文章#1中,grad函数直接返回点积,而在文章#2中,将创建矢量对象,并调用点积函数以明确显示正在执行的操作(这可能会慢一些比其他实现方式要好,因为每次要运行算法时都会创建并短暂使用很多矢量对象)。

2种实现是否产生相同的地形/高度图取决于它们是否为正方形/立方体的每个角(点积的结果)生成相同的随机值。如果2个算法为网格上的每个整数点(所有可能的正方形/立方体的所有角)生成相同的随机值,则它们将产生相同的结果。 Ken Perlin的原始实现以及这3篇文章都使用整数数组为每个角(从4个可能的选择中)生成随机梯度矢量来计算点积。因此,从理论上讲,如果数组相同,则它们将产生相同的结果。 (除非某些实现方法使用另一种方法来生成随机向量,否则)。

我不确定是否能回答您的问题,所以不要犹豫,问其他问题:)

编辑:

通常,您不会单独使用Perlin噪声。因此,对于每个所需的最终值(例如,高度图纹理中的单个像素),您将多次调用噪波函数(八度)。例如:

float finalValue = 0.0f;
float amplitude = 1.0f;
float frequency = 1.0f;
int octaveCount = 8;

for (int octave = 0; octave < octaveCount; ++octave) {
    finalValue += amplitude * noise(x * frequency, y * frequency, z * frequency);
    amplitude *= 0.5f;
    frequency *= 2.0f;
}

// Do something fun with 'finalValue'

频率,振幅和八度数是您可以用来产生不同值的最常见参数。

例如,如果要生成地形,则需要多个八度。第一个将产生山脉的粗糙形状,因此您需要一个高振幅(在示例代码中为1.0)和低频(在上述代码中也为1.0)。但是,只有这个八度会导致没有任何细节的真正平滑的地形。对于那些小细节,您可能需要更多的八度音阶,但是需要更高的频率(因此,在相同的输入范围内(x,y,z),Perlin噪声值会有更多的起伏),而更低振幅(您需要一些小细节,因为如果您要与第一个八度音阶(在示例代码中为1.0)保持相同的振幅,那么实际上会有很多起伏紧密并非常高,这将导致真的很粗糙(想象一下,您每走几米就会跌落100米,80度会下降并倾斜)

您可以使用这些参数来获得不同的结果。您还可以查找称为“域扭曲”或“扭曲噪声”的东西。基本上,您将噪声函数称为噪声函数的输入。喜欢而不是打电话:

float result = noise(x, y, z);

您会这样称呼:

// The numbers used are arbitrary values, you can just play around until you get something cool
float result = noise(noise(x * 1.7), 0.5 * noise(y * 4.1), noise(z * 2.3));

这可以产生really interesting results

相关问题