我正在尝试在C ++中实现2D Perlin噪声生成,而我发现的一些实现根本不使用种子(here,here或here)。其他实现采用种子值来根据噪声值获得不同的噪声。
但是我找到example code,其中一个将种子值添加到函数参数中,计算每个八度音程的噪声值(参见链接代码中的PerlinNoise :: Total())。另一个使用3D种子函数并使用固定的种子值作为z值(刚刚找不到示例)。其他文章建议使用其他噪音功能。
所以我的问题是,为Perlin噪音生成添加种子值的最佳方法是。给定相同的种子值,应生成相同的噪声值。如果解决方案是使用自定义噪声函数,我会感兴趣它是否可以使用Boost.Random(或C ++ 11的标准C ++库类)实现。
编辑:用“最佳”方式回答我的意思:什么是给我Perlin噪音的最佳方式,就像它应该工作一样,例如:梯度噪声函数。
答案 0 :(得分:16)
由于没有人会从评论中写出答案,我正在尝试自己。请在我正确的时候投票,否则请评论:)
有几种实现和示例代码(尝试)实现Perlin噪声。首先,Ken Perlin本人就有Improved Noise reference implementation。
噪声函数需要三个双精度值并输出一个值。当使用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 *种子,y + 64.0 *种子)。
然后有一个implementation的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();
}
随机数生成器有一些ctors,其中一个取一系列uint32_t来确定RNG的初始状态。
还有一些库会产生相干噪声,例如libnoise,这可能会对此有所帮助。
我没有问过单纯形噪声,但是我发现的那个implementation (from Stefan Gustavson)使用了类似Ken Perlin的参考实现的类似技术(一些预先计算的表),并且可以像上面的情况1那样播种。罗宾逊评论员在生成查找表时提到了种子,但我不知道它会如何起作用。