Perlin noise is amazing

Disclamer

This is my take on Perlin noise. There are already tons of tutorials about Perlin noise on the web. There was probably no need for another one. The only reason that one exists, is that I was playing with it in javascript and HTML5/canvas, and had all the code ready. I just thought it would be cool to write a tutorial where each sample image is actually generated on the fly and painted on the page. So hint: refresh the page and you will see a different image. But each picture on that page is consistent in the entire tutorial. I thought that was pretty cool. So sorry if it takes some time to load. And if you never see images on this page, maybe it is time to upgrade your browser to a real one, like Chrome or Firefox. Now that we got that out of the way, let’s got to the cool stuff.

Perlin noise

Perlin noise amazes me. Here is what it looks like in 2D.

Imagine that the above image is representing a map. Maybe the darker area are mountains, and the lighter are valleys.

It may seem relatively hard to generate such image randomly. Fortunately, some guy, Ken Perlin, developed a cool technique that does just that. He even won an academy award for it…

The technique can be applied to generate 1D Perlin noise, to generate a random-looking profile for example. Or to generate 3D Perlin noise, to add some volume information, like a bunch of clouds. In that example, we will work with 2D perlin noise. Maybe even 4D noise, but I will let you imagine what that would look like…

The technique is pretty simple. Basically, it is an average of few random images of different sizes.

Step by step

The algorithm starts with a simple random image. Each pixel has a random value between 0 (black) and 1 (white). In this tutorial, I want to generate an image of 256 pixels wide. Here is the first random image:

Not very nice yet.

Let’s generate another one, that is half the size, so 2562 = 128 pixels.

We need to add this second image to the first one. But since they are not of the same size, we have to take the smaller one, and scale it up by a factor of 2 to get an image of 256 pixels:

Now, the magic happens. We just take each pixel of those two 256 pixels wide images, average them, and save the result to a new image:

Tadaaaa!

Not very impressive. Yet.

Now, the second step is repeated with an image half the size again. We started with 256 pixels, then 128. Now, let’s take a 64 pixels image, and resize it to 4 times its size:

And we add it to our previous image:

Wash, rinse, repeat

These operations are repeated for images of 32, 16, and 8 pixels: generate random image, resize, add to (or rather average with) the last obtained image:

WOOOOWW !

The algorithm, visualized

The following image has 3 columns: the first one is a randomly generated image. The second one is the same image as the first column, but scaled to be of the same size as our target image (256 pixels, red lines). The third and last column contains average images between the image above itself, and the image to its left (blue lines). The algorithm starts with a randomly generated image (in the top right corner, and images are added together.

There are a lot of parameters to play with. For example in that example we started with an image of size 256. But we could start with a 64 pixels image resized to 256 pixels (basically skip the first 2 images). That would remove some of the fine grain to the final image. We can also add one or 2 extra steps at the end. Basically, up to a 2x2 pixels image (1x1 does not make any sense, since it would add the same value to every pixel of the image).

Another important factor is how an image is scaled up. In the above examples I used linear scaling, but other techniques will produce different results.

It is also possible to change the way two images are added together, in which order, and what formula is used. Here, much more importance is given to the last image I add, since it basically accounts for half the value of each pixels on the result. This can be tuned as well.

Colors ! It is very easy to apply a color map to this black and white map, and get completely different textures, like lava, ocean, dirt, wood, etc.

Different parameters will work better for different applications.

In a next article, I’ll play with colors, and explain how to generate Perlin noise to infinity, in a way that doesn’t require computing an initial noise the size of… infinity (which is how this whole tutorial thing actually started)

The Old Goat's 50 miler » « Inkscape Pattern Along Path