由于没有人会从评论中写出答案,我正在尝试自己。正确时请点赞,错误时请评论:)
有几个实现和示例代码(尝试)实现 Perlin 噪声。首先,Ken Perlin 本人提供了改进的噪声参考实现。
案例 1:改进的噪声参考实现
噪声函数采用三个双精度值并输出一个值。当使用 x 和 y 生成 2D 位图并保持 z 不变时,就会得到众所周知的 Perlin 噪声模式。当 z 在 0.0 和 1.0 之间变化时,噪声云似乎“变化”缓慢。因此,设置 z 的播种方法,例如z = 10.0 * seed
,可以用于“播种”。
播种噪声函数的另一种方法是:如果你总是得到 [0.0; 范围内的噪声;64.0[ 对于 x 和 y,可以通过在调用噪声函数时向 x、y 或两者添加偏移量来播种噪声:噪声(x + 64.0*seed,y + 64.0*seed)。
案例 2:教程风格的 Perlin 噪声代码
然后是 Perlin 噪声的实现(在许多其他 Perlin 噪声教程中改编和使用),它具有这样的基本噪声函数(伪代码):
function Noise2(integer x, integer y)
n = x + y * 57
n = (n<<13) ^ n;
return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589)
& 7fffffff) / 1073741824.0);
end function
我的主要怀疑来自神奇的数字和这些页面作者的信任,即公式会导致均匀分布的噪声。其他作者在这个公式的某处添加了种子值。
为这种类型的 Perlin 噪声实现添加种子的解决方案是编写一个函数,该函数为给定的 x 和 y 值均匀分布输出值(当然,通过为相同的 x 和 y 值返回相同的值)。可以使用 Boost.Random 编写此函数(代码未测试):
double Noise2(int x, int y)
{
uint32_t seeds[3] = { uint32_t(x), uint32_t(y), seed };
boost::mt19937 rng(seeds, seeds+3);
boost::uniform_real<> dist(0.0, 1.0);
boost::variate_generator<boost::mt19937&, boost::uniform_real<> >
die(rng, dist);
return die();
}
随机数生成器有一些 ctor,其中一个采用 uint32_t 的范围来确定 RNG 的初始状态。
还有一些生成连贯噪声的库,例如libnoise,在这里可能会有所帮助。
单纯形噪声
我没有询问 Simplex 噪声,但我发现的一个实现(来自 Stefan Gustavson)使用了类似的技术(一些预先计算的表),如 Ken Perlin 的参考实现,并且可以像上面的案例 1 一样被播种。评论者 Robinson 在生成查找表时提到了播种,但我不知道它是如何工作的。