【问题标题】:How to avoid patterns when making random perlin noise产生随机柏林噪声时如何避免模式
【发布时间】:2013-06-12 20:23:47
【问题描述】:

我正在制作一个 3d perlin 噪声发生器。重要的是,坐标是种子,这样它每次都会给我相同的随机值(永远不会存储噪声)。这是我基于作为坐标的种子生成随机值的函数:

__forceinline float getRandomField(const vec3& Position) const
{
    uint32_t seed = uint32_t(Position.x);
    seed <<= 8;
    seed ^= 0xE56FAA12;
    seed |= uint32_t(Position.y);
    seed <<= 8;
    seed ^= 0x69628a2d;
    seed |= uint32_t(Position.z);
    seed <<= 8;
    seed ^= 0xa7b2c49a;

    srand(seed);

    return (float(int(rand()%2001) -1000)/1000.0f);
}

结果(x,y 平面中的切片):

奇怪的是,这给了我一个模式。显然,我不知道我在做什么。我虽然应用了一些奇怪的异或值并将位移到随机种子中会给我一个随机数。显然我错了。

从坐标创建随机值而不产生模式的最佳方法是什么?

【问题讨论】:

  • 一种 slow 方法将散列 3 个位置的串联 [例如散列你的种子忽略异或位](使用说md5)并取出最低的2个字节。不过可以。
  • 我也必须(相对)快。我对 md5 一无所知,但我在 536 行上看到了一些用于 md5 生成器的代码。那是慢的方式。
  • 这是一份关于俄勒冈州噪音的有趣 pdf web.engr.oregonstate.edu/~mjb/cs519/Handouts/noise.1pp.pdf
  • 为什么不只给 RNG 播种一次,然后按固定顺序生成值?这足以重现性。
  • 以固定顺序生成值不是一种选择。生成图片只是为了测试。实际上,它将用于在查看器接近时生成地形。由于对世界没有硬性限制,因此不可能存储所有内容,因此如果您只播种一次,就无法确保生成的样本相同。

标签: c++ random 3d perlin-noise


【解决方案1】:

只是为了给其他可能有同样问题的人一个答案。我找到了一个产生了相当好的结果的。我什至不需要 rand() 函数。

__forceinline float getRandomField(const vec3& Position) const
{
    uint32_t seed = uint32_t(Position.x)*1087;
    seed ^= 0xE56FAA12;
    seed += uint32_t(Position.y)*2749;
    seed ^= 0x69628a2d;
    seed += uint32_t(Position.z)*3433;
    seed ^= 0xa7b2c49a;

    return (float(int(seed%2001) -1000)/1000.0f);
}

关键是将每个轴与一个质数相乘。我在维基百科上找到了这些: 1087,2749,3433。 异或的十六进制值只是由我随机敲定的。据我所知,它们不是素数。查看结果:

【讨论】:

  • 我使用柏林噪声有一段时间了,我知道使用素数很重要,但从来没有为什么素数是关键。你对此有什么煽动吗?
  • @RichardTingle 我相信这是因为素数不能被彼此整除。你有一个网格,它为每个素数的倍数绘制一个点,你得到的重叠可能性较小。 io9.com/5895840/why-do-cicadas-know-prime-numbers
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 2012-01-29
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多