Let’s make some noise!

I was always fascinated by games, and the problems game developers solve on a daily basis. One of the most interesting topics for me was procedural terrain generation. The idea of building a massive world purely described by algorithm looked very intriguing.

A couple of months ago I decided to get my head around it and understand how it’s done from the ground up. It turned out to be quite an interesting journey and I ended up giving a talk about it during one of our regular tech lunches at carwow. Several people asked if I’d write it up as a blog post, so here it is!

What is noise?

First of all, when I mention noise, I mean a function that receives a pair of coordinates and returns a floating-point value, usually between 0 and 1. In the image below, the elevation graph simply shows the change of noise output from 0 to 1, while the image graph uses grayscale for the same purpose with black and white representing 0 and 1 respectively. To generate regular noise, we just need to select a random value for each point. You can see the results of this in the first image below. But for our case of procedural generation, it’s too random.

Enter Perlin noise

So what exactly is Perlin noise? How is it different from regular noise?

Perlin noise is a type of gradient noise developed by Ken Perlin in 1983 as a result of his frustration with the “machine-like” look of computer graphics at the time.

You can see in the second example below that there is still ‘randomness’ to the image, but the gradients smooth out the differences.

Comparison of regular (on the left) and Perlin noise (on the right)

The pseudorandom nature of Perlin noise made it instantly useful and popular in the film and game CGI industries. Its development has allowed computer graphics artists to better represent the complexity of natural phenomena in visual effects and simulate fire, clouds, smoke, and even stains and rust.

But one of its many uses has been generating procedural terrains, and today I’ll show you how to do just that.

Generating terrain

In this interactive example, you can see that we have full control over some of the noise properties. The examples below make use of the noise.js JavaScript library, and you can find the full source code in my repo.

This is a good start, but too simplistic. In order to generate terrain, we need to combine multiple noises of different amplitudes and frequencies to simulate different terrain features.

For instance, low-frequency high-amplitude noise could be used for simulating mountains, mid-frequency mid-amplitude noise to simulate hills and high-frequency low-amplitude noise for minor features like bumps.

Perlin noises of different frequency and amplitude

If we overlay these three noises we get something that looks a bit more like a terrain.

At this point, a good idea would be to automate the process. Let’s introduce a couple of properties that would control how noise layers are generated.

Octaves — Defines a number of noise layers used by the generator

Persistence — Defines how amplitude is changing between each noise layer

Lacunarity — Defines how frequency is changing between each noise layer

If we create a noise generator that uses these properties to combine different noise layers we get a much more realistic effect:

We can also make the effect more or less extreme. Here, instead of just outputting the value, I’m raising it to the power of three first. That way I can create a larger difference between the high and the low ground.

Adding some colour

Now, if we want to make the output of our generator to look more like a terrain, we need to introduce some colours. As I already mentioned our noise generator just outputs the floating-point value for each pixel. Let’s map the output to colours.

Let’s say that everything below 0.05 would be water, between 0.058 and 0.175 would be a layer of sand, grassland would be between 0.175 and 0.5 and so on.

After performing the mapping we get a pretty good looking result.

Going 3D

Having a 2d map is nice, but how cool would be to create an actual 3d terrain using our generator? Turns out it’s relatively easy.

Let’s start by building a high resolution plane (the following examples are built using THREE.js library).

Then if we raise each vertical according to the output of our terrain generator, we can create some elevation.

Finally, let's use the texture we got when we mapped the colours to elevation value.

Nice! But I don’t really like my new neighbours. Can I turn it into an uninhabited island? Turns out, it wasn’t a hard puzzle to crack. By simply modifying the elevation value depending on how far this point is from the centre of the terrain, I got that:

I’ve decided to go even further and scattered some trees and added a few clouds (which, of course, were also generated using Perlin noise) 😃

In my opinion, that was an interesting experiment and I’m quite happy with the results! If you are looking for more details or the source code please check out my git repository: https://github.com/mightykho/noise

While you’re here: carwow is hiring developers and engineering managers. Interested? Check out our available roles 🙇

--

--