C++ 什么';是什么造成了我的2D柏林噪音中的这些人工制品?
我实现了。为3D噪波提供的代码工作正常 我调整了算法,以一种看似显而易见的方式制作了一个2D版本。它几乎可以工作,但会产生如下图所示的人工制品 以下是正确的3D版本:C++ 什么';是什么造成了我的2D柏林噪音中的这些人工制品?,c++,perlin-noise,C++,Perlin Noise,我实现了。为3D噪波提供的代码工作正常 我调整了算法,以一种看似显而易见的方式制作了一个2D版本。它几乎可以工作,但会产生如下图所示的人工制品 以下是正确的3D版本: unsigned inc (unsigned number) { return (number + 1) & 255; } double fade (double t) { // Fade function as defined by Ken Perlin. // This eases coord
unsigned inc (unsigned number)
{
return (number + 1) & 255;
}
double fade (double t)
{
// Fade function as defined by Ken Perlin.
// This eases coordinate values
// so that they will "ease" towards integral values.
// This ends up smoothing the final output.
// 6t^5 - 15t^4 + 10t^3
return t * t * t * (t * (t * 6 - 15) + 10);
}
double lerp (double a, double b, double x)
{
return a + x * (b - a);
}
double grad (unsigned hash, double x, double y, double z)
{
// Take the hashed value and take the first 4 bits of it
// (15 == 0b1111)
unsigned h = hash & 15;
// If the most significant bit (MSB) of the hash is 0
// then set u = x. Otherwise y.
double u = h < 8 /* 0b1000 */ ? x : y;
double v;
if (h < 4 /* 0b0100 */)
// If the first and second significant bits
// are 0, set v = y
v = y;
else if (h == 12 /* 0b1100 */ || h == 14 /* 0b1110*/)
// If the first and second significant bits
// are 1, set v = x
v = x;
else
// If the first and second significant bits are not
// equal (0/1, 1/0) set v = z
v = z;
// Use the last 2 bits to decide if u and v are positive
// or negative. Then return their addition.
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}
double
ImprovedNoise :: noise (double x, double y, double z)
{
// Calculate the "unit cube" that the point asked will be located in
// The left bound is ( |_x_|,|_y_|,|_z_| ) and the right bound is that
// plus 1. Next we calculate the location (from 0.0 to 1.0) in that
// cube. We also fade the location to smooth the result.
int xi = (int)x & 255;
int yi = (int)y & 255;
int zi = (int)z & 255;
double xf = x - (int) x;
double yf = y - (int) y;
double zf = z - (int) z;
double u = fade (xf);
double v = fade (yf);
double w = fade (zf);
int aaa, aba, aab, abb, baa, bba, bab, bbb;
auto & p = permutation;
aaa = p[p[p[ xi ] + yi ] + zi ];
aba = p[p[p[ xi ] + inc(yi)] + zi ];
aab = p[p[p[ xi ] + yi ] + inc(zi)];
abb = p[p[p[ xi ] + inc(yi)] + inc(zi)];
baa = p[p[p[inc(xi)] + yi ] + zi ];
bba = p[p[p[inc(xi)] + inc(yi)] + zi ];
bab = p[p[p[inc(xi)] + yi ] + inc(zi)];
bbb = p[p[p[inc(xi)] + inc(yi)] + inc(zi)];
double x1, x2, y1, y2;
// The gradient function calculates the dot product between a
// pseudorandom gradient vector and the vector from the input
// coordinate to the 8 surrounding points in its unit cube.
// This is all then lerped together as a sort of weighted average
// based on the faded (u,v,w) values we made earlier.
x1 = lerp (
grad (aaa, xf , yf , zf),
grad (baa, xf-1, yf , zf),
u);
x2 = lerp (
grad (aba, xf , yf-1, zf),
grad (bba, xf-1, yf-1, zf),
u);
y1 = lerp (x1, x2, v);
x1 = lerp (
grad (aab, xf , yf , zf-1),
grad (bab, xf-1, yf , zf-1),
u);
x2 = lerp (
grad (abb, xf , yf-1, zf-1),
grad (bbb, xf-1, yf-1, zf-1),
u);
y2 = lerp (x1, x2, v);
auto result = (lerp (y1, y2, w) + 1) / 2;
assert (0 <= result);
assert (result <= 1);
assert (false == std :: isnan (result));
return result;
}
double grad (unsigned hash, double x, double y)
{
double u = (hash & 1) ? x : y;
double v = (hash & 2) ? x : y;
return ((hash & 4) ? u : -u) + (hash & 8) ? v : -v;
}
double
ImprovedNoise :: noise (double x, double y)
{
int xi = (int)x & 255;
int yi = (int)y & 255;
double xf = x - (int) x;
double yf = y - (int) y;
double u = fade (xf);
double v = fade (yf);
int aaa, aba,baa, bba;
auto & p = permutation;
aaa = p[p[ xi ] + yi ];
aba = p[p[ xi ] + inc(yi)];
baa = p[p[inc(xi)] + yi ];
bba = p[p[inc(xi)] + inc(yi)];
double x1, x2;
// The gradient function calculates the dot product between a
// pseudorandom gradient vector and the vector from the input
// coordinate to the 8 surrounding points in its unit cube.
// This is all then lerped together as a sort of weighted average
// based on the faded (u,v,w) values we made earlier.
x1 = lerp (
grad (aaa, xf , yf),
grad (baa, xf-1, yf),
u);
x2 = lerp (
grad (aba, xf , yf-1),
grad (bba, xf-1, yf-1),
u);
double result = (lerp (x1, x2, v) + 1) / 2;
assert (0 <= result);
assert (result <= 1);
assert (false == std :: isnan (result));
return result;
}
这是它生成的图像
它是使用以下方法生成的:
int size=400;
int freq=10;
create_widget (size, size, [&] (int x, int y)
{
return noise (x*freq / float (size), y*freq / float (size));
});
是什么导致了这些水平线和垂直线?我认为这可能是一个整数边界问题,但这将预测整个图像中的freq
伪影,所以我猜这是另外一回事
您能看到错误是什么吗?grad中可能有错误(
+
的优先级高于?:
),这会导致特定xf
/yf
/散列值的结果发生突然变化(无论如何都不正确)
return ((hash & 4) ? u : -u) + (hash & 8) ? v : -v;
( )
我希望,如果它在3D中z=0工作,但在2D中不工作,那么您只需要对代码进行并排比较,看看发生了什么变化。换句话说,z=0时,2D代码与3D代码有何不同?如何定义排列?