我读了Stefan Gustavson's excellent paper on simplex noise,其中我答应了:
单纯形噪声没有明显的方向性伪影
与“经典”Perlin噪音相反。我兴奋地实施它,以发现相反的情况似乎是真的。我确实看到了经典噪音中的人工制品,但我看到至少与单轴噪声一样多的伪像,与主轴成45度对齐。当您将噪声映射到阶跃函数时,它们尤其明显。
为了确保我的实施不是问题,我使用了someone else's JavaScript implementation。比较一些图像:
here's a gallery和所有这些。在最后一张图像中,查找与水平/垂直方向成45度对齐的边框。他们到处都是。如果需要,我可以突出其中一些,但它们对我来说似乎非常明显。 (再次,我也在经典的噪声图像中看到它们。)
编辑:为了更加量化,我对100万个随机点进行了采样,并且对于每个点,我数值计算了经典和单纯噪声的梯度,并取了histogram of the direction of the gradient projected onto the x-y plane。如果没有方向性伪影,则图形将是平坦的。但你可以看到经典和单纯的噪音每45度就会达到峰值。
这是单纯噪声算法的问题吗?这是可以修复的吗?或者我是唯一一个将此视为问题的人?
答案 0 :(得分:18)
我刚刚阅读了论文,我想我知道可能导致这些文物的原因。从相当小的查找表伪随机地选择网格的每个顶点的梯度。正如古斯塔夫森在第3页所述:
“2D和更高的选择是选择单位长度但不同方向的渐变。对于2D,8或16个渐变分布在单位圆周围是一个不错的选择。”
这是经典Perlin噪声中使用的方法, 不 Perlin在他的2001 paper中为单纯形噪声提出的内容,第14页:
“新方法不是使用表查找方案来计算每个周围顶点的伪随机梯度的索引,而是使用仅使用极少数硬件门的位操作方案。”
然而,古斯塔夫森在第7页说:
“为了清晰起见,我将使用混合方法,使用经典噪声的渐变哈希方法,但单纯形网格和单纯噪声的噪声贡献的直接求和。这实际上是一种更快的软件方法。”
他的2D实现实际上使用了3D渐变表中的12个渐变,丢弃了z坐标。在该方案中,边缘坐标每次使用两次,但拐角仅使用一次,这似乎以90度间隔引入偏差。但这与你的情况无关,因为你所使用的实现只有8个渐变,非常暗示45度间隔的偏差。从这种最小方差中出现的可见模式的可能性似乎相当高。但是使用mod 16置换表应该很容易使该算法适应16个梯度,这有助于显着减少方向性伪影。
但最终,我认为在任何梯度噪声函数的单个八度音程中总会有一些可见的模式,仅仅因为它们受到设计的限制,因为窄范围的频率会使扰动对齐。网格。作为三角形网格,即使梯度是真正随机的,单面噪声也可能以60度的间隔呈现出一些偏差。嗯,这只是猜想,但重点是这些噪音功能真的被设计成以不同的频率组合,这往往会打破你在一个八度音阶中看到的任何模式。
编辑:
我刚刚意识到的另一点是,(1,1)等角落梯度不是单位长度,它们是sqrt(2)。第一个引用清楚地表明渐变应该位于单位圆上。这可能是另一个偏见的来源。有趣的是,Gustavson也使用了这些非单位渐变。
答案 1 :(得分:2)
perlin噪声的值噪声版本也会产生难看的直线,而perlin的梯度噪声版本会产生稍微更圆的东西,所以也许你有一个单值的噪声实现而不是渐变版本。
否则代码中的插值梯度是错误的,因为它在象限之间产生了这样的角度转换。那一定是错误的地方。似乎在网上说单面噪声不仅更快,而且渐变更圆润。
我认为这意味着插值曲线的角度更圆。也许有人误解了肯·佩林斯关于此事的断言,并且他只是说渐变包含较少的抖动(抱歉使用了错误的描述),因为代码实际上并没有像窦那样产生完美的数学曲线,如果你将许多Perlin加在一起我发现抖动/曲线不规则性足以测量,这与正弦波和数学函数不同。所以你可以在线研究其他人对单纯噪声梯度的评论。
我认为有一个渐变查找表,在你的情况下它似乎经常上升到45',否则你在2点之间使用的分级曲线离理想化的正弦曲线太远了会产生圆形而根本没有直线,但这种计算不那么容易,特别是在CPU上。在GPU上,我认为使用比使用多项式梯度曲线更快的窦梯度是合理的。
您是否也检查过单纯形的湍流和多重分形等版本?在任何一种情况下,它们都是大约5行,表示噪声函数如何运行并且每次返回非常不同的结果。
scrawkblog改进了GPU的Perlin噪音 IMG http://i40.tinypic.com/2py6oba.jpg