棘手的柏林噪音问题。Grad 函数如何使用归一化向量?

Nio*_*yan 5 math vector noise

我目前正在了解改进的柏林噪音。我完全理解这个理论,但是,我对其常见实现的一个方面感到困惑,例如this

我的问题是, grad() 函数如何返回归一化向量(梯度和方向)的点积?我的意思是,归一化向量的点积的范围为 -1 到 1,这是将所有点积混合(淡入淡出)在一起后 Perlin 噪声的正常输出。但是进行点积的向量没有标准化(梯度函数和方向向量都不是)。那么,输出如何落在-1到1的范围内呢?

我唯一的猜测是梯度向量的大小均为根 2,并且方向向量的所有轴都在 -1 到 1 的范围内。因此,我认为这就是 Perlin 噪声输出最终落在 -1 范围内的原因至 1 范围。这是为什么吗?有人能证明或找到证据吗?

多谢你们

小智 4

这些向量没有标准化(它们的长度是 sqrt(2),正如其他贡献者所描述的那样),并且噪声的总输出不是精确的 -1 到 1。如果向量 <1, 1, 1> 和所有符号排列都是可能的,那么我相信最大值将位于每个立方体的中心。它将是 dot(grad, offsetFromVertex) = dot(<1, 1, 1>, <0.5, 0.5, 0.5>) = 1.5, /8 对于 0.5^3 在 3 个方向中每个方向都有一半的插值权重, *8 再次因为有 8 个顶点所以它取消。如果向量被归一化,并且它们可以指向每个立方体的中心,那么您将得到 dot(<1, 1, 1>/sqrt(3), <0.5, 0.5, 0.5>) = 1.5/sqrt(3 ) \xe2\x89\x88 0.8660254037844387。

\n

但是,这两种情况都不是这种情况,因此噪声的实际最小/最大值更加复杂。我过去曾使用您正在查看的梯度集对噪声进行梯度上升,以找到其真正的最大值。最大值略大于1,并且不在中心。与整个噪声相乘(或等效地预乘表中的每个梯度)以校正输出范围的值是 0.964921414852142333984375 。

\n

顺便说一句,如果您还没有通过其他来源发现这一点:Perlin 非常好学,但它会对基轴产生很大的偏差,并且其特征的角度分布变化很小。良好的单纯型噪声实现通常会产生更好的结果。如果您要使用 Perlin,我建议选择您的垂直(或时间或未使用)方向,并在输入坐标上使用以下公式之一。您可以在分形求和之前执行此操作(更有效),也可以将其放入函数定义的开头(更方便)。一旦你这样做了,它就很棒,并且在正确的情况下使用时看起来比某些 Simplex 类型噪声实现更好。但请注意,即使您的用例只是 2D,您也需要始终使用 3D 噪声来实现此技术。

\n

如果 Z 为垂直、时间或未使用:

\n
double xy = x + y;\ndouble s2 = xy * -0.211324865405187;\nz *= 0.577350269189626;\nx += s2 - z;\ny = y + s2 - z;\nz += xy * 0.577350269189626;\n
Run Code Online (Sandbox Code Playgroud)\n

如果 Y 为垂直、时间或未使用:

\n
double xz = x + z;\ndouble s2 = xz * -0.211324865405187;\ny *= 0.577350269189626;\nx += s2 - y;\nz = z + s2 - y;\ny += xz * 0.577350269189626;\n
Run Code Online (Sandbox Code Playgroud)\n

之前(大量 45 度和 90 度部件)

\n

非域旋转 3D Perlin

\n

之后(方向偏差基本上不可见)

\n

域旋转 3D Perlin

\n