re-working the editor nodes

de-coupling godot resources from internal runtime logic
This commit is contained in:
2026-03-28 03:12:31 +03:30
parent 166f9e4aa7
commit d3c1b7bb5b
21 changed files with 393 additions and 235 deletions

View File

@@ -4,22 +4,26 @@
<img src="./logo-cropped.svg" alt="FastVoxel logo" width="180" />
</p>
FastVoxel is a voxel terrain engine for Godot written as a Rust GDExtension. The goal is basically: generate chunks quickly, keep voxel storage lightweight, and build meshes at runtime for blocky worlds with textured materials.
**FastVoxel** is a **Voxel Engine** for Godot written as a Rust GDExtension. The goal is basically: generate chunks quickly, keep voxel storage lightweight, and build meshes at runtime for blocky worlds with textured materials.
This repo contains the engine/plugin side of the project.
This repo contains the engine/GDExtension side of the project.
It's currently being refactored a bit, so some internal structure may change, but the main ideas and APIs are stable enough to explain here.
It's currently being refactored constantly, so some internal structure may change, but the main ideas and APIs are stable enough to explain here. (or Are They?)
## Highlights
- Rust-based Godot 4 GDExtension
- chunked voxel terrain pipeline
- chunked voxel mesh pipeline
- bit-packed voxel storage (solid / air)
- procedural terrain using `fastnoise-lite`
- chunk streaming around the player
- runtime cube meshing with texture atlas support
- Godot editor resources for config + voxel registry
## Soon:
- Multi-Threaded chunk meshing and world generation using a `Work Stealing` Thread pool with divideandconquer parallelism.
## Screenshots
<p align="center">
@@ -63,6 +67,12 @@ Rough pipeline looks like this:
The idea is to keep generation, storage, and meshing fairly modular so different strategies can be swapped in later.
## What FastVoxel "Doesn't" do
1. The engine doesn't use compute shaders or any kind of GPU accelerated meshing algorithem.
2. The engine doesn't bake per-vertex AO on greedy mesher (because it complicates things and I'm running on two brain cells at the moment)
3. The engine doesn't cull the neighboring faces because it has no access to the data of adjacent chunks. (I'm working on it).
## Core Concepts
### Chunked world layout
@@ -73,7 +83,7 @@ Current defaults:
- `CHUNK_SIZE = 32`
- each chunk = `32 × 32 × 32` voxels
- columns stack multiple chunks vertically
- columns stack multiple chunks vertically like a hamburger
- chunk loading/unloading happens around the player based on render distance
Relevant files:
@@ -84,14 +94,18 @@ Relevant files:
### Bit-packed voxel storage
Instead of storing a struct per voxel, chunks store occupancy using packed `u32` blocks.
Instead of storing a struct per voxel, chunks store occupancy using packed `u32` blocks. since a voxel is represented by a single **bit**, a single `u32` can store the state of `32 voxels`.
So right now a voxel is basically:
right now a voxel is basically:
- `0` -> air
- `1` -> solid
This keeps memory usage low and makes lookups very cheap. It works well for early terrain prototypes and simple block worlds.
This keeps memory usage low and makes lookups very cheap.
For a 32 × 32 × 32 chunk, each horizontal row of 32 voxels fits into a single u32. Which means a layer of the chunk requires 32 u32s, and the entire chunk can be stored as a 32 × 32 array of u32s. Each u32 corresponds to one row of voxels along the X axis.
This compact memory layout works well for terrain meshing stage, where the main concern is to quickly check whether voxels are empty or solid. because we use a single bit to represent a voxel instead of a full struct or enum or whatever, the implementation is 32× more memory efficient (no sh- sherlock).
Material differences are currently handled at the meshing/registry layer instead of inside the voxel storage itself.