我已经阅读了一些有关Perlin噪声的文章,但是每篇文章似乎都有自己的实现方式:
在this文章中,梯度函数返回单个double值。
在this文章中,渐变是作为3D向量生成的。
在this文章中,生成了256个随机梯度向量的静态数组,并使用置换表选择了一个随机的梯度向量,然后讨论了球形梯度的更复杂的细节。
这些只是我看到的几篇文章。在使用同一算法的所有这些变体中,我应该使用哪一种,或者哪种才适合于什么目的?
我使用每种技术都生成了地形和高度图,它们各自的输出在各自的方式上存在很大差异,我无法确定我是否做对了,因为我不知道在输出中寻找什么(因为最后只是随机值)
我只是在寻找何时使用什么的背景,因此任何见解都将非常有用
答案 0 :(得分:1)
有多种方法可以实现相同的算法,有些方法比其他方法更快或更慢,有些则更容易理解。单看The original implementation by Ken Perlin很难理解。因此,您链接的某些文章(包括我写的#2,是的!)试图简化实现,使其更易于理解。
但是最后,它的算法完全相同:
在文章#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));