I’m currently working on prototyping a game project in my personal time that involves a lot of procedural generation and simulated systems. To achieve this, I’ve been investigating voxel world generation would assist me in that goal.
There is a fantastic Godot module out there simply called Voxel Tools for Godot, which provides all the essentials for rendering and managing voxel data in real-time.
Initially while just testing around the module, I was able to create a some basic generation from using he built-in generators within the module and quickly was able to get something up and running.
I started working on prototyping my own custom generator in GDScript. Initially, I created some simple Terrain via a noise map surrounded by a hexagonal wall representing the map edges. This was a good first setup in familiarizing myself with the voxel tooling.
Path generation ended up being a bit more complicated that I initially expected. For starters, I took two points and then just generated flat terrain between them. While this looked very unnatural, it boosted my confidence in my ability to work with the generation system as I wanted.
At this point, I started working with multiple voxel types, which easily gave the world a lot more color, even with my programmer art. This will definitely be something I’ll be tweaking going forward, especially by implementing a system for having unique textures for each face.
Next, I made the paths a little bit more natural by taking the noise value on the borders and smoothing to the center point. I initially didn’t get perfect results as seen below.
But after making a few modifications, I was able to get something pretty nice, at least for terrain that isn’t too steep!
I was very happy with what I was able to achieve here, but the code was starting to get a bit bloated, which led to some performance issues. So with the concept proven, I decided to do some refactoring and getting the system running as a GDExtension.
Practically within the game, it very much resembles the early prototype but with much better performance. Without going into too many specifics, the refactor should allow for a more compartmentalized generation by going through difference layers of generation. The follow-up is to create those layers to start generating a good functional playground for more feature development.