Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何创建用于噪声生成的哈希函数_C++_Algorithm_Hash_Noise_Perlin Noise - Fatal编程技术网

C++ 如何创建用于噪声生成的哈希函数

C++ 如何创建用于噪声生成的哈希函数,c++,algorithm,hash,noise,perlin-noise,C++,Algorithm,Hash,Noise,Perlin Noise,我最近在玩弄噪声函数,即柏林噪声和单纯形噪声。我对噪声算法没有任何疑问,因为我已经启动并运行了它们,但我对ken perlin使用的哈希方法有一些疑问: 一些背景: 所以在这些噪声函数中,每个坐标都需要一个(伪)随机值。在Ken Perlins的实现中,他使用查找表获取以下值: static const U8 perlin_hash_values[] = { 151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225, 140,

我最近在玩弄噪声函数,即柏林噪声和单纯形噪声。我对噪声算法没有任何疑问,因为我已经启动并运行了它们,但我对ken perlin使用的哈希方法有一些疑问:

一些背景: 所以在这些噪声函数中,每个坐标都需要一个(伪)随机值。在Ken Perlins的实现中,他使用查找表获取以下值:

static const U8 perlin_hash_values[] = {
151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233,  7,225,
140, 36,103, 30, 69,142,  8, 99, 37,240, 21, 10, 23,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,

151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233,  7,225,
140, 36,103, 30, 69,142,  8, 99, 37,240, 21, 10, 23,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};
坐标映射到如下值:

return perlin_hash_values[perlin_hash_values[y & 255] + x & 255];
我有一些问题:它消耗内存,重复速度很快,并且不可种子(至少是参考实现。我想你可以使用3D柏林噪声和z值作为种子),我想知道是否可以更快。(可能不是,因为阵列可能在缓存中,而且它的2个内存读取和3条指令都很难被击败)。我这么做主要是为了好玩和学习一些东西

我的问题是: 用算法代替这种方法的好方法是什么?理想的特性可能是它的速度快,不会产生视觉伪影,并且不会像这个数组那样快速重复

我首先想到使用一个标准的哈希函数,但是我发现了两个实际上并不需要的属性:哈希函数通常接受任意长的输入,这在这里是不需要的。它们还试图避免冲突(不同输入的相同输出),这在这里也不是必需的。至少如果我认为视觉伪影和碰撞之间可能没有很强的相关性是正确的话。这两个因素使得标准哈希函数看起来不必要地复杂。所需要的只是从N维到1维的映射,看起来是随机的

到目前为止,我所尝试的:
采用xorshift*伪随机数生成器:我将内部64位状态设置为x和y串联的值

F32 xor_shift_star_adaption(S32 x, S32 y, U32 seed) {
    union concat_S32
    {
        S32 s[2];
        U64 u;
    };
    concat_S32 temp;
    temp.s[0] = x;
    temp.s[1] = y;
    xorshift_star_64 xor;
    xor.state = temp.u;
    return xor.get_random_number();
}
我没有足够的声誉来发布图片:/。我怀疑伪随机数生成器不适合此任务,因为我听说它们通常需要一些时间来“预热”。内部状态自我提升,时间越长,随机数的质量就越高。通过这种方法,我可以防止prng“升温”。另一方面,状态可以看作是一个线性的数字序列。如果我用一个在这个线性序列中很长的数字初始化prng,我是否应该立即得到“高质量”的数字


使用某人建议的超级简单的一行程序(现在不再是一行程序):

但是它有一些昂贵的操作


使用杂音3散列函数,这似乎是我能找到的最好的“正常”散列函数。(我不会在这里发布代码,它很大)。它的表现也很好,但完成工作也需要很长时间


试着用素数做一些异或和位移位的事情,因为我认为PRNG就是这样工作的:D。正如你所能想象的,它看起来很可怕(更接近抽象艺术而不是随机噪声)。如果不了解prng,创建prng似乎是不可能的


那么,你对下一步的尝试有什么建议吗?我认为一般来说,我更喜欢哈希函数而不是prng,因为它更符合我在这里试图实现的目标


(很抱歉没有链接和图片,这里的声誉系统真的把我搞砸了)

两种可能的解决方案:

a) 使用二维随机表。如果它适合一级缓存,那么速度会很快

b) 使用整数散列:

例如,这:

uint32_t hash( uint32_t a)
    a = (a ^ 61) ^ (a >> 16);
    a = a + (a << 3);
    a = a ^ (a >> 4);
    a = a * 0x27d4eb2d;
    a = a ^ (a >> 15);
    return a;
}
uint32\u t散列(uint32\u t a)
a=(a^61)^(a>>16);
a=a+(a>4);
a=a*0x27d4eb2d;
a=a^(a>>15);
返回a;
}

使用(散列)((yWhy不使用xorshift*常规方法,因此不需要将坐标放入其中?因为这将使其成为rng。噪声函数的一个优点是,对于给定的坐标,可以得到相同的值。如果我只使用prng给我的数字序列,点的值将不依赖于该点,而是on前面的点序列。请注意您正在考虑的哈希函数:其中一些函数经过精心设计,运行速度尽可能慢。标准的C++11随机生成器(如or)如何?我还没有听说knuth-b,所以我可能会尝试一下。关于Mersenne Twister:它可能会慢10倍,而不是HAND XORSHIFT *(它是一只野兽)是不受欢迎的。我选择XORFREST,因为我读到它是一个很好的PRNG(与MelSeNeNe媲美)。另一方面,PRNG测试通常不在这里测试我的情况:为每一个你想要的数字重新设置PRNG。这很有趣:当我使用你的整数哈希变体而不掩蔽最后一个字节。(没有&0xFF)我得到了非常糟糕的视觉伪影。当我屏蔽字节时,所有的伪影都消失了,看起来很好!看起来低位更“随机”比高位更重要?我会在我使用的其他方法上尝试一些位屏蔽的东西,看看它是否有区别。谢谢!是的,这是可能的。你可以查看其他函数。例如,有一个函数,Bob说,“如果你承诺至少使用17个最低位,这个还不错。”。这应该更快,并且可能对您的目的同样好(请注意,我在这里展示的变体不是我的,我只是从Bob的站点复制的)。
uint32_t hash( uint32_t a)
    a = (a ^ 61) ^ (a >> 16);
    a = a + (a << 3);
    a = a ^ (a >> 4);
    a = a * 0x27d4eb2d;
    a = a ^ (a >> 15);
    return a;
}