4.5 KiB
📄 Introduction into FastVoxel
Surface generation
Default generator: SimpleSurfaceGenerator
It uses fastnoise-lite to create a heightmap, then fills voxel columns from the bottom up.
Files:
src/generation/generator.rssrc/generation/simple_heightmap.rs
Generation uses traits, so you can plug in whatever mumbo jumbo nonsense you want later: caves, biomes, multiverse, whatever.
Meshing
Multiple meshers exist because one was simply not enough to satisfy my unhealthy obsession with "doing it right this time." [engine development perfectionism disorder. there's no cure.]
CullingMesher– basic visible-face meshingTexturedMesher– UV-aware cube meshing (Minecraft basically)BinaryGreedyMesher– experimental optimization attempt
Files:
src/meshing/mesher.rssrc/meshing/textured_mesher.rssrc/meshing/binary_greedy_mesher.rs
The textured mesher is currently the most practical one because it respects UVs and etc. simply because you can define the material for it. It's not optimized though.
Godot integration
The engine exposes several handy APIs for the editor:
WorldConfig– generation settingsVoxelRegistry– voxel definitions and atlas stuffWorld– main terrain nodeWorldPlugin– editor plugin hooks
Files:
src/editor/world_config.rssrc/editor/voxel_registry.rssrc/editor/world_node.rssrc/editor/world_plugin.rs
Project Structure
src/
├── chunk/ # chunk data, columns, manager
├── editor/ # Godot resources + editor plugin
├── generation/ # terrain generators
├── meshing/ # meshing algorithems
├── rendering/ # mesh to Godot conversion
├── terrain/ # I'm not so sure
└── voxel/ # registry + older voxel logic
Build and Install
Requirements:
- Rust toolchain
- Godot 4 project with GDExtension
- Optional sibling project for
build.shto work.
Build the extension
cargo build --release
Helper script
build.sh builds & copies the extension to:
../minekoloft/addons/fastvoxel/bin/linux
Run with:
./build.sh
If your project is elsewhere, edit the path.
Using It in Godot
Typical use:
- build the Rust extension
- install addon in your Godot project
- create
WorldConfig - create
VoxelRegistry - add
Worldnode - assign config + registry
- generate terrain
- Call the "update with player position" API every frame. Spam it. It returns early and won't yell at you.
WorldConfig
Contains:
- chunk_size
- render_distance
- worker_threads
- seed
- frequency
- terrain_height
Defaults:
- chunk:
32,32,32 - render dist:
8 - threads:
4 - seed:
1234 - freq:
0.03 - terrain height:
6
VoxelRegistry
Each voxel defines:
- type
- atlas size
- tile index per face (top, bottom, left, right, front, back)
Mesher uses this for UVs.
Runtime API
World node provides:
generate_terrain()regenerate_terrain()clear_terrain()update_from_gdscript(player_world_pos)
GDScript example:
@onready var world = $World
@onready var player = $Player
func _ready():
world.generate_terrain()
func _process(_delta):
world.update_from_gdscript(player.global_position)
Engine-Level API Notes
Generation trait
pub trait SurfaceGenerator: Send + Sync {
fn generate(&self, column: &mut ChunkColumn);
fn sample_voxel(&self, pos: Vector3i) -> bool;
}
Mesher trait
pub trait Mesher: Send + Sync {
fn generate_mesh(&self, chunk: &Chunk, mesh: &mut ChunkMesh);
fn generate_mesh_with_registry(
&self,
chunk: &Chunk,
registry: &VoxelRegistry,
mesh: &mut ChunkMesh,
);
fn get_name(&self) -> &str;
}
ChunkManager
Handles:
- chunk lifetime
- generation around player
- unloading distant chunks
- meshing
- sending meshes to renderer
- attaching instances to scene
Basically the project's overworked intern.
Current State
Mid-development, active refactors, might panic on unwrap. Direction is clear though:
- compact chunk storage
- trait-based generation
- modular meshing
- Godot resource workflow
- runtime streaming
Why This Document Exists
Because why not? If you actually wanted to read the code, you wouldn't be here.
Future Work
- finish terrain/world refactor
- more screenshots
- stable API for godot
- multithreaded chunk gen (GOD HELP)
- Better Godot material integration for voxel meshes (so things look less like programmer art).
- fix the greedy meshing
- sample Godot project