With the great success of Minecraft behind us now, I have always wondered how they managed to develop a random 3D world. Generating a cube is fairly simple, the difficult part is how they were able to adjust the terrain level. I did a bit of research and I was able to find out that this is called “procedural generation” of a world. Heightmaps can be generated using some noise function like the Perlin noise in a pure mathematical process. Once these heightmaps are generated they are applied to a series of voxel grids or objects.
Also, generating entire worlds at one instance is very processor intensive so many developers subdivide the area into smaller chunks and then generate.
My goal today is to gain a better understanding on how 3D worlds are generated and hopefully apply this to one of my future games.
First we must define what actual basic terrain is. We need to cut our world up into a solid and open areas. Solid areas will be where the actual terrain like grass, dirt and sand are. Open areas will be the air and perhaps the water.
Here is a good noise function to use as a heightmap. Since this is just an image we would be sampling from it is very efficient in terms of data storage. The only problem about this heightmap is that it works well in a 2D game not 3D. Games like Minecraft are volumetric, the have cliffs, caves, tunnels and overhangs. We need a function that operates in 3D space to determine if the terrain is solid or open.
The next major step is to take a function that we can input (x,y,z) that references a single voxel cell in the world and we can apply a noise function to that point. This function could also sample from a noise function and apply it to a voxel cube.
This is a basic heightmap applied to the top of the voxel cube. If we were to take a noise function like this:
And apply it to each side of the cube, we can get:
I haven’t gone too much into the coding aspect of how they are generated since I am am not too familiar with the generation and manipulation of voxels. The general idea is fairly easy to grasp. One can create a bunch of noise samples and apply each to a subdivision of the world to get the desired effect.
Looking at this map of a Minecraft world we can see the different types of terrain and “Biomes” that they have. The developers probably sample different noise functions for different hightmaps of different types of biomes that they want to generate. As for the rarity of gold/diamonds/iron under the terrain, they most likely use another noise function that affects lower subdivisions and places them over their respective terrain.
For example: Diamonds would only spawn once the player is at a low enough elevation and they normally spawn near lava. To do this I would have different noise functions for different elevations and areas using some nested “if” and “else” statement. If everything was completely random we would be having desserts appearing underground. So by having set elevations for different biomes the game is a bit more realistic and it creates a better player experience.
I was able to find a good noise generating open source software for C++ online called libnoise that would be great for a project like this. It even has a few tutorials that help you create terrain .bmp files for heightmaps and what not.
Next week I will talk about the 2D level generation of Terraria.
Thank you for reading