代码之家  ›  专栏  ›  技术社区  ›  Dr.Knowitall

为什么柏林噪声使用哈希函数而不是计算随机值?

  •  3
  • Dr.Knowitall  · 技术社区  · 9 年前

    我正在通读 this explanation of Perlin noise 它描述了一个哈希函数,用于计算所有x,y坐标的随机点。

    我们在哈希映射上使用排列来查找随机值,这只是一个优化问题吗?我能想到的唯一原因是,通过我们的哈希映射的排列如何产生平滑效果,但我看不出是如何产生的。

    为了澄清,我在代码中引用了这一节:

    private static readonly int[] p = { 151,160,137,91,90,15,                 // Hash lookup table as defined by Ken Perlin.  This is a randomly
        131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,    // arranged array of all numbers from 0-255 inclusive.
        190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
        88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
        77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
        102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
        135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
        5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
        223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
        129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
        251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
        49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
        138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
    };
    
    int aaa, aba, aab, abb, baa, bba, bab, bbb;
            aaa = p[p[p[    xi ]+    yi ]+    zi ];
            aba = p[p[p[    xi ]+inc(yi)]+    zi ];
            aab = p[p[p[    xi ]+    yi ]+inc(zi)];
            abb = p[p[p[    xi ]+inc(yi)]+inc(zi)];
            baa = p[p[p[inc(xi)]+    yi ]+    zi ];
            bba = p[p[p[inc(xi)]+inc(yi)]+    zi ];
            bab = p[p[p[inc(xi)]+    yi ]+inc(zi)];
            bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];
    

    aaa = random(255)
    aab = random(255)
    // ...
    
    1 回复  |  直到 5 年前
        1
  •  7
  •   templatetypedef    5 年前

    柏林噪声生成背后的关键思想是创建一个点网格,每个点都被赋予一些向量值,然后以特定的方式在这些点之间插值。

    我退房了 Ken Perlin's original paper on Perlin noise 似乎早在最初的论文中,他就建议使用哈希函数来实现这一点:

    H最好作为哈希函数实现。

    (我的重点)。

    1. 有一些公式,给定空间中的一个点,计算出梯度,或者
    2. 显式创建一个表并存储所需的所有随机值。

    选项(1)是Ken Perlin提出的。这种方法的优点是存储梯度所需的内存使用量最小;您只需要使用散列函数。

    选项(2)是您提出的建议。这很好,但它使用了大量内存(您需要为正在处理的整数晶格中的每个点存储多个值)。记得柏林的论文写于1985年(!)当时的记忆比今天少得多。

    不过,我无法解释为什么你读到的那篇文章的作者选择使用他们使用的特定哈希函数。我的猜测是,它“足够随机”,足够快,不会成为计算中的瓶颈;请记住,哈希函数在噪声生成代码中被多次调用。这似乎是实现柏林噪声的标准方法;即使 Ken Perlin mentions using this hash function on his site

    不能 aaa aab , aba 等等。是随机的。原因是柏林噪声算法要求您在给定点多次重新评估噪声项,并期望每次都返回相同的值。如果你想计算真正的随机值,你可以这样做,但你需要缓存你的结果,这样你就可以在每个点上返回一致的噪声项的答案。

    推荐文章