3D 单纯形噪声高度突然变化
3D Simplex Noise Sudden Height Change
我在生成 3D 噪点时遇到问题。
我已经编写了一个使用 DirectX11 来呈现所有内容的框架。
我生成一个 Geo-sphere 并使用 3D Simplex Noise 函数修改高度值。
问题是,当我看到结果时,我看到高度的突然变化根本不像噪声...
(图片中间的长方形)
我已将 Persistence 修改为 0.1,因此此处很容易看到错误...
我无法弄清楚身高突然变化的问题。这是一个错误,对吧?
我用以下方法计算身高...
for( int i = 0; i < sphere.Vertices.size(); ++i )
{
// seperate out our positions
float x = sphere.Vertices[ i ].Position.x;
float y = sphere.Vertices[ i ].Position.y;
float z = sphere.Vertices[ i ].Position.z;
// get our noise value ( -1 to 1 )
float ix = noise.octavenoise3D( 10, 0.1, 0.5, x, y, z, perm, &grad3[0][0] );
// pack our coordinates into a vector
XMVECTOR curPos = { x, y, z };
// get the normalized vector of our position
XMVECTOR normPos = XMVector3Normalize( curPos );
// seperate our normalzed x y and z
float normX = XMVectorGetX( normPos );
float normY = XMVectorGetY( normPos );
float normZ = XMVectorGetZ( normPos );
// figure out the height of this specific vertice, maxHeight = sphereRadius / 3.0f;
float height = ix * maxHeight;
float change = height + sphereRadius;
// calculate the offset x y and z by the noise
float changeX = change * normX;
float changeY = change * normY;
float changeZ = change * normZ;
// save our new x y and z
vertices[ i ].Pos.x = x + changeX;
vertices[ i ].Pos.y = y + changeY;
vertices[ i ].Pos.z = z + changeZ;
// calculate color based on noise value
float colorChange = ( 0.5f * ix );
float color = 0.5f + colorChange;
// save color value in r g b
vertices[ i ].Color.x = color;
vertices[ i ].Color.y = color;
vertices[ i ].Color.z = color;
}
另外,改变函数的基坐标并不能消除这个奇怪的输出。 (对于那些认为从 0,0,0 开始的人不知何故搞砸了)
噪声实现
float Noise::octavenoise3D( const float octaves, const float persistence,
const float scale, const float x, const float y, const float z, int *perm, int *grad3)
float total = 0;
float frequency = scale;
float amplitude = 1;
float maxAmplitude = 0;
for( int i = 0; i < octaves; i++ )
{
total = total + rawnoise3D( x * frequency, y * frequency, z * frequency, perm, grad3 ) * amplitude;
frequency = frequency * 2;
maxAmplitude = maxAmplitude + amplitude;
amplitude = amplitude * persistence;
}
return total / maxAmplitude;
float Noise::rawnoise3D(const float x, const float y, const float z, int *perm, int *grad3)
float n0, n1, n2, n3;
float F3 = 1.0 / 3.0;
float s = ( x + y + z ) * F3;
int i = fastfloor( x + s );
int j = fastfloor( y + s );
int k = fastfloor( z + s );
float G3 = 1.0 / 6.0;
float t = ( i + j + k ) * G3;
float X0 = i - t;
float Y0 = j - t;
float Z0 = k - t;
float x0 = x - X0;
float y0 = y - Y0;
float z0 = z - Z0;
int i1, j1, k1;
int i2, j2, k2;
if( x0 >= y0 )
{
if( y0 >= z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 1;
k2 = 0;
}
else if( x0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
}
else
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
}
else
{
if( y0 < z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 0;
}
else if( x0 < z0 )
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
}
else
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
float x1 = x0 - i1 + G3;
float y1 = y0 - j1 + G3;
float z1 = z0 - k1 + G3;
float x2 = x0 - i2 + 2.0 * G3;
float y2 = y0 - j2 + 2.0 *G3;
float z2 = z0 - k2 + 2.0 *G3;
float x3 = x0 - 1.0 + 3.0 * G3;
float y3 = y0 - 1.0 + 3.0 * G3;
float z3 = z0 - 1.0 + 3.0 * G3;
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int gi0 = perm[ ii + perm[ jj + perm[ kk ] ] ] % 12;
int gi1 = perm[ ii+ i1 + perm[ jj + j1 + perm[ kk + k1 ] ] ] % 12;
int gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 ] ] ] % 12;
int gi3 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 ] ] ] % 12;
float t0 = 0.6 - ( x0 * x0 ) - ( y0 * y0 ) - ( z0 * z0 );
if( t0 < 0 )
{
n0 = 0.0;
}
else
{
t0 = t0 * t0;
n0 = ( t0 * t0 ) * dot( &grad3[ gi0 ], x0, y0, z0);
}
float t1 = 0.6 - ( x1 * x1 ) - ( y1 * y1 ) - ( z1 * z1 );
if( t1 < 0 )
{
n1 = 0.0;
}
else
{
t1 *= t1;
n1 = ( t1 * t1 ) * dot( &grad3[ gi1 ], x1, y1, z1);
}
float t2 = 0.6 - ( x2 * x2 ) - ( y2 * y2 ) - ( z2 * z2 );
if( t2 < 0 )
{
n2 = 0.0;
}
else
{
t2 *= t2;
n2 = ( t2 * t2 ) * dot( &grad3[ gi2 ], x2, y2, z2);
}
float t3 = 0.6 - ( x3 * x3 ) - ( y3 * y3 ) - ( z3 * z3 );
if( t3 < 0 )
{
n3 = 0.0;
}
else
{
t3 = t3 * t3;
n3 = t3 * t3 * dot( &grad3[ gi3 ], x3, y3, z3);
}
float final = 32.0 * ( n0 + n1 + n2 + n3 );
return final;
int Noise::fastfloor( const float x )
return x > 0 ? (int)x : (int)x - 1;
float Noise::dot( const int* g, const float x, const float y, const float z )
return g[0]*x + g[1]*y + g[2]*z;
我找到了解决方案...
解决办法:我傻了。我的原始噪声函数中有一个愚蠢的错误,但我现在修复了它
这是代码的固定部分
if( x0 >= y0 )
{
if( y0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
else if( x0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
}
else
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
}
else
{
if( y0 < z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
}
else if( x0 < z0 )
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
}
else
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
原来我在旧值中有几个不正确的值。
我在生成 3D 噪点时遇到问题。
我已经编写了一个使用 DirectX11 来呈现所有内容的框架。
我生成一个 Geo-sphere 并使用 3D Simplex Noise 函数修改高度值。
问题是,当我看到结果时,我看到高度的突然变化根本不像噪声...
(图片中间的长方形)
我已将 Persistence 修改为 0.1,因此此处很容易看到错误...
我无法弄清楚身高突然变化的问题。这是一个错误,对吧?
我用以下方法计算身高...
for( int i = 0; i < sphere.Vertices.size(); ++i )
{
// seperate out our positions
float x = sphere.Vertices[ i ].Position.x;
float y = sphere.Vertices[ i ].Position.y;
float z = sphere.Vertices[ i ].Position.z;
// get our noise value ( -1 to 1 )
float ix = noise.octavenoise3D( 10, 0.1, 0.5, x, y, z, perm, &grad3[0][0] );
// pack our coordinates into a vector
XMVECTOR curPos = { x, y, z };
// get the normalized vector of our position
XMVECTOR normPos = XMVector3Normalize( curPos );
// seperate our normalzed x y and z
float normX = XMVectorGetX( normPos );
float normY = XMVectorGetY( normPos );
float normZ = XMVectorGetZ( normPos );
// figure out the height of this specific vertice, maxHeight = sphereRadius / 3.0f;
float height = ix * maxHeight;
float change = height + sphereRadius;
// calculate the offset x y and z by the noise
float changeX = change * normX;
float changeY = change * normY;
float changeZ = change * normZ;
// save our new x y and z
vertices[ i ].Pos.x = x + changeX;
vertices[ i ].Pos.y = y + changeY;
vertices[ i ].Pos.z = z + changeZ;
// calculate color based on noise value
float colorChange = ( 0.5f * ix );
float color = 0.5f + colorChange;
// save color value in r g b
vertices[ i ].Color.x = color;
vertices[ i ].Color.y = color;
vertices[ i ].Color.z = color;
}
另外,改变函数的基坐标并不能消除这个奇怪的输出。 (对于那些认为从 0,0,0 开始的人不知何故搞砸了)
噪声实现
float Noise::octavenoise3D( const float octaves, const float persistence, const float scale, const float x, const float y, const float z, int *perm, int *grad3)
float total = 0;
float frequency = scale;
float amplitude = 1;
float maxAmplitude = 0;
for( int i = 0; i < octaves; i++ )
{
total = total + rawnoise3D( x * frequency, y * frequency, z * frequency, perm, grad3 ) * amplitude;
frequency = frequency * 2;
maxAmplitude = maxAmplitude + amplitude;
amplitude = amplitude * persistence;
}
return total / maxAmplitude;
float Noise::rawnoise3D(const float x, const float y, const float z, int *perm, int *grad3)
float n0, n1, n2, n3;
float F3 = 1.0 / 3.0;
float s = ( x + y + z ) * F3;
int i = fastfloor( x + s );
int j = fastfloor( y + s );
int k = fastfloor( z + s );
float G3 = 1.0 / 6.0;
float t = ( i + j + k ) * G3;
float X0 = i - t;
float Y0 = j - t;
float Z0 = k - t;
float x0 = x - X0;
float y0 = y - Y0;
float z0 = z - Z0;
int i1, j1, k1;
int i2, j2, k2;
if( x0 >= y0 )
{
if( y0 >= z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 1;
k2 = 0;
}
else if( x0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
}
else
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
}
else
{
if( y0 < z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 0;
}
else if( x0 < z0 )
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
}
else
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
float x1 = x0 - i1 + G3;
float y1 = y0 - j1 + G3;
float z1 = z0 - k1 + G3;
float x2 = x0 - i2 + 2.0 * G3;
float y2 = y0 - j2 + 2.0 *G3;
float z2 = z0 - k2 + 2.0 *G3;
float x3 = x0 - 1.0 + 3.0 * G3;
float y3 = y0 - 1.0 + 3.0 * G3;
float z3 = z0 - 1.0 + 3.0 * G3;
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int gi0 = perm[ ii + perm[ jj + perm[ kk ] ] ] % 12;
int gi1 = perm[ ii+ i1 + perm[ jj + j1 + perm[ kk + k1 ] ] ] % 12;
int gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 ] ] ] % 12;
int gi3 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 ] ] ] % 12;
float t0 = 0.6 - ( x0 * x0 ) - ( y0 * y0 ) - ( z0 * z0 );
if( t0 < 0 )
{
n0 = 0.0;
}
else
{
t0 = t0 * t0;
n0 = ( t0 * t0 ) * dot( &grad3[ gi0 ], x0, y0, z0);
}
float t1 = 0.6 - ( x1 * x1 ) - ( y1 * y1 ) - ( z1 * z1 );
if( t1 < 0 )
{
n1 = 0.0;
}
else
{
t1 *= t1;
n1 = ( t1 * t1 ) * dot( &grad3[ gi1 ], x1, y1, z1);
}
float t2 = 0.6 - ( x2 * x2 ) - ( y2 * y2 ) - ( z2 * z2 );
if( t2 < 0 )
{
n2 = 0.0;
}
else
{
t2 *= t2;
n2 = ( t2 * t2 ) * dot( &grad3[ gi2 ], x2, y2, z2);
}
float t3 = 0.6 - ( x3 * x3 ) - ( y3 * y3 ) - ( z3 * z3 );
if( t3 < 0 )
{
n3 = 0.0;
}
else
{
t3 = t3 * t3;
n3 = t3 * t3 * dot( &grad3[ gi3 ], x3, y3, z3);
}
float final = 32.0 * ( n0 + n1 + n2 + n3 );
return final;
int Noise::fastfloor( const float x )
return x > 0 ? (int)x : (int)x - 1;
float Noise::dot( const int* g, const float x, const float y, const float z )
return g[0]*x + g[1]*y + g[2]*z;
我找到了解决方案...
解决办法:我傻了。我的原始噪声函数中有一个愚蠢的错误,但我现在修复了它
这是代码的固定部分
if( x0 >= y0 )
{
if( y0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
else if( x0 >= z0 )
{
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
}
else
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
}
else
{
if( y0 < z0 )
{
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
}
else if( x0 < z0 )
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
}
else
{
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
原来我在旧值中有几个不正确的值。