Minecraftian Voxel Engine: 1, Terrain height generation


Introduction

This is the beginning of a little series about Minecraftian Terrain Generation. This means that we have a terrain built from voxels. So, we do not have only a height map but also overhangs, wholes under the terrain shape. We can add and remove these voxels anytime in the game.

If you always wanted to find out more about Minecraftian Terrain Generation, read on :)
I want to share how I came to a working prototype conceptually.

If you can't wait to see how I managed it in Godot 4 check out the next blog posts.
I do not discuss code in the first posts. 

References I heavily rely on for the topic here:

  1. Talk from Henrik Kniberg about terrain generation in Minecraft:
  2. Comprehensive page about noise maps for terrain generation:
    https://www.redblobgames.com/maps/terrain-from-noise/

I do not say that I exactly understood and thus do what is done in the references. I try to explain the version that works best for me. I think it is beneficial to check out the references first before reading on.

Overview

In short, you can say that the terrain is generated from random numbers. The interesting part is how to shape this randomness to something like a naturally looking countryside for instance.

For this we use 2D noise maps and splines. If you want to know more about the nature of such noise maps, the linked video above from reference 1 shows it pretty good. Roughly summarized we can think of it like many added sinus waves with different scale and offsets. This applies to the very popular Simplex Noise function (this is not exact but it is a good imagination to work with).

Continentalness, Erosion and Peaks'n'Valleys

The easiest approach is to use exactly one 2D noise map and directly use the resulting values as height for the terrain. Godot provides such a thing directly by using a plane mesh and applying a noise texture to it. But this is not enough for a minecraftian world where it looks like a real world with continents, mountains, biomes and so on.

So, we add the resulting height values of different 2D noise maps and still don't get what we want. Looks still too generic and wavily. The first important thing to understand for minecraftian terrain is that we can use a spline function. To be able to give the result of the 2D noise map better the shape that we want. And the next is that we link a semantic to our 2D noise map + spline combinations:

  • Continentalness
  • Erosion
  • Peaks and Valleys

See the image taken from reference 1:


I had to think about it several times and check out the video over and over again to form an understanding of it. There are several things encoded here. We can see the three spline functions (the semantic mentioned above). The largest one is the continentalness and the others are named accordingly. The red and green arrows pointing to the splines denote subtraction and addition.

Minecraftian Terrain Height Map

So far, we still have nothing more than a height map but with very nice countryside shape like behaviour:

[x, y] -> 1. 2D noise map -> Continentalness spline function -
[x, y] -> 2. 2D noise map -> Erosion spline function +
[x, y] -> 3. 2D noise map -> Peaks and valleys spline function
-> terrain height for x and y coordinate

Very simple, eh? But wait! All our 2D noise maps still have their default parameters and if you look at FastNoiseLite from Godot 4 there are many parameters to choose from. And indeed, the "hard" point here is not to add or subtract the noise maps with splines but to define a nice set of parameters that results in a terrain that is interesting for exploring because it has a dramatic shape and much interesting details.

Color on the terrain height map: biome(s)

Now that we have the height of the terrain we want to decide what we lay on top of it. Some Earth but also grass, trees and so on. In Minecraft we have it a bit more complex. The type of the biome defines what we choose for each height and humidity (another 2D noise map) combination.

I took the knowledge from reference 2 for one biome and it worked quite well. So, we only have the height from above combined with a humidity map that decides whether we have water (very low), grassland (in the middle for instance) and snowy mountain (on top) for high humidity or scorched alpine-sedge for low humidity. See the image from reference 2 which can be used directly as 2D map for coloring the terrain height map with the height of the terrain on the y-axis and humidity on the x-axis:

If we add another 2D noise map and use it as temperature we get biomes, or so I understand it:


The image is from reference 1 and shows a full set of 2D noise maps with concrete parameters (zoom the page for better readability).

Leave a comment

Log in with itch.io to leave a comment.