C++ School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become a C++ Expert!

Join 307,004 C++ Programmers for FREE! Get instant access to thousands of C++ experts, tutorials, code snippets, and more! There are 1,974 people online right now. Registration is fast and FREE... Join Now!




Perlin Noise

 
Reply to this topicStart new topic

> Perlin Noise, A simple explanation on Perlin Noise.

Pontus
Group Icon



post 6 Oct, 2008 - 12:20 PM
Post #1


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.

IPB Image

This is coherent noise

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

IPB Image

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

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

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

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

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
CODE

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.

CODE

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.

CODE

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.

CODE

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.
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

Deepglue555
Group Icon



post 18 May, 2009 - 12:38 AM
Post #2
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?)
Go to the top of the page
+Quote Post

Pontus
Group Icon



post 18 May, 2009 - 06:52 AM
Post #3
I don't know anything of guitars. I think you'd be better of at a music forum. tongue.gif
Go to the top of the page
+Quote Post


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/21/09 06:52AM

Live C++ Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

C++ Tutorials

Reference Sheets

C++ Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month