Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Raloth

perlin noise troubles

This topic is 5315 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

I read the article at http://freespace.virgin.net/hugo.elias/models/m_perlin.htm and implemented the pseudocode but things didn''t work quite right. After searching around I found Yann fixing it up a bit and implemented his changes, but it still isn''t the same. My function seems to just output random numbers 0 through 1 (actually a much smaller range, maybe something like .45 to .55). Can anyone spot an error in my code?
float Terrain::Noise(int x,int y,int octave) {
	int n = x + y*52743561 + octave * 73;
	n = (n<<13) ^ n;
	double f = 1.0 - ((n * (n * (n * 15737 + 737281)) + 1376312589) & 0x7fffffff) / 1539152227.0;
	return f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; // clamp to 0,1

}

float Terrain::SmoothNoise(float x,float y,int octave) {
	float corners = (Noise(x-1,y-1,octave) + Noise(x+1,y-1,octave) + Noise(x-1,y+1,octave) + Noise(x+1,y+1,octave)) / 16.0f;
	float sides = (Noise(x-1,y,octave) + Noise(x+1,y,octave) + Noise(x,y-1,octave) + Noise(x,y+1,octave)) / 8.0f;
	float center = Noise(x,y,octave) / 4.0f;
	return corners + sides + center;
}

float Terrain::Interpolate(float a,float b,float x) {
	double f = x;
	return a*(1-f) + b*f;
}

float Terrain::InterpolatedNoise(float x,float y,int octave) {
	int iX = (int)x;
	float fX = x - iX;

	int iY = (int)y;
	float fY = y - iY;

	float v1 = SmoothNoise(iX,iY,octave);
	float v2 = SmoothNoise(iX+1,iY,octave);
	float v3 = SmoothNoise(iX,iY+1,octave);
	float v4 = SmoothNoise(iX+1,iY+1,octave);

	float i1 = Interpolate(v1,v2,fX);
	float i2 = Interpolate(v3,v4,fX);

	return Interpolate(i1,i2,fY);
}

float Terrain::PerlinNoise(float x,float y) {
	float total = 0;
	float persistance = .5f;

	for(int i=0;i<5;i++) {
		int frequency = 1 << i;
		float amplitude = pow(persistance,i);
		total += InterpolatedNoise(x*frequency,y*frequency,i)*amplitude;
	}
	return total < 0.0 ? 0.0 : total > 1.0 ? 1.0 : total;
}

Share this post


Link to post
Share on other sites
Advertisement
I just copied and adapted Perlin''s original code and reorganized a few things to fit my needs. I also implemented his improvements to the algorithm. Both are available here.

Share this post


Link to post
Share on other sites
The problem with that code is I have no idea what''s going on in it. There are no comments and the variable names make no sense at all . I feel bad taking code that I don''t understand.

#define s_curve(t) ( t * t * (3. - 2. * t) )

And what do those .s after the numbers mean?

Share this post


Link to post
Share on other sites
Definitely read perlin''s original paper on the noise function if you can find it. It''s siggraph 85 I think and well worth the read. Elias'' tutorial is great, as is his site, it''s just not really Perlin noise. Perlin noise refers to a specific type of noise which actually looks better than what Elias has (although I bet his is faster).

"Math is hard" -Barbie

Share this post


Link to post
Share on other sites
First,try to use
Noise
instead of
SmoothNoise
to debug.

Second,seems that you should divide by
2147483647.0
instead of
1539152227.0
if you want it to be in 0..1 range.

You should sample your noise in range 0..1,so in test prog you should divide your screen coordinates by resolution(!).

Temporaly remove(comment out)
for(int i=0;i<5;i++)
use "int i=0"
instead.
So it will be much simpler to spot bug.

And also don''t clamp everything,it''s not a good idea for terrain.

Share this post


Link to post
Share on other sites
If this helps here is some code from my planet generation thingy... It still in testing so is a bit messy! but I will add some notes for you...



