Jump to content
  • Advertisement
Sign in to follow this  
Fiodis

Perlin noise trouble

This topic is 1843 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello Gamedev.net!  I've been lurking about for a few months reading tutorials, but only just now got around to making an account.  

 

Anyway, I recently read this quite easy to understand perlin noise tutorial.  I tried to build my own perlin noise function closely following it, but when I try to fill a bitmap it creates an image of TV-like static with some repeating elements:

perlin-1.png

When I divide the input pixel coordinates by 64, which has the effect of zooming in, it looks a bit more like noise, but it's horribly blocky:

perlin-3.png

Searching, I found an old thread on the subject here, but wasn't able to glean a solution from it.  I appear to be missing something here - perhaps I'm casting a float to an int or something where I shouldn't be, and losing some information.  The code:

float intNoise(int x, int which){// which determines which of the five random number generators below to use
	if (which == 1){
		x = (x<<13)^x;
		return (float)(1.0f - ((x * (x * x * 15731 + 789221) + 1376312589) & 2147483647)/ 1073741824.0);
	}
	else if (which == 2){
		x = (x<<13)^x;
		return (float)(1.0f - ((x * (x * x * 89107 + 300109) + 800143) & 2147483647)/ 973801.0);
	}
	else if (which == 3){
		x = (x<<13)^x;
		return (float)(1.0f - ((x * (x * x * 58937 + 351991) + 832883) & 989171)/ 1073741824.0);
	}
	else if (which == 4){
		x = (x<<13)^x;
		return (float)(1.0f - ((x * (x * x * 44417 + 390991) + 865847) & 2147483647)/ 1073741824.0);
	}
	else if (which == 5){
		x = (x<<13)^x;
		return (float)(1.0f - ((x * (x * x * 35803 + 399983) + 1376312589) & 2147483647)/ 1073741824.0);
	}
}

float cosineInterpolate(float a, float b, float x){
	float ft = x * 3.1415927f;
	float f = (1.0f - cos(ft)) * 0.5f;
	return (a * (1.0f - f)) + (b * f);
}

float noise2DPure(float x, float y, int which){
	float n = x + y * 57;
	return intNoise(int(n), which);
}

float smoothNoise_2DPure(float x, float y, int which){
	float corners = (noise2DPure(x-1.0f, y-1.0f, which) + noise2DPure(x+1.0f, y+1.0f, which) + noise2DPure(x-1.0f, y+1.0f, which) + noise2DPure(x+1.0f, y-1.0f, which))/16.0f;
	float sides = (noise2DPure(x, y-1.0f, which) + noise2DPure(x, y+1.0f, which) + noise2DPure(x-1.0f, y, which) + noise2DPure(x+1.0f, y, which))/8.0f;
	float center = (noise2DPure(x, y, which))/4.0f;
	return center + sides + corners;
}

float interpolateNoise2DPure(float x, float y, int which){
	int integer_X = (int)x;
	int integer_Y = (int)y;
	float fractional_X = x - (float)integer_X;
	float fractional_Y = y - (float)integer_Y;

	float v1 = smoothNoise_2DPure((float)integer_X, (float)integer_Y, which);
	float v2 = smoothNoise_2DPure((float)(integer_X + 1), (float)integer_Y, which);
	float v3 = smoothNoise_2DPure((float)integer_X, (float)(integer_Y + 1), which);
	float v4 = smoothNoise_2DPure((float)(integer_X + 1), (float)(integer_Y + 1), which);

	float i1 = cosineInterpolate(v1, v2, fractional_X);
	float i2 = cosineInterpolate(v3, v4, fractional_X);

	return cosineInterpolate(i1, i2, fractional_Y);
}

float perlinNoise2DVary(float x, float y, float persistence, int octaves){
	float total = 0;
	float p = persistence;
	int n = octaves - 1;
	for (int i = 0; i <= n; i++){
		float frequency = powf(2.0f, (float)i);
		float amplitude = powf(p, (float)i);
		total += interpolateNoise2DPure(x * frequency, y * frequency, i+1) * amplitude;
	}
	return total;
}

// Bitmap fill:
int main(int argc, char argv[]){
	const unsigned int res = 256;
	float min = 1.0f;
	float max = 0.0f;
	unsigned char *picArr = new unsigned char[res*res*3];
	for (unsigned int i = 0; i < res; i++){
		for (unsigned int j = 0; j < res; j++){
			picArr[3*(i*res + j)] = char(int(((perlinNoise2DVary((float)i/64.0f, (float)j/64.0f, 1.0f, 5))/2000.0f * -1.0f) * 255));
			picArr[3*(i*res + j) + 1] = char(int(((perlinNoise2DVary((float)i/64.0f, (float)j/64.0f, 1.0f, 5))/2000.0f * -1.0f) * 255));
			picArr[3*(i*res + j) + 2] = char(int(((perlinNoise2DVary((float)i/64.0f, (float)j/64.0f, 1.0f, 5))/2000.0f * -1.0f) * 255));
		}
	}
	unsigned int testInt = SOIL_save_image("perlin.bmp", SOIL_SAVE_TYPE_BMP, res, res, 3, &picArr[0]);
	delete[] picArr;
}

The function also appears to return a value between 0.0 and -1000.0.

 

Also, calling the function with just one octave causes the bitmap to be purely black.

Share this post


Link to post
Share on other sites
Advertisement

Anyway, I recently read this quite easy to understand perlin noise tutorial.

I continue to wish that site would die in a fire...

Despite the name, the link doesn't actually describe perlin noise. It's really a form of 'value noise', which is missing a lot of the nice features you get with perlin/simplex noise (especially smooth derivatives).

 

You'd be better off finding an actual perlin/simplex noise implementation.

Share this post


Link to post
Share on other sites

I do have a simplex noise implementation which I grabbed off the internet that looks quite nice, but I was hoping to create my own to better understand what goes on inside the magic box.  Just looking at the implementation I have is a bit overwhelming, though; it's not very well commented and I don't know where to start.  

 

Is there an actual perlin, not value, noise tutorial out there which you'd recommend?  I tried searching for "Perlin noise tutorial" but got some six reworded versions of that same value noise tutorial, all with the same results once I implemented them.  

Share this post


Link to post
Share on other sites

I largely wrote my simplex noise implementation from this: http://code.google.com/p/fractalterraingeneration/wiki/Simplex_Noise

I never bothered with the original perlin noise.

 

There is actually a perlin linked to from that page, but I do not know if it is correct since enver been through it. It talks about and has pictures of gradients, so looks like it might be. http://code.google.com/p/fractalterraingeneration/wiki/Perlin_Noise

Edited by SyncViews

Share this post


Link to post
Share on other sites

I largely wrote my simplex noise implementation from this: http://code.google.com/p/fractalterraingeneration/wiki/Simplex_Noise
http://code.google.com/p/fractalterraingeneration/wiki/Perlin_Noise

Ja, those are some of the simpler explanations of perlina and simplex noise.

If you really want to understand the theory and mindset behind perlin noise, best to go to the source.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!