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