Carving voxels

three.js r160 · zero assets · one file

Voxelcraft

An entire island of grass, stone and water, built from nothing but coloured cubes. Every world is one seeded number, every face that can't be seen is thrown away, and the whole terrain ships as a single draw call. Drag to look around. Roll the dice for somewhere new.

How it works ↓
dragorbit scrollzoom Rnew seed Tday cycle Hhide interface
fps—
tris—
calls—
seed
time

The engine

A quarter million cubes, drawn like one.

Naive voxel rendering issues one draw call per block and dies at a few hundred. Voxelcraft instead walks the grid once, keeps only the faces another block can't hide, bakes ambient occlusion straight into the vertex colours, and hands the GPU a single buffer.

01

Invisible faces never ship

A face is emitted only when the neighbouring cell is air. Interior blocks cost nothing — grass under grass is never uploaded. Terrain blocks per island vary with the seed, but the triangle count stays in the tens of thousands, not millions.

02

Shadows you can buy cheaply

No SSAO pass, no post-processing chain. Corner darkening is measured from neighbour occupancy while the mesh is built and multiplied into the vertex colour, so it costs nothing after the world exists. The frame budget is watched too: two bad seconds lower the render scale, two more give up shadows. It degrades before it stutters.

03

Frames, not luck

Clouds are a single instanced mesh, stars and motes are point clouds, and nothing allocates inside the frame loop. ~93 k triangles and 10 draw calls is the whole page, which leaves the 16 ms budget alone.

Worlds

Every island is a number.

Continents come from five octaves of value noise; the mountain mask is a second field that only bites where the base already rose, and the whole thing is multiplied by an island falloff so the coast always drops into the sea. The same seed builds the same mountains on every machine, in every browser — which is why the seed sits in the address bar, ready to send to someone.

Altitude decides the palette: sand at the tide line, grass on the gentle slopes, bare stone where the cliff is too steep to hold soil, snow above the line. Trees and boulders are placed by the same stream of deterministic noise, then merged into the very same geometry as the ground beneath them.

// one pass over the grid — hide what is shared
for (const f of FACES) {
  if (solid(x + f.n[0], y + f.n[1], z + f.n[2])) continue;
  for (let c = 0; c < 4; c++) {
    const s1 = solid(base + sideA), s2 = solid(base + sideB);
    ao = (s1 && s2) ? 0 : 3 - (s1 + s2 + corner);
    pushColour(albedo * JITTER * AO_TABLE[ao]);
  }
}
// 128 × 128 × 44 grid → 1 geometry, 1 draw call

This world, right now

Live numbers from the running scene.

Voxel grid
128 × 128 × 44
Solid blocks
—
Visible faces
—
Triangles
—
Draw calls
—
Assets
0 files