Archived

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

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.

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 on other sites
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 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 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 on other sites
First,try to use
Noise
SmoothNoise
to debug.

Second,seems that you should divide by
2147483647.0
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"
So it will be much simpler to spot bug.

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

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

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 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 on other sites
Pragma, do you have to be a member and/or pay to have access to siggraph articles?

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 12
• 14
• 9
• 9
• Forum Statistics

• Total Topics
633349
• Total Posts
3011464
• Who's Online (See full list)

There are no registered users currently online

×