Generating Digital Worlds Using Perlin Noise
If there’s one great fault with reality, it’s that there is not enough of it. Our solar system and the surrounding galaxy are full of incredible things, but eventually we will run out of things to explore. The universal constants imprison us within a bubble that we won’t ever leave. That being true, it’s all the more incredible that the computer you’re reading this on is able to generate an infinite amount of worlds at a moments notice. How? Using a concept called Perlin noise.
What is Perlin Noise?
Perlin noise is a method of generating sets of random structured numbers. While a normal random number generator will produce outputs that are completely independent from each other — excellent if you’re trying to generate a password or shuffle a deck, there are lots of instances where you want some coherence in the randomness.
Perlin noise does just that — it generates random numbers that follow a smooth gradient. This means that if you sample the generator at two nearby points (say 0.5 and 0.6) you’ll get back two similar results (0.143 and 0.144). These structured random numbers can be used in many applications such as cloud generation, water simulation, and terrain generation.
If we have an algorithm that can generate smooth gradients of random numbers, how do we turn that into a heightmap? Well, take a look at the sample of Perlin noise above — it kind of looks like a mountain range, doesn’t it? There are peaks, valley, and lots of other interesting shapes. If we could somehow generate 2D Perlin noise then we’d be able to use it to make a heightmap.
Luckily most programming languages will let you feed the Perlin noise generator two numbers, an x and a y coordinate, instead of just a single number. Doing this will let you generate 2D Perlin noise (see here). The lighter spots have larger values, think of them being the peaks of the mountains. The darker places are the valleys or rivers, located much closer to a hypothetical sea-level.
While this texture is interesting, it’s still not perfect. Take a look at any real-world heightmap and you’ll see that they look a lot more intricate.
It’s much too complicated to make a heightmap that’s 100% realistic, but we can do a lot better than this. Here are a few methods that can be applied to improve the quality of these heightmaps.
Generating An Island
Islands always look cool. They’re surrounded by water so it’s easy to map them if you only need a small section of a heightmap. They also tend to look more natural since they have a defined structure.
The question now becomes, how do we turn a borderless heightmap into an island? The most obvious solution would be to cut out a circle from the center, but that wouldn’t look very natural. Instead we generate a smooth, circular gradient that masks the height of the island. This produces a relatively natural shape.
The next method for improving your heightmaps is to use a threshold slider. Think of the threshold as the sea-level — as it increases more of the land will be submerged until just the highest peaks remain above the water. We can apply this same idea to terrain generation and it will produce much more interesting results.
Combining the two methods above will allow the generation of a much more interesting and realistic heightmap. It will be an island, it will have interesting shapes, and it will be simply magnificent.
Increasing The Complexity
Now that we have a method for generating interesting heightmaps, what can we do with them? Outlined below are three more methods that can be applied to increase the visual and technical quality of a heightmap.
The heightmaps above look complex, but they’re not pretty. That’s a problem. Even the most hard-core computer programmer needs some pretty in their lives (in fact, they often need more than most).
Let’s transform those ugly greyscale heightmaps into more attractive coloured ones! It’s really not that complicated, just find some colours, in my case I chose to use these nice pastel ones, and select the colour of a pixel not from the Perlin noise but from whatever colour the Perlin noise is closest to.
Ridged noise is precisely what it sounds like: an application of Perlin noise used to generate ridge-like shapes, similar to mountain ranges. In essence it works by taking the value from the Perlin noise and transforming it so that the peaks lie at the threshold between the light and the dark. This can be achieved though the following equation.
new_height = absolute((old_height - 0.5) * 2)
As can be seen from the example below, this new algorithm produces Perlin Noise that looks much more like a mountain range. Using the island generation method outlined above this results in a much sharper and more geometric island.
You won’t want to use ridged noise for everything, in my opinion regular Perlin noise often looks better, but it can be useful for generating mountain ranges or cave systems. It can also be used to generate procedural textures for lightning or other particle effects.
Another method that can be layered on top of regular Perlin noised is warped noise. Warped noise is generated by taking the inputs to the Perlin noise generator and using a separate Perlin noise function to offset them by a random amount.
By this point we’ve moved far past the original goal of island generation. You can try and use this as a heightmap but more practically it could be used to generate procedural textures for liquids or gasses.
As far as 2D Perlin noise goes that’s about all you’ll need to know. There are some more complex algorithms that let one generate different shapes or patterns, but in general most of them operate under the assumption that the noise is being used in three dimensions. Here are the three things I’d suggest looking into if you’re interested in this idea.
- 3D meshes. This is more a prerequisite for the next two suggestions, but bringing your world into the third dimension will make it much more interesting. I’d recommend using either the Unity game engine or the Processing Java IDE. Processing is easier to jump into, but Unity will make it easier for you to create intricate environments down the road.
- Voxel terrain. Ever heard of Minecraft? Yeah — try making your own version. Instead of sampling the Perlin noise in two dimensions try sampling it in three and placing a cube wherever it’s greater than some threshold. It’s not as simple as a basic mesh but it lets you create complex features like caves and overhangs.
- Marching cubes. This algorithm is basically a method of taking voxel terrain and making it look smoother. If you’re interested in this I’d suggest checking out Sebastian Lague’s coding adventure for further context, or feel free to steal my code from Github.
If none of those three ideas piqued your interest then I have one last idea for you. Just create something cool that’s never been done. Say you want to make an algorithm that generates sky islands — go and make it. It’ll be harder to build it on your own but it’ll be infinitely more rewarding in the end. This is procedural generation we’re talking about — there’s literally an infinite number of worlds to be created.
Thanks for reading my article! Feel free to message me on LinkedIn if you have anything to say, or follow me on Medium to get notified when I post another article!