Voxels and units
The voxel size and the fixed storage hierarchy of chunks, blocks and bricks; how chunks compress; voxel types, materials and the six faces each voxel carries; and the heightfield patterns that give surfaces their relief.
The voxel size
core/Units.hpp. The edge of one voxel is a runtime setting, 1/64 m by default (LostVale’s microvoxels, about 1.5 cm):
rv::setVoxelSize(1.0f / 16.0f); // before creating worlds, streamers, physics or renderers
rv::voxelSize(); // metres per voxel
rv::blockSize(); // a block: 64 voxels
rv::chunkSize(); // a chunk: 1,024 voxels
The range is 1/4096 m to 16 m: 1/64 m for microvoxel worlds, 1/16 m for chunkier sculpting, 1 m for block worlds, 1/256 m for tabletop dioramas. AppConfig::voxelSize sets it for you at start-up. Values out of range throw std::invalid_argument, and setVoxelSize returns the previous scale.
Set it once, before anything is built at a scale. Everything that turns voxel coordinates into metres reads it: meshing bounds and cluster padding, physics colliders, streaming rings, the renderer’s volumes and the shaders (FrameUBO::units, MICRO in common.glsl). Changing it while worlds, streamers or renderers built at another scale are alive leaves them inconsistent; between worlds, call Renderer::resetWorld first. Heightfield relief reaches at most a brick out of a face at any scale.
The storage hierarchy
The hierarchy is fixed, so changing the voxel size scales blocks and chunks with it:
| Level | Holds | At 1/64 m |
|---|---|---|
| Voxel | one VoxelId |
1.56 cm |
| Brick | 8³ voxels | 12.5 cm |
| Block | 8³ bricks = 64³ voxels | 1 m |
| Chunk | 16³ blocks = 1,024³ voxels | 16 m |
Sparse, hierarchical chunks
voxel/Chunk.hpp stores a chunk sparsely:
- a chunk is 16³ block entries;
- a block is either uniform (one
VoxelIdfills all 64³ voxels) or a table of 8³ brick entries; - a brick is either uniform (one
VoxelIdfor its 512 voxels) or a detail brick, palette-compressed at 1, 2, 4, 8 or 16 bits a voxel.
Each entry is a u32: with bit 31 clear, the low 16 bits are a uniform VoxelId; with it set, the low 31 bits index the next level. Air, solid rock and the inside of anything big collapse to a single id, so storage follows the surface, not the volume.
Voxel types and the palette
A VoxelId (a u16; 0 is always air) indexes the global VoxelPalette. Each entry is a voxel type: a material plus six face parameter sets, one for each face direction. intern(type) (or intern(material, faceParams)) returns the id of an identical type if there is one, so voxel types are deduplicated across the whole world.
Face parameters
Every face carries:
| Parameter | Range | Meaning |
|---|---|---|
pattern |
name | the heightfield and surface pattern (below) |
amplitude |
0 to 255 | displacement; 255 is 12.5 cm at the default scale |
frequency |
0 to 255 | spatial frequency: 0.5 × 2f/32 cycles a metre |
seed |
0 to 255 | pattern decorrelation |
tint |
RGB 0 to 255 | multiplies the albedo; 128 is 1.0 |
roughness |
0 to 255 | multiplies the material’s roughness; about 160 is 1.0 |
emissive |
0 to 255 | emissive boost |
wetness |
0 to 255 | darkens and sharpens |
sheen |
0 to 255 | back-lit translucency |
seam |
0 to 255 | strength of the emissive seam round merged tiles; 128 is the material’s default |
Materials
voxel/Material.hpp. A material carries albedo, roughness, subsurface, emission, a seam colour and strength, flags, and default face parameters. Material 0 is air and is registered automatically.
| Flag | Meaning |
|---|---|
opaque |
blocks light and sight |
water |
drawn by the water pass |
foliage |
sways in the wind, back-lit translucency |
emissive |
glows |
collidable |
physics collides with it |
dressed |
built by hand and laid true (walls, roofs, floors, paths): turned or pitched faces shade smooth |
glass |
solid to the touch (collides, holds up a roof, encloses a room) but drawn by the glass pass, letting light and sight through; its albedo is the light one pane lets through, its seam colour the lead of its cames |
A material may also grow grass: blades on its up-facing faces in the grass pass, with height, density, width, stiffness, root and tip colours and a share of flowers.
Heightfield patterns
Faces are not flat. On the GPU each face is tessellated and displaced by a procedural heightfield evaluated in world space, so neighbouring faces with the same parameters join seamlessly, and the displacement fades to zero at quad edges so neighbours never crack. The patterns:
- General: flat, grain, strata, cells, bark, blades, ripples, pebbles, leafy.
- Rocks and minerals modelled on real ones: granite (feldspar phenocrysts, quartz, biotite flecks, sheet joints), chalk (with bands of flint nodules), Carboniferous limestone (bedding planes, clints and grykes, crinoid ossicles), slate (cleavage laminae with stepped edges), sandstone (cross-bedded laminae), basalt (columnar joints, vesicles), schist (crenulated foliation with mica sheen), gneiss (banding), mudstone, quartzite, gritstone.
- Ground: peat, clay (with desiccation cracks), shingle, dune sand (wind ripples), loam, turf, moss cushions, heather.
- Bark: oak, beech, birch, pine and ash.
- Leaves and flowers: lobed, oval, serrate, needle, pinnate, spiny, hawthorn, rowan, bracken, gorse, scale, pad and strap leaves, petals, blossom, berries and fungus caps. These are not noise: each grows individual leaves on the face from equations.
- Built finishes: lime render, roof tiles, roof slates, shingles and thatch, laid in courses down the slope of the surface (
frequencysets the courses per metre); glazing patterns for glass (quarries, leadwork, roundels, mosaic).
Bounded worlds
voxel/VoxelWorld.hpp is a bounded world of chunks on a dense grid. It lives as an ECS resource; per-chunk runtime state (meshes, physics bodies, dirty flags) lives on chunk entities that refer to grid cells by ChunkCoord. Most games use it through VoxelScene.
Written from the engine's headers and source as of commit 02e81b2 (2026-11-01).