Files
fastvoxel/README.md
2026-04-14 21:20:36 +03:30

133 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FastVoxel
<p align="center">
<img src="./logo-cropped.svg" alt="FastVoxel logo" width="180" />
</p>
**FastVoxel** is a voxel engine for Godot written in Rust using GDExtension.
Main goals are:
- Generate chunks fast enough (It's already faster than minecraft, but not because of my good code, it's actually minecraft's fault)
- store voxels using almost no memory (because RAM prices blah blah blah.. and also I enjoy suffering so why not spend 1k hours optimizing this thing?),
- and build meshes at runtime for blocky worlds with textured materials.
This repo contains the engine side of the project.
Yes, things are constantly being refactored.
And yes, I still have no idea what I'm doing, so take that for granted and pray to the compiler.
## Highlights
- Rust-based Godot 4 GDExtension
- Chunked voxel mesh pipeline
- Bit-packed voxel storage (solid/air, liquid, whatever)
- Procedural terrain via `fastnoise-lite`
- Chunk streaming around the player
- Runtime cube meshing with texture atlas support (up to 1024x1024)
- Godot editor resources for config + voxel registry
## Soon
- Multi-threaded chunk meshing & generation using a **work stealing** thread pool with divideandconquer parallelism.
(Some C dev just segfaulted reading that.)
## Screenshots
<p align="center">
<img src="docs/screenshots/colors.png" width="960" />
</p>
<p align="center">
<img src="docs/screenshots/heightmap-noise.png" width="960" />
</p>
<p align="center">
<img src="docs/screenshots/normal-map.png" width="960" />
</p>
The repo mostly contains branding assets. More gameplay screenshots coming soon, assuming I stop rewriting the engine every Tuesday.
To add your own: put them in
```
docs/screenshots
```
then embed with
```
![image](docs/screenshots/my_face.png)
```
## What FastVoxel Actually Does
The engine generates a voxel world using chunk columns.
The suspiciouslysimple pipeline:
1. `SurfaceGenerator` decides if a voxel is solid.
2. `ChunkColumn` stacks chunks vertically.
3. Each `Chunk` stores voxels in bitpacked `u32`s.
4. `Mesher` converts only the exposed voxel faces into triangles.
5. `Renderer` throws those triangles into Godot's scene tree.
6. The world updates chunks as the player moves around.
Everything is modular because future "me", will absolutely regret today's design decisions and might decide to get back into the cave and rewrite the engine again.
## What FastVoxel _Doesn't_ Do (Yet)
1. No compute shaders or GPU meshing. This is an OS-Thread party.
2. No pervertex AO on the greedy mesher.
(Because it's complicated and my last functioning brain cell is currently writing this.)
3. Doesn't cull neighboring chunk faces yet because chunks don't talk to each other.
(They're socially anxious.)
## Core Concepts
### Chunked world layout
Terrain = columns of chunks.
Defaults:
- chunk size: `32 × 32 × 32`
- chunks load/unload based on render distance (default: 8)
Relevant files:
- `src/chunk/chunk.rs`
- `src/chunk/column.rs`
- `src/chunk/chunk_manager.rs`
### Bit-packed voxel storage
Instead of storing a big struct per voxel, we cram voxels into `u32`s.
Each voxel = **1 bit**:
- `0` => air
- `1` => solid
A single `u32` stores 32 voxels (very memory-friendly).
A 32×32×32 chunk:
- each row (32 voxels) = `u32`
- each layer = 32 rows = 32 `u32`s
- whole chunk = 32 × 32 = **1024 `u32`s**
This layout is amazing for meshing because checking solid/air is basically:
```
bit = (row >> x) & 1
```
Since we use 1 bit instead of a whole struct, one could argu the memory usage is ~32× lower.
Important, because RAM now costs $800 for 16 GB. that's like fifty bucks per gigabyte, and I'm not emotionally prepared for that.
Materials are handled at the meshing/registry layer, not in voxel storage.
## License
MIT License. Do whatever, just don't blame me.