我一直在为5维和6维单纯形噪声编写函数,以快速噪声四维函数为基础。2D、3D和4D噪声都遵循一种非常相似和可识别的模式,可以很容易地扩展到更高的维度,但是输出看起来不太好:

可见对角线区域(线),其中的价值都是非常相似的,以及钻石形状,价值不融合在一起。(这算不连续吗?)
完整的5D噪声功能是:
static const FN_DECIMAL F5 = (sqrt(FN_DECIMAL(6)) - 1) / 5;
static const FN_DECIMAL G5 = (6 - sqrt(FN_DECIMAL(6))) / 30;
FN_DECIMAL FastNoise::SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w, FN_DECIMAL v) const
{
FN_DECIMAL n0, n1, n2, n3, n4, n5;
FN_DECIMAL t = (x + y + z + w + v) * F5;
int i = FastFloor(x + t);
int j = FastFloor(y + t);
int k = FastFloor(z + t);
int l = FastFloor(w + t);
int h = FastFloor(v + t);
t = (i + j + k + l + h) * G5;
FN_DECIMAL X0 = i - t;
FN_DECIMAL Y0 = j - t;
FN_DECIMAL Z0 = k - t;
FN_DECIMAL W0 = l - t;
FN_DECIMAL V0 = h - t;
FN_DECIMAL x0 = x - X0;
FN_DECIMAL y0 = y - Y0;
FN_DECIMAL z0 = z - Z0;
FN_DECIMAL w0 = w - W0;
FN_DECIMAL v0 = v - V0;
int rankx = 0;
int ranky = 0;
int rankz = 0;
int rankw = 0;
int rankv = 0;
if (x0 > y0) rankx++; else ranky++;
if (x0 > z0) rankx++; else rankz++;
if (x0 > w0) rankx++; else rankw++;
if (x0 > v0) rankx++; else rankv++;
if (y0 > z0) ranky++; else rankz++;
if (y0 > w0) ranky++; else rankw++;
if (y0 > v0) ranky++; else rankv++;
if (z0 > w0) rankz++; else rankw++;
if (z0 > v0) rankz++; else rankv++;
if (w0 > v0) rankw++; else rankv++;
int i1 = rankx >= 4 ? 1 : 0;
int j1 = ranky >= 4 ? 1 : 0;
int k1 = rankz >= 4 ? 1 : 0;
int l1 = rankw >= 4 ? 1 : 0;
int h1 = rankv >= 4 ? 1 : 0;
int i2 = rankx >= 3 ? 1 : 0;
int j2 = ranky >= 3 ? 1 : 0;
int k2 = rankz >= 3 ? 1 : 0;
int l2 = rankw >= 3 ? 1 : 0;
int h2 = rankv >= 3 ? 1 : 0;
int i3 = rankx >= 2 ? 1 : 0;
int j3 = ranky >= 2 ? 1 : 0;
int k3 = rankz >= 2 ? 1 : 0;
int l3 = rankw >= 2 ? 1 : 0;
int h3 = rankv >= 2 ? 1 : 0;
int i4 = rankx >= 1 ? 1 : 0;
int j4 = ranky >= 1 ? 1 : 0;
int k4 = rankz >= 1 ? 1 : 0;
int l4 = rankw >= 1 ? 1 : 0;
int h4 = rankv >= 1 ? 1 : 0;
FN_DECIMAL x1 = x0 - i1 + G5;
FN_DECIMAL y1 = y0 - j1 + G5;
FN_DECIMAL z1 = z0 - k1 + G5;
FN_DECIMAL w1 = w0 - l1 + G5;
FN_DECIMAL v1 = v0 - h1 + G5;
FN_DECIMAL x2 = x0 - i2 + 2*G5;
FN_DECIMAL y2 = y0 - j2 + 2*G5;
FN_DECIMAL z2 = z0 - k2 + 2*G5;
FN_DECIMAL w2 = w0 - l2 + 2*G5;
FN_DECIMAL v2 = v0 - h2 + 2*G5;
FN_DECIMAL x3 = x0 - i3 + 3*G5;
FN_DECIMAL y3 = y0 - j3 + 3*G5;
FN_DECIMAL z3 = z0 - k3 + 3*G5;
FN_DECIMAL w3 = w0 - l3 + 3*G5;
FN_DECIMAL v3 = v0 - h3 + 3*G5;
FN_DECIMAL x4 = x0 - i4 + 4*G5;
FN_DECIMAL y4 = y0 - j4 + 4*G5;
FN_DECIMAL z4 = z0 - k4 + 4*G5;
FN_DECIMAL w4 = w0 - l4 + 4*G5;
FN_DECIMAL v4 = v0 - h4 + 4*G5;
FN_DECIMAL x5 = x0 - 1 + 5*G5;
FN_DECIMAL y5 = y0 - 1 + 5*G5;
FN_DECIMAL z5 = z0 - 1 + 5*G5;
FN_DECIMAL w5 = w0 - 1 + 5*G5;
FN_DECIMAL v5 = v0 - 1 + 5*G5;
t = FN_DECIMAL(0.5) - x0*x0 - y0*y0 - z0*z0 - w0*w0 - v0*v0;
if (t < 0) n0 = 0;
else
{
t *= t;
n0 = t*t * GradCoord5D(offset, i, j, k, l, h, x0, y0, z0, w0, v0);
}
t = FN_DECIMAL(0.5) - x1*x1 - y1*y1 - z1*z1 - w1*w1 - v1*v1;
if (t < 0) n1 = 0;
else
{
t *= t;
n1 = t*t * GradCoord5D(offset, i + i1, j + j1, k + k1, l + l1, h + h1, x1, y1, z1, w1, v1);
}
t = FN_DECIMAL(0.5) - x2*x2 - y2*y2 - z2*z2 - w2*w2 - v2*v2;
if (t < 0) n2 = 0;
else
{
t *= t;
n2 = t*t * GradCoord5D(offset, i + i2, j + j2, k + k2, l + l2, h + h2, x2, y2, z2, w2, v2);
}
t = FN_DECIMAL(0.5) - x3*x3 - y3*y3 - z3*z3 - w3*w3 - v3*v3;
if (t < 0) n3 = 0;
else
{
t *= t;
n3 = t*t * GradCoord5D(offset, i + i3, j + j3, k + k3, l + l3, h + h3, x3, y3, z3, w3, v3);
}
t = FN_DECIMAL(0.5) - x4*x4 - y4*y4 - z4*z4 - w4*w4 - v4*v4;
if (t < 0) n4 = 0;
else
{
t *= t;
n4 = t*t * GradCoord5D(offset, i + i4, j + j4, k + k4, l + l4, h + h4, x4, y4, z4, w4, v4);
}
t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w4*w4 - v5*v5;
if (t < 0) n5 = 0;
else
{
t *= t;
n5 = t * t * GradCoord5D(offset, i + 1, j + 1, k + 1, l + 1, h + 1, x5, y5, z5, w5, v5);
}
return 8 * (n0 + n1 + n2 + n3 + n4 + n5); // TODO: Find value scaler
}GradCoord5包括:
inline FN_DECIMAL FastNoise::GradCoord5D(unsigned char offset, int x, int y, int z, int w, int v, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd, FN_DECIMAL vd) const
{
unsigned char lutPos = Index5D_80(offset, x, y, z, w, v) * 5;
return xd * GRAD_5D[lutPos] + yd * GRAD_5D[lutPos + 1] + zd * GRAD_5D[lutPos + 2] + wd * GRAD_5D[lutPos + 3] + vd * GRAD_5D[lutPos + 4];
}Index5D_80包括:
unsigned char FastNoise::Index5D_80(unsigned char offset, int x, int y, int z, int w, int v) const
{
return m_perm80[(x & 0xff) + m_perm[(y & 0xff) + m_perm[(z & 0xff) + m_perm[(w & 0xff) + m_perm[(v & 0xff) + offset]]]]];
}数组GRAD_5D是一个长400个项的数组,每个值表示对角向量。数组m_perm是一个长512个项的排列数组,值从0到255,按随机顺序排列,数组的后半部分与前半部分相同。数组m_perm80也是一个512个条目长的数组,但是m_perm的值被模块化了80。(因为GRAD_5D中有80个梯度)
目前,我不确定FN_DECIMAL(0.5)s是否真的应该是FN_DECIMAL(0.6),就像Stefan Gustavson在3D & 4D单纯形噪声函数和SimplexNoise.java中所看到的那样。古斯塔夫森在单纯形噪声消隐中说,这个值应该改为0.5 (但在他自己的源代码中没有做到这一点?)肯·佩林使用0.6在他关于单纯形噪声的论文中,但是它只是一个幻数,他没有解释它的意义或起源。
我也不确定8在返回最终值时是否将n个组件的和“正常化”,尽管它做了合理的工作,将值保持在一个可用范围内。
我对这个数学堆栈交换问题感到困惑,它声称正常化值实际上应该是67.695367.6953。该值确实使噪声在值的变化上更接近四维噪声,但也使一些值超出-1和1,使对角线区域更加明显,钻石伪影更加清晰。

然而,正常化因素似乎并不是问题所在,因为它只是在-1到1的范围内带来了数值。
无论FN_DECIMAL(0.5)值被正式命名(我认为它可能是球形核半径,我找不到任何硬证明),减少它使值更接近0(实际上使图像更平坦,因为它使得t小于0,因此不使用该顶点的贡献)。肯·佩林的确提到“以每个单纯形为中心的超球面核的精确半径和振幅都需要进行调整,以便为每一种选择的n产生最佳的视觉效果”,事实上,把这个值推到0.8 (并将标准化值降到6)确实会产生一个更吸引人的图像,但是它不能消除奇怪的钻石形状,而对角线仍然可以被看作是钻石制品下的稍模糊的区域。

是什么导致了这些文物?这可能是索引问题吗?还有别的吗?
发布于 2018-07-15 16:48:52
事实证明,造成可见钻石(单纯形)形状的原因是一个不幸的错误。
线
t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w4*w4 - v5*v5;应该是
t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w5*w5 - v5*v5;我在没有规范化值的情况下运行了一些迭代,以找到函数的自然最小/最大值,并使用这些迭代来计算规范化值,并对falloff函数进行调整,以找到输出在视觉上具有吸引力的一个很好的点。最后的职能是:
FN_DECIMAL FastNoise::SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w, FN_DECIMAL v) const
{
static const FN_DECIMAL norm = FN_DECIMAL(10.733025427569862289390260016388);
FN_DECIMAL n0, n1, n2, n3, n4, n5;
FN_DECIMAL t = (x + y + z + w + v) * F5;
int i = FastFloor(x + t);
int j = FastFloor(y + t);
int k = FastFloor(z + t);
int l = FastFloor(w + t);
int h = FastFloor(v + t);
t = (i + j + k + l + h) * G5;
FN_DECIMAL X0 = i - t;
FN_DECIMAL Y0 = j - t;
FN_DECIMAL Z0 = k - t;
FN_DECIMAL W0 = l - t;
FN_DECIMAL V0 = h - t;
FN_DECIMAL x0 = x - X0;
FN_DECIMAL y0 = y - Y0;
FN_DECIMAL z0 = z - Z0;
FN_DECIMAL w0 = w - W0;
FN_DECIMAL v0 = v - V0;
int rankx = 0;
int ranky = 0;
int rankz = 0;
int rankw = 0;
int rankv = 0;
if (x0 > y0) rankx++; else ranky++;
if (x0 > z0) rankx++; else rankz++;
if (x0 > w0) rankx++; else rankw++;
if (x0 > v0) rankx++; else rankv++;
if (y0 > z0) ranky++; else rankz++;
if (y0 > w0) ranky++; else rankw++;
if (y0 > v0) ranky++; else rankv++;
if (z0 > w0) rankz++; else rankw++;
if (z0 > v0) rankz++; else rankv++;
if (w0 > v0) rankw++; else rankv++;
int i1 = rankx >= 4 ? 1 : 0;
int j1 = ranky >= 4 ? 1 : 0;
int k1 = rankz >= 4 ? 1 : 0;
int l1 = rankw >= 4 ? 1 : 0;
int h1 = rankv >= 4 ? 1 : 0;
int i2 = rankx >= 3 ? 1 : 0;
int j2 = ranky >= 3 ? 1 : 0;
int k2 = rankz >= 3 ? 1 : 0;
int l2 = rankw >= 3 ? 1 : 0;
int h2 = rankv >= 3 ? 1 : 0;
int i3 = rankx >= 2 ? 1 : 0;
int j3 = ranky >= 2 ? 1 : 0;
int k3 = rankz >= 2 ? 1 : 0;
int l3 = rankw >= 2 ? 1 : 0;
int h3 = rankv >= 2 ? 1 : 0;
int i4 = rankx >= 1 ? 1 : 0;
int j4 = ranky >= 1 ? 1 : 0;
int k4 = rankz >= 1 ? 1 : 0;
int l4 = rankw >= 1 ? 1 : 0;
int h4 = rankv >= 1 ? 1 : 0;
FN_DECIMAL x1 = x0 - i1 + G5;
FN_DECIMAL y1 = y0 - j1 + G5;
FN_DECIMAL z1 = z0 - k1 + G5;
FN_DECIMAL w1 = w0 - l1 + G5;
FN_DECIMAL v1 = v0 - h1 + G5;
FN_DECIMAL x2 = x0 - i2 + 2 * G5;
FN_DECIMAL y2 = y0 - j2 + 2 * G5;
FN_DECIMAL z2 = z0 - k2 + 2 * G5;
FN_DECIMAL w2 = w0 - l2 + 2 * G5;
FN_DECIMAL v2 = v0 - h2 + 2 * G5;
FN_DECIMAL x3 = x0 - i3 + 3 * G5;
FN_DECIMAL y3 = y0 - j3 + 3 * G5;
FN_DECIMAL z3 = z0 - k3 + 3 * G5;
FN_DECIMAL w3 = w0 - l3 + 3 * G5;
FN_DECIMAL v3 = v0 - h3 + 3 * G5;
FN_DECIMAL x4 = x0 - i4 + 4 * G5;
FN_DECIMAL y4 = y0 - j4 + 4 * G5;
FN_DECIMAL z4 = z0 - k4 + 4 * G5;
FN_DECIMAL w4 = w0 - l4 + 4 * G5;
FN_DECIMAL v4 = v0 - h4 + 4 * G5;
FN_DECIMAL x5 = x0 - 1 + 5 * G5;
FN_DECIMAL y5 = y0 - 1 + 5 * G5;
FN_DECIMAL z5 = z0 - 1 + 5 * G5;
FN_DECIMAL w5 = w0 - 1 + 5 * G5;
FN_DECIMAL v5 = v0 - 1 + 5 * G5;
t = FN_DECIMAL(0.7) - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0 - v0 * v0;
if (t < 0) n0 = 0;
else
{
t *= t;
n0 = t * t * GradCoord5D(offset, i, j, k, l, h, x0, y0, z0, w0, v0);
}
t = FN_DECIMAL(0.7) - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1 - v1 * v1;
if (t < 0) n1 = 0;
else
{
t *= t;
n1 = t * t * GradCoord5D(offset, i + i1, j + j1, k + k1, l + l1, h + h1, x1, y1, z1, w1, v1);
}
t = FN_DECIMAL(0.7) - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2 - v2 * v2;
if (t < 0) n2 = 0;
else
{
t *= t;
n2 = t * t * GradCoord5D(offset, i + i2, j + j2, k + k2, l + l2, h + h2, x2, y2, z2, w2, v2);
}
t = FN_DECIMAL(0.7) - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3 - v3 * v3;
if (t < 0) n3 = 0;
else
{
t *= t;
n3 = t * t * GradCoord5D(offset, i + i3, j + j3, k + k3, l + l3, h + h3, x3, y3, z3, w3, v3);
}
t = FN_DECIMAL(0.7) - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4 - v4 * v4;
if (t < 0) n4 = 0;
else
{
t *= t;
n4 = t * t * GradCoord5D(offset, i + i4, j + j4, k + k4, l + l4, h + h4, x4, y4, z4, w4, v4);
}
t = FN_DECIMAL(0.7) - x5 * x5 - y5 * y5 - z5 * z5 - w5 * w5 - v5 * v5;
if (t < 0) n5 = 0;
else
{
t *= t;
n5 = t * t * GradCoord5D(offset, i + 1, j + 1, k + 1, l + 1, h + 1, x5, y5, z5, w5, v5);
}
return (n0 + n1 + n2 + n3 + n4 + n5) * norm; // TODO: Find value scaler
}https://computergraphics.stackexchange.com/questions/6408
复制相似问题