最好的方法添加种子到Perlin噪音? [英] Best way to add seed to Perlin noise?

查看:126
本文介绍了最好的方法添加种子到Perlin噪音?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在C ++中实现2D Perlin噪声生成,一些实现我发现根本没有使用种子(此处此处在这里)。其他实现取种子值,根据噪声值得到不同的噪声。



但是,我发现示例代码,其中将种子值添加到计算每个八度音阶的噪声值的函数参数(参见链接代码中的PerlinNoise :: Total())。另一个使用3D种子函数,并使用固定的种子值作为z值(刚才找不到示例)。其他文章建议使用其他噪声函数。



所以我的问题是,最好的方法是添加一个种子值到Perlin噪声生成。给定相同的种子值,应该产生相同的噪声值。如果解决方案是有自定义的噪声函数,我会感兴趣的是,如果它可以使用Boost.Random(或C ++ 11的标准C ++库类)实现。



编辑:回答我的意思与最好的方式:什么是最好的方式,给我Perlin噪音,这是应该工作,例如一个梯度噪声函数。

解决方案

因为没有人会写评论的答案,请注意,当我正确,不评论时:)



有几个实现和示例代码(尝试)实现Perlin噪声。首先,有来自Ken Perlin自己的改进噪声参考实现



情况1:改进的噪声参考实现



噪声函数需要三个double值并输出一个值。当使用x和y生成2D位图,并且保持z恒定时,得到公知的Perlin噪声模式。当z在0.0和1.0之间变化时,噪声云似乎缓慢地改变。因此,设置z的种子方法,例如。 z = 10.0 * seed 可以用于播种。



这个:如果你总是只是在[0.0; 64.0 [对于x和y,当调用噪声函数:noise(x + 64.0 * seed,y + 64.0 * seed)时,可以通过向x,y或两者添加偏移来产生噪声。



案例2:教程风格的Perlin噪音代码



然后有一个

 函数Noise2(整数x,整数y)
n = x + y * 57
n =(n <13)
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,确定RNG的初始状态的uint32_t。



还有生成相干噪声的库,例如 libnoise ,这在这里可能有帮助。



单纯噪声



不要求单纯形噪声,而是一个实现(来自Stefan Gustavson)我发现使用类似的技术(一些预计算表)像Ken Perlin的参考实现,并且可以像上面情况1一样播种。评论者Robinson在生成查找表时提到种子,但我不知道这将如何工作。


I'm trying to implement 2D Perlin noise generation in C++, and some implementations I found use no seed at all (here, here or here). Other implementations take a seed value to get different noise depending on the noise value.

However I found example code where one added the seed value to the function parameters calculating the noise value for each octave (see PerlinNoise::Total() in the linked code). Another one uses a 3D seed function and uses the fixed seed value as the z value (couldn't find the example just now). Other articles suggest using other noise functions.

So my question would be, what the best way would be to add a seed value to Perlin noise generation is. Given the same seed value, the same noise values should be generated. If the solution would be to have a custom noise function, I would be interested if it could be implemented using Boost.Random (or C++11's Standard C++ Library classes).

Edit: To answer what I mean with "best" way: What's the best way that gives me Perlin noise like it was supposed to work, e.g. a gradient noise function.

解决方案

Since no one is going to write up an answer from the comments, I'm trying myself. Please upvote when I'm correct, comment when not :)

There are several implementations and example code that (try to) implement Perlin noise. First, there is the Improved Noise reference implementation from Ken Perlin himself.

Case 1: Improved Noise reference implementation

The noise function takes three double values and outputs a value. When generating a 2D bitmap using x and y, and keeping z constant, one gets the well known Perlin noise pattern. When z is varied between 0.0 and 1.0, the noise clouds seem to "change" slowly. So a seeding method that sets z, e.g. z = 10.0 * seed, could work for "seeding".

Another way to seed the noise function would be this: If you always just get noise in a range of [0.0; 64.0[ for x and y, one could seed the noise by adding an offset to x, y or both when calling the noise function: noise(x + 64.0*seed, y + 64.0*seed).

Case 2: Tutorial style Perlin noise code

Then there is an implementation of Perlin noise (adapted and used in many other Perlin noise tutorials) that have a base noise function like this (pseudocode):

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

My main skepticism came from the magic numbers and the trust of the authors of these pages that the formula leads to uniformly distributed noise. Other authors added the seed value somewhere in this formula.

The solution to add a seed to this type of Perlin noise implementation is to write a function that uniformly distributes output values for given x and y values (and by returning the same value for the same x and y values, of course). This function can be written using Boost.Random (code not tested):

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();
}

The random number generator has some ctors, among them one that takes a range of uint32_t's that determine the initial state of the RNG.

There also are libraries that generate coherent noise, such as libnoise, that may be of help here.

Simplex Noise

I didn't ask of Simplex noise, but the one implementation (from Stefan Gustavson) I found uses a similar technique (some precomputed tables) like Ken Perlin's reference implementation, and could be seeded just like case 1 above. Commenter Robinson mentioned seeding when generating the look-up table, but I don't know how that would work.

这篇关于最好的方法添加种子到Perlin噪音?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