//

// THIS INTERPOLATES BETWEEN TWO VALUES WITH COSINE FUNCTION

//

float NoiseInterpolate(float a, float b, float x)
{
float ft = (x * 3.1415927f);
float f = (1 - cos(ft))/2;
return (a*(1.0f-f) + (b*f));
}

//

// NOISE GENERATION, PRODUCES VALUE -1.0F TO +1.0F; 2DIMENSIONS

//

float Noise_2D(int x, int y)
{
int n = x + y * GLOBAL_NOISE_SEED;
n = (n<<13) ^ n;

return float( 1.0f - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f);
}

//

// SMOOTH OUT VALUES

//

float SmoothedNoise_2D(int x, int y)
{
float corners = ( Noise_2D(x-1, y-1)+Noise_2D(x+1, y-1)+Noise_2D(x-1, y+1)+Noise_2D(x+1, y+1) ) / 16;

float sides = ( Noise_2D(x-1, y) +Noise_2D(x+1, y) +Noise_2D(x, y-1) +Noise_2D(x, y+1) ) / 8;

float center = Noise_2D(x, y) / 4;

return (corners + sides + center);
}
//

// MAIN INTERPOLATE & SMOOTH

//

float InterpolatedNoise_2D(float x, float y)
{
int integer_X = int(x);
float fractional_X = float(x - integer_X);

int integer_Y = int(y);
float fractional_Y = float(y - integer_Y);

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

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

return NoiseInterpolate(i1 , i2 , fractional_Y);
}

//

// THIS IS CALLED FOR EACH X,Y COORD

//


float PerlinNoise_2D(float x, float y)
{

x = x *2.1f;
y = y *2.1f;

float total = 0.0f;

int n = 8; // Number_Of_Octaves - 1;

float p = 25.5f; // persistence;


float frequency,amplitude;

for(int i=0;i<n;i++)
{

amplitude = 2.7f / (i*i+1.0f);
frequency = p / (i*i*i+1.0f);
total = total + float(InterpolatedNoise_2D((x / frequency),(y / frequency)) * amplitude);

}

if (total<0.0f) total = 0.0f;
if (total>1.0f) total = 1.0f;

return (total);
}


Please remember that this code is realy crap but it was my first test code (but it does work!) I am now using full 3d perlin noise to generate realtime 3d planets!

right call PERLIN NOISE 2D for each x,y coord and thats it!
hope it helps

[Please use [ source ] and [ /source ] tags if you're going to paste a lot of code. Thanks. -Superpig]

[edited by - Superpig on April 13, 2004 5:24:25 AM]

Share this post


Link to post
Share on other sites
p.s GLOBAL_NOISE_SEED is just that a seeded value that determines the outcome of the perlin noise.

I start Global_noise_seed at 57; and then each time multiply it up by its self to produce different results.

Also you may need to change the persistance in the PERLIN_NOISE_2d fuction. I am currently using 0.66f not 25! but what ever works eh!

Share this post


Link to post
Share on other sites
I apologise - right now I don''t have time to look at your code in order to suggest a solution, but here are some links that may help you. I''ve recently finished my own Perlin Noise implementation, and I found the following links easiest to understand:

http://www.robo-murito.net/code/perlin-noise-math-faq.html
http://www.delphi3d.net/download/perlin.zip

The second link is a written in Delphi, though its still easy to see how the code works. It is partly based on the tutorial from the first link.

Hope that helps.

Share this post


Link to post
Share on other sites
Just thought I''de mention that Jame''s Long''s implementation is VERY slow. It makes a great tutorial for learning, but Perlin Noise using the dot-product method is MUCH MUCH FASTER. Especially with the fast bit-wise gradient lookup tricks.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Pragma, do you have to be a member and/or pay to have access to siggraph articles?

Share this post


Link to post
Share on other sites

  • 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!