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

标签 math vector noise

我目前正在了解改进的 Perlin 噪声。
我完全理解这个理论,但是我对其常见实现的一个方面感到困惑,例如 this .
我的问题是,grad() 函数如何返回归一化向量(梯度和方向)的点积?我的意思是,归一化向量的点积范围为 -1 到 1,这是将所有点积混合(淡入淡出)后的 Perlin 噪声的正常输出。但是经过点积的向量没有归一化(梯度函数和方向向量都不是)。那么,输出如何落在 -1 到 1 的范围内?
我唯一的猜测是梯度向量的大小都是 2 根,方向向量的所有轴都在 -1 到 1 的范围内。所以,我认为这就是为什么 Perlin 噪声输出最终落入 -1到 1 个范围。这是为什么?谁能证明或找到证明?
谢谢你们

最佳答案

向量没有被归一化(它们的长度是 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 ) ≈ 0.8660254037844387。
但是,这两种情况都不是这种情况,因此噪声的实际最小值/最大值更为复杂。我过去曾在噪声上运行梯度上升,使用您正在查看的梯度集,以找到其真正的最大值。最大值略大于1,不在中心。将整个噪声乘以(或等效地预先乘以表中的每个梯度)以校正输出范围的值为 0.964921414852142333984375 。
顺便说一下,如果您还没有通过其他来源发现这一点:Perlin 非常好学,但它对基轴产生了很大的偏差,并且在其特征的角度分布中产生的变化很小。好的 Simplex 类型噪声实现通常会产生更好的结果。如果您要使用 Perlin,我建议您选择垂直(或时间或未使用)方向,并在输入坐标上使用以下公式之一。您可以在分形求和之前执行此操作(更有效),也可以将其放入函数定义的开头(更方便)。一旦你这样做了,它就很棒,并且在正确的情况下使用时看起来比一些 Simplex 类型的噪声实现更好。但请注意,即使您的用例只是 2D,您也需要始终将 3D 噪声用于此技术。
如果 Z 为垂直、时间或未使用:

double xy = x + y;
double s2 = xy * -0.211324865405187;
z *= 0.577350269189626;
x += s2 - z;
y = y + s2 - z;
z += xy * 0.577350269189626;
如果 Y 是垂直的、时间的或未使用的:
double xz = x + z;
double s2 = xz * -0.211324865405187;
y *= 0.577350269189626;
x += s2 - y;
z = z + s2 - y;
y += xz * 0.577350269189626;
之前(大量 45 度和 90 度零件)
Un-domain-rotated 3D Perlin
之后(方向偏差在很大程度上是不可见的)
Domain-rotated 3D Perlin

关于math - 棘手的柏林噪声问题。 Grad 函数如何使用归一化向量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65540146/

相关文章:

ipad - 数学符号字体

java - 将点移离另一个点

c++ - 从 std :vector 获取数组

c++ - 更快地交换或分配字符串 vector ?

matlab - 了解 Matlab 中的过滤器

java - 分形噪声地形产生奇怪的人工制品线

python - 计算 x1 ^ (x2 ^ (x3 ^ (... ^ xn))) 的最后一位(十进制)数字

php - 有没有一种聪明的方法可以用纯数学来做到这一点

c++ - 我收到调试断言失败的第 1662 行

python - 在python中为RGB图像添加噪声