我正在实施改进的Perlin噪音。其随机化的关键特征是硬编码的置换表,该置换表在网格单元处给出了基本随机但可重现的渐变。排列表只是整数0..255的排列,通常是下表(直接从Perlin的原始实现中复制):从此表产生的噪声中得出的结果如下所示:我可以创建一个全新的噪声场(而不是仅以不同的偏移量对其进行采样)。但是,并非所有排列都被很好地混洗。万一随机排列只是从0255的排序数组,则噪声看起来会像这样:当然,在$ 256!$中有$ 1 $的机会,这不是我需要担心的情​​况。但是可以肯定的是,这不是产生非常明显的伪像的唯一排列。反向排序和几乎排序的排列可能会遇到相同的问题。那么还有多少其他排列不合适?假设代码会在流行的游戏中用于预先生成一个随机世界,但如果每100,000个生成的世界看起来遥遥规则,这仍然很烦人。

所以问题是,究竟是什么使一个好(或坏)的排列表,以及如何以编程方式评估排列表的质量,以便在发生“坏”表的不太可能发生的情况下,我可以再次对表进行重新组合?

评论

对随机数生成器的统计测试应该是有用的。计算顺序(反向顺序)对的预期数量可能是开始测试的好地方。本文有很多参考资料:csrc.nist.gov/groups/ST/toolkit/rng/documents/nissc-paper.pdf。

#1 楼

首先-一定不能出现两次,这是隐含的,因为我们在谈论置换。因此,使用简单的random(255)函数填充表格将无法正常工作。

其次,您需要确保没有过早的重复模式:

考虑这些值1,2,3,4-排列表4,3,2,1并不是一个很好的表,因为它具有短循环特性,即1-> 4,4,->1。同样对于4,2,3, 1或1,2,3,4。最佳表格会带您遍历所有位置:3,1,4,2或2,4,1,3。

随着增加尺寸和执行尺寸,此属性变得越来越重要递归查找。

但是,仅此方法可能会创建过于相似的值簇,可能不需要,也可能不需要,这将导致我进入下一个观点。

,当您生成具有非循环属性的表,您需要以随机方式逐步处理其余未分配的索引。在可能的情况下,将此处的随机步距限制为某个最小和最大范围,例如5..120避免相似值的聚集组。这些数字值得尝试。

评论


$ \ begingroup $
欢迎使用Computer Graphics SE!关于第二点,我看了Perlin使用的置换表的循环分解。它由多个长度为{4,121,89,12,4,4,15,4,6}的循环组成,那么这显然足够好吗? (或者也许不是,并且不同的排列表甚至会“更好”?尽管我不确定人类是否可以感知到这种差异。或者实际上有多个循环会更好?)我没有关注您的第三点。均匀的随机分布是什么?那是什么步距呢?
$ \ endgroup $
–马丁·恩德(Martin Ender)
16 Jan 25'11:29



$ \ begingroup $
谢谢!是的,我想那是很神秘的。几年前我曾对此进行过试验,所以我不记得确切的实现了,但是当您拥有实现最佳路径生成的实现时,很明显,您可以从未使用的索引剩下的位置中随机选择,这是我指的是随机步长。我更新了答案
$ \ endgroup $
– mhbuur
16 Jan 25 '11:53



#2 楼

一种可能是从密码学团体那里借用,尤其是在AES / Rijndael密码中使用的8位到8位替换。
可以在Wikipedia上找到用于生成表的表和代码。

我想,为了生成多达256个表,您可以执行以下操作:

Func(U8 input, U8 TableNum) = SBox( (TableNum + Sbox(input)) Mod256 )


(因为SBox函数是非常非线性的)

话虽如此,(请谅解我,如果我有一些在过去的生活中,我使用相对简单的RNG / Hash函数实现了Perlin噪声,但由于将2维或3维简单映射到标量值,发现X / Y / Z的相关性存在问题。我发现一个非常简单的修复方法就是使用CRC。像

InputToRNGHash = CRC(Z xor CRC( Y xor CRC(X))). 


鉴于CRC内在函数可能内置于CPU硬件中,这可以是一种快速的方法。