Sign in to follow this  
Paul7

3D Perlin Noise

Recommended Posts

I`m trying to create 3D perlin noise using the improved Perlin Noise found here but using time as the third parameter. Ive tried converting his source code into C++ but all i`m getting is black and white noise. Do the inputs into the noise funtion have to have a value to the decimal part of them i.e. not 1.0, 2.0, 3.0 but for example 1.3, 2.63. I think I read somewhere that if they are whole numbers then it wont produce anything? In which case should I divide the x and y values from the loops by some factor? Hope you can understand what I mean. my source code is as follows:
int *p;

int permutation[] = { 151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};

int main()
{
	p = new int[512];
    for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i];

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  
	glutInitWindowSize(NPIXELS, NPIXELS);  
	glutInitWindowPosition(100, 100);  
	glutCreateWindow("Perlin Noise");
	glutKeyboardFunc(Keyboard);
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glLoadIdentity();  
	gluOrtho2D(0, NPIXELS, 0, NPIXELS);
	glutDisplayFunc(display);
	glutMainLoop();
}

void display(void) 
{ 
	int x,y;
	float pnoise, time;
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f (0.0, 0.4, 0.0);
    glPointSize((float)1);

	glBegin(GL_POINTS);
	for(x = 0; x <= 256; x++)
	{
		for(y = 0; y<= 256; y++)
		{
				time=0.5;
				pnoise = noise(x, y, time) ;

				glColor3f(pnoise, pnoise, pnoise);
				glVertex2i(x, y);
		}
	}
	glEnd();

	glutSwapBuffers();
	glFlush();
} 

double noise(double x, double y, double z) 
{
    int X = (int)floor(x) & 255,                  // FIND UNIT CUBE THAT
        Y = (int)floor(y) & 255,                  // CONTAINS POINT.
        Z = (int)floor(z) & 255;
    x -= floor(x);                                // FIND RELATIVE X,Y,Z
    y -= floor(y);                                // OF POINT IN CUBE.
    z -= floor(z);
    double u = fade(x),                                // COMPUTE FADE CURVES
            v = fade(y),                                // FOR EACH OF X,Y,Z.
            w = fade(z);
    int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,      // HASH COORDINATES OF
        B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,

    return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  // AND ADD
                                    grad(p[BA  ], x-1, y  , z   )), // BLENDED
                            lerp(u, grad(p[AB  ], x  , y-1, z   ),  // RESULTS
                                    grad(p[BB  ], x-1, y-1, z   ))),// FROM  8
                    lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
                                    grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
                            lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                    grad(p[BB+1], x-1, y-1, z-1 ))));
}

double fade(double t) 
{ 
	return t * t * t * (t * (t * 6 - 15) + 10); 
}

double lerp(double t, double a, double b) 
{ 
	return a + t * (b - a); 
}

double grad(int hash, double x, double y, double z)
{
    int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
    double u = h<8 ? x : y,                 // INTO 12 GRADIENT DIRECTIONS.
            v = h<4 ? y : h==12||h==14 ? x : z;
    return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}


Does this look ok? Ive just set time to a constant for the moment while I get it working. Thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by Paul7
I`m trying to create 3D perlin noise using the improved Perlin Noise found here but using time as the third parameter.
...
Do the inputs into the noise funtion have to have a value to the decimal part of them i.e. not 1.0, 2.0, 3.0 but for example 1.3, 2.63. I think I read somewhere that if they are whole numbers then it wont produce anything? In which case should I divide the x and y values from the loops by some factor? Hope you can understand what I mean.

I used this code as base for my own perlin noise and it wokrs just fine. I do similar as you but I scale inputs in 0..1 range.
( pnoise = noise(x/255.0f, y/255.0f, time); )

Share this post


Link to post
Share on other sites
Thanks thats improved it but getting this now:


Any thoughts why?

Also is there any way to alter the persistance, frequency and number of octaves with this code or are they encoded into it giving a fixed result based on all the numbers in the permutation array?

Share this post


Link to post
Share on other sites
Your code actualy calculates just one octave of perlin noise. You have to add them together with different amplitudes and frequencys to make it look good. There is not much you can do by chnaging this code.


// get 3D noise
float CBFM::Noise( float x, float y, float z ) {
float result = 0.0f;
for ( unsigned int i=0; i<octaves; ++i ) {
result += perlinNoise.Noise( x, y, z ) * amplitudeLUT[ i ];
x *= lacunarity;
y *= lacunarity;
z *= lacunarity;
}
return result;
}

Share this post


Link to post
Share on other sites
Right so Ive now got my perlin noise working so it animates dependant upon time. I`m wanting to use this for water simulation and its too slow to calculate it every frame.

It was suggested to me before to generate a set of samples and interpolate between them. This needs to be made tileable so I can loop the playback of the samples. Any suggestions on how I go about doing this?

Thanks.

Share this post


Link to post
Share on other sites
Thanks that works great.

Just one more question. When using this as a heightmap for my water can I also use it to calculate the normals and then intepolate these between the samples also?

Share this post


Link to post
Share on other sites
Quote:
Original post by Paul7
When using this as a heightmap for my water can I also use it to calculate the normals and then intepolate these between the samples also?

Yes, but you'll probably have to renormalize them. Preferebly at perpixel level. It's not a problem if you use fragment programs / pixel shaders.

Share this post


Link to post
Share on other sites
I`m having difficulty in getting this to look good for my water movement. I know its not the best method to use for water but should give reasonable results.

For the Perlin noise does anyone have any recommended values for the frequency, amplitude, etc.? and how many octaves would you recomend using?

When interpolating samples, how many samples should I use. At the moment I am only doing 10 and sampling it every second for ten seconds. I think this should be sampled more frequently but then I will end up with loads of samples increasing the memory requirements.

Any suggestions?

Thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by Paul7
For the Perlin noise does anyone have any recommended values for the frequency, amplitude, etc.? and how many octaves would you recomend using?

For that you have to try yourself. Make your system so you can change those values at runtime and watch the results. You might also want to use modified perlin noise (turbolence, sin/cos noise,...).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this