20

我阅读了Stefan Gustavson 关于单纯形噪声的优秀论文,其中我被承诺:

单纯形噪声没有明显的方向性伪影

与“经典”柏林噪声形成对比。我兴奋地实现了它,发现事实恰恰相反。我确实在经典噪声中看到了伪影,但我在单纯噪声中看到了至少同样多的伪影,与主轴成 45 度角对齐。当您将噪声映射到阶跃函数时,它们尤其明显。

为了确保我的实现没有问题,我使用了别人的 JavaScript 实现。比较一些图像:

这是一个拥有所有这些的画廊。在最后一张图片中,查找与水平/垂直成 45 度角对齐的边框。他们到处都是。如果需要,我可以突出显示其中的一些,但它们对我来说似乎很明显。(再一次,我在经典的噪声图像中也看到了它们。)

编辑:为了更量化,我采样了 100 万个随机点,对于每个点,我数值计算了经典噪声和单纯噪声的梯度,并获取了投影到 xy 平面上的梯度方向的直方图。如果没有方向性伪影,则图形将是平坦的。但是您可以看到经典噪声和单纯噪声每 45 度出现一次尖峰。

这是单纯形噪声算法的问题吗?它是可以修复的吗?还是只有我认为这是一个问题?

4

2 回答 2

27

我刚读了这篇论文,我想我知道是什么导致了这些伪影。网格的每个顶点的梯度是从一个相当小的查找表中伪随机选择的。正如 Gustavson 在第 3 页所说:

“对于 2D 及更高版本,一个不错的选择是选择单位长度但方向不同的梯度。对于 2D,在单位圆周围分布 8 或 16 个梯度是一个不错的选择。”

这是经典 Perlin 噪声中使用的方法,这不是Perlin 在其2001 年论文第 14 页中针对 Simplex 噪声提出的方法:

“新方法不是使用表查找方案来计算每个周围顶点的伪随机梯度的索引,而是使用仅使用极少数硬件门的位操作方案。”

然而,Gustavson 在第 7 页指出:

“为了清晰起见,我将使用混合方法,使用经典噪声的梯度散列方法,但使用单纯形网格和单纯形噪声的噪声贡献的直接求和。这实际上是软件中更快的方法。”

他的 2D 实现实际上使用了 3D 梯度表中的 12 个梯度,丢弃了 z 坐标。在该方案中,边缘坐标每次使用两次,但角点仅使用一次,这似乎会以 90 度的间隔引入偏差。但这与您的情况无关,因为您使用的实现只有 8 个渐变,这非常暗示 45 度间隔的偏差。从这种最小差异中出现可见模式的可能性似乎很高。但是使用 mod 16 置换表应该很容易将该算法适应 16 个梯度,这应该有助于显着减少方向伪影。

不过,最终,我认为在任何梯度噪声函数的单个八度音程中总会有一些可见的模式,仅仅是因为它们是设计限制的,因为窄的频率范围倾向于将扰动与网格对齐。作为一个三角形网格,即使梯度是真正随机的,Simplex 噪声也可能会以 60 度的间隔表现出一些偏差。好吧,这只是推测,但重点是这些噪声函数实际上是设计为以不同的频率组合的,这往往会破坏您在单个八度音程中可能看到的任何模式。

编辑:

我刚刚意识到的另一点,诸如(1,1)之类的角梯度不是单位长度,它们是sqrt(2)。第一个引用清楚地表明梯度应该位于单位圆上。这可能是偏见的另一个来源。有趣的是,Gustavson 也使用了这些非单位梯度。

于 2014-02-05T04:38:47.970 回答
4

perlin 噪声的值噪声版本也产生直线,而 perlin 的梯度噪声版本产生略圆的东西,所以也许你在那里有一个单纯形的值噪声实现而不是梯度版本。

否则代码中的插值梯度是错误的,因为它会在象限之间产生角度转换。网上似乎说单纯形噪声不仅更快,而且梯度更圆润。

我将其解释为插值曲线的角度更圆。也许有人误解了 Ken Perlins 的说法,他只是说梯度包含较少的抖动(抱歉使用错误的描述),因为如果你将许多 Perlin 相乘,代码实际上并不会产生像窦一样的完美数学曲线我发现抖动/曲线的不规则性足以测量,而正弦波和数学函数则不然。所以你可以在网上研究其他人对单纯形噪声梯度的评论。

我认为有一个渐变查找表,在您的情况下,它似乎经常上升到 45',否则您在 2 点之间使用的分级曲线与会产生圆形的理想化正弦曲线太远形状,根本没有直线,但计算起来不太容易,尤其是在 CPU 上。在GPU上,我认为正弦梯度比使用的多项式梯度曲线更快是有道理的。

您是否还检查过您的单纯形的湍流和多重分形等版本是什么?在任何一种情况下,它们都是大约 5 行,表示噪声函数如何运行并每次返回非常不同的结果。

从 scrawkblog 改进了 GPU 的 Perlin 噪声 IMG

于 2013-09-24T03:01:59.173 回答