I have a problem generating 3D Noise.
I've written a framework that uses DirectX11 to render everything.
I generate a Geo-sphere and modify the height values using a 3D Simplex Noise function.
The problem is that when I see the result I see sudden changes in height that are not noise like at all...
(the rectangle shape in the center of the picture)
I've modified the Persistence to 0.1 so the error is easily seen here...
I can't figure out the issue with the sudden height changes. This is an error, right?
I calculate the height with the following...
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;
}
Also, changing the base coordinates of the function doesn't get rid of this weird output. (for anyone who thinks that starting at 0,0,0 was messing it up somehow)
Noise Implementation
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;
I found the solution...
Solution: I was silly. I had a dumb error in my raw noise function but i fixed it now
This is the fixed part of the code
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;
}
}
Turned out I had several incorrect values in the old one.