Page 1 of 1

Perlin Noise A simple explanation on Perlin Noise. Rate Topic: -----

#1 Pontus  Icon User is offline

  • Cattlebruiser

Reputation: 17
  • View blog
  • Posts: 612
  • Joined: 28-December 06

Post icon  Posted 06 October 2008 - 01:20 PM

Hi there, guys

I'm here to teach you something about Perlin Noise. You know, that magical thing that gives infinite possibilties and is usefull in every single game.

To be honest with you, it's not that very difficult, but it can be if it's not explained right.

First, the theoratical side:

Now, what exactly is perlin noise? Well, it is some pseudo random coherent noise. Let me explain that bit by bit:
*Pseudo random: This means that it appears random, but you get the same result twice every time you call it. Think of the rand() function. You might have
noticed that if you not seed it it always will give number 13 as first. If it was to be fully random you would get a different number everytime.

*Coherent: This means that it is very smooth. Here's a picture of some non-coherent noise.

Posted Image

This is coherent noise

Posted Image

Imagine that you zoom in on that non-coherent noise, and as you zoom in, you see that there are transitions between those pixels, and there you go,
coherent noise!

Posted Image

But that contrast is a bit high, don't you, let's smooth it out a bit:

Posted Image

There we go, looks much better, doesn't it?

But if you want to use it as a heightmap, it will be a bit too smooth, don't you think? Well, let me show you how to improve that by using octaves.
Maybe this image will help explain:

Posted Image

So, the smoothed noise is image a. If We zoom out on that noise, we get image b, and if we zoom out on b, u get image c. If u add a,b,c,... U get this:

Posted Image

And this is what we are going for.

Now, lets take that what we have learned and bring it in the practical side.

First of all, we'll need a pseudo-random number generator:

I searched a bit on the web and I came across this one:

1D
inline double findnoise(double x)
{			 
 int x = (x<<13) ^ x;
 return (double)( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & Ox7fffffff) / 1073741824.0);	
}



Here's the 2D version
inline double findnoise2(double x,double y)
{
 int n=(int)x+(int)y*57;
 n=(n<<13)^n;
 int nn=(n*(n*n*60493+19990303)+1376312589)&0x7fffffff;
 return 1.0-((double)nn/1073741824.0);
}



Don't ask me how it works because I dont know how it works myself, something with prime numbers... But what I do know is that it returns a value between
-1 and 1, just like our perlin noise function.

Now, as I've explained before, we get coherent noise because we look between the pixels, so our perlin noise function must be able to accept
double numbers. So we have to interpolate between the pixels. Interpolate is like taking the average, but a little bit more complicated. We'll be using
cosine interpoliation. It gives a very nice effect because it looks like a curve. But I wont explain too much, that's maybe for another tutorial.
Here is it.

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



Now you might ask: "Hey, what about the 2D version?". Well, let me explain this. Let's take the average of a and b and call it d.
Let's also take c and d and call it e. And if we take the average of d and e it would equal to the average of a b c and d.
This enables us to stick to 1 dimension, making the code alot easier. Now, I'll combine these into one function. It uses SDL for image handling.

double noise(double x,double y)
{
 double floorx=(double)((int)x);//This is kinda a cheap way to floor a double integer.
 double floory=(double)((int)y);
 double s,t,u,v;//Integer declaration
 s=findnoise2(floorx,floory); 
 t=findnoise2(floorx+1,floory);
 u=findnoise2(floorx,floory+1);//Get the surrounding pixels to calculate the transition.
 v=findnoise2(floorx+1,floory+1);
 double int1=interpolate1(s,t,x-floorx);//Interpolate between the values.
 double int2=interpolate1(u,v,x-floorx);//Here we use x-floorx, to get 1st dimension. Don't mind the x-floorx thingie, it's part of the cosine formula.
 return interpolate1(int1,int2,y-floory);//Here we use y-floory, to get the 2nd dimension.
}



And there we are, a perlin noise function. It returns a value between -1 and 1. To convert this to a 0-256 RGB value, we simple multiply it by 128,
then add 128 to it. But in the theory section I mentioned something about octaves, well I'll show it now. I call this result clouds.

SDL_Surface *Render_Clouds(int w,int h,double zoom,double p, int r, int g, int b)//w and h speak for themselves, zoom wel zoom in and out on it, I usually
{//										   use 75. P stands for persistence, this controls the roughness of the picture, i use 1/2
 int octaves=2;
 SDL_Surface *ret=SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,24,0,0,0,0);//Create an empty image.
 for(int y=0;y<h;y++)
 {//Loops to loop trough all the pixels
  for(int x=0;x<w;x++)
  {
   double getnoise =0;
   for(int a=0;a<octaves-1;a++)//This loops trough the octaves.
   {
	double frequency = pow(2,a);//This increases the frequency with every loop of the octave.
	double amplitude = pow(p,a);//This decreases the amplitude with every loop of the octave.
	getnoise += noise2(((double)x)*frequency/zoom,((double)y)/zoom*frequency)*amplitude;//This uses our perlin noise functions. It calculates all our zoom and frequency and amplitude
   }//											It gives a decimal value, you know, between the pixels. Like 4.2 or 5.1
   int color= (int)((getnoise*128.0)+128.0);//Convert to 0-256 values.
   if(color>255)
	color=255;
   if(color<0)
	color=0;
   SetPixel(ret,x,y,(int)((r/255.0)*(double)color),(int)((g/255.0)*(double)color),(int)((b/255.0)*(double)color));//This colours the image with the RGB values 
  }//														   given at the beginning in the function.
 }
 return ret;
}



And this gives some nice clouds. I hope you enjoyed this tutorial, and I there's enough request, I'll make a more in-depth sequel.

Is This A Good Question/Topic? 1
  • +

Replies To: Perlin Noise

#2 Deepglue555  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 6
  • View blog
  • Posts: 110
  • Joined: 13-April 09

Posted 18 May 2009 - 01:38 AM

how might i generate Guitar Tube Amplifier hiss/hum or change a transistor amp to sound like a Tube Amplifier for Guitar or better Stereo/Mp3 player lol
(am i asking too much?)
Was This Post Helpful? 0
  • +
  • -

#3 Pontus  Icon User is offline

  • Cattlebruiser

Reputation: 17
  • View blog
  • Posts: 612
  • Joined: 28-December 06

Posted 18 May 2009 - 07:52 AM

I don't know anything of guitars. I think you'd be better of at a music forum. :P
Was This Post Helpful? 0
  • +
  • -

#4 Guest_Maito*


Reputation:

Posted 21 February 2010 - 06:29 PM

Hi.

I really like your tutorial, but I don't understand one thing of the code.
You tell us about the setPixel function but when I try to use it, compilers throws a message saying this function doesn't exists.
What is the problem with this? What function is it? Do I have to write the code of setPixel instead?

Sorry for my bad english and thanks in advance.
Was This Post Helpful? 0

#5 Guest_pontus*


Reputation:

Posted 22 February 2010 - 09:20 AM

Yes, you have to make one yourself. It's a function that sets a given color on a given pixel in the image. As It's a tutorial on just the perlin noise not all the basic functions are made.
Was This Post Helpful? 0

#6 doveraudio  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 18
  • Joined: 17-March 10

Posted 17 March 2010 - 05:03 PM

thanks so much for this blurb. converted the interpolate function into a synthedit module, wondering if you'd mind if i share it with people. hoping for permission to credit you in the "liner notes"

(also hoping to use the rest of the code too - the interpolate bit really helped this stuff click)
		ft=input1 * 3.1415927;
		f=(1.0-cos(ft))*0.5;
		float result = input2*(1.0-f)+input3*f;


hoping you make more tutorials, thanks for the function on too btw. cheers.
Was This Post Helpful? 0
  • +
  • -

#7 Pontus  Icon User is offline

  • Cattlebruiser

Reputation: 17
  • View blog
  • Posts: 612
  • Joined: 28-December 06

Posted 18 March 2010 - 08:44 AM

View Postdoveraudio, on 18 March 2010 - 12:03 AM, said:

thanks so much for this blurb. converted the interpolate function into a synthedit module, wondering if you'd mind if i share it with people. hoping for permission to credit you in the "liner notes"

(also hoping to use the rest of the code too - the interpolate bit really helped this stuff click)
		ft=input1 * 3.1415927;
		f=(1.0-cos(ft))*0.5;
		float result = input2*(1.0-f)+input3*f;


hoping you make more tutorials, thanks for the function on too btw. cheers.


You can spread this tutorial and the code as much as you like. Just include a link to this original topic.
Was This Post Helpful? 0
  • +
  • -

#8 doveraudio  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 18
  • Joined: 17-March 10

Posted 20 March 2010 - 08:23 PM

View PostPontus, on 18 March 2010 - 07:44 AM, said:

View Postdoveraudio, on 18 March 2010 - 12:03 AM, said:

thanks so much for this blurb. converted the interpolate function into a synthedit module, wondering if you'd mind if i share it with people. hoping for permission to credit you in the "liner notes"

(also hoping to use the rest of the code too - the interpolate bit really helped this stuff click)
		ft=input1 * 3.1415927;
		f=(1.0-cos(ft))*0.5;
		float result = input2*(1.0-f)+input3*f;


hoping you make more tutorials, thanks for the function on too btw. cheers.


You can spread this tutorial and the code as much as you like. Just include a link to this original topic.


cool 8)
Was This Post Helpful? 0
  • +
  • -

#9 doveraudio  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 18
  • Joined: 17-March 10

Posted 20 March 2010 - 08:44 PM

View PostDeepglue555, on 18 May 2009 - 12:38 AM, said:

how might i generate Guitar Tube Amplifier hiss/hum or change a transistor amp to sound like a Tube Amplifier for Guitar or better Stereo/Mp3 player lol
(am i asking too much?)


word. come over to http://www.kvraudio.com/.

if you're into coding, i could use some help at dovergadget on sourceforge. i use the synthedit sdk 2, i could email u a copy as it's no longer online.

By creating synthedit modules i get to work more with dsp ideas and less rhetorical stuff. not that i'm very good at this stuff yet at all.

This post has been edited by doveraudio: 20 March 2010 - 08:50 PM

Was This Post Helpful? 0
  • +
  • -

#10 iko79  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 24-April 12

Posted 24 April 2012 - 05:51 AM

You've got multiple used symbols in your explaination of bilinear interpolation.

View PostPontus, on 06 October 2008 - 01:20 PM, said:

Let's take the average of a and b and call it d.

Let's not, because it is already occupied by the fourth pixel in a, b, c, d. :)

Also, there is a typo in the code: you call "interpolate1" which is undefined.

Anyway, thanks for the code, you really saved me some time!

Cheers,
iko
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1