随机生成二维噪声

时间:2014-09-01 01:27:19

标签: c random procedural-generation

我试图生成一个从[x,y]坐标程序生成的随机2D网格(而不是预先生成一个2D数组)。原因是地图可能很大,并且很可能实际上不需要大部分网格。

这是我到目前为止所拥有的:

double value_at(Grid *grid, int seed, int x, int y) {
  srand(seed + x + y * grid->width);
  return (double)rand() / (RAND_MAX + 1.0);
}

更新:要求是value_at具有参考透明度(尽可能)。所以以下内容必须成立:

int i = value_at(grid, seed, 100, 100);
int j = value_at(grid, seed, 100, 100);

assert(i == j);

换句话说,如果我使用相同的参数调用value_at,无论我在程序执行期间调用它多少次,总是都应该给出相同的结果。 这是因为我试图生成随机地形,这将涉及不同网格点之间的插值;用户也可能会重新访问网格中的某个点。

它正确地生成了网格,但是我在输出中看到了很多规律:

Grid 1 Grid 2

你可以看到有一种" grain"发送线条通过输出对角移动。

我正在做一些研究,但我在寻找方法时遇到了一些麻烦。有没有人知道如何让网格更加随机"?

更新:感谢ldgabbay提供的链接,我添加了一个简单的旋转哈希函数,如下所示:

int simple_hash(int * is, int count) {
  // this contains a bunch of arbitrarily chosen prime numbers
  int i;
  unsigned int hash = 80238287;

  for (i = 0; i < count; i++){
    hash = (hash << 4) ^ (hash >> 28) ^ (is[i] * 5449 % 130651);
  }

  return hash % 75327403;
}

然后value_at函数如下所示:

double value_at(Grid *grid, int seed, int x, int y) {
  int is[] = {x, y, seed};
  srand(simple_hash(is, 3));
  return (double)rand() / (RAND_MAX + 1.0);
}

以下是它生成的一些示例网格:

Grid 3 enter image description here

1 个答案:

答案 0 :(得分:1)

我认为使用srand来确定value_at确定性是一个微妙的缺陷。通常,随机数生成器被播种一次,并且从其中出来的数字是伪随机的。但是,在这种方法中,您正在查看随机数生成器中出现的第一个随机数,用于表示不同的种子。这可能不像你想的那样随机。我希望这在很大程度上取决于系统上随机数生成器的实现。

由于您要求不能保存随机序列,我有一些想法。

1)

尝试更改用于更改随机种子的公式。现在,当您在网格中移动时,您的种子正在变得非常可预测。 (例如种子,种子+ 1,种子+ 2,......,种子+宽度,种子+宽度+ 1等)你想要的是:

srand(seed + hash(x + y * grid->width));

其中hash是一个简单的东西,它将[0,width * height]中的数字映射到该范围内的另一个数字,但不太可预测。

可以找到一些简单的哈希函数here

2)

在获取随机值之前,从随机数生成器中弹出确定数量的随机数。因此,在返回语句之前,添加如下行:

for (i=0; i!=skip; ++i) rand();

您可以将skip设置为固定数字,或者甚至可以使其成为x,y甚至种子的确定性函数。