Digging into Enshrouded

Embervale, voxel by voxel

The world of Enshrouded is not painted on a surface. Every hill, cave and wall is built from half-metre blocks that you can dig, carve and build with. After watching a recent video from the developers about the performance work for 1.0, I got curious about how all of this works and started reading the files, purely for educational purposes. This page is my attempt to understand how the game stores billions of those blocks, starting with the simple idea and a question like “where is the biggest iron deposit?”, and ending with the bytes on disk, as far as I managed to read them.

Why it matters

A world you can take apart

Enshrouded drops you into Embervale, a hand-made world about 10 by 10 kilometres. You can swing a pickaxe at almost anything: dig into a mountain, tunnel under a river, flatten a hill for your base, or stumble into a cave that nobody marked on a map. What you dig out is real. It goes into your bag as dirt, stone or ore, and the hole stays there for a while.

That's rare. Many open-world games build their ground as a heightmap: one height for every spot, like a tablecloth draped over a table. A tablecloth can't have a cave under it or a ledge sticking out over it, and you can't cut a piece out. Caves and cliffs in those games are often separate 3D models placed on top of the sheet.

Enshrouded fills the whole volume instead. From what I could see in its files, the world is cut into small cubes called voxels (short for volume pixels), each half a metre wide, and every one of them knows what it is made of. Mountains, caves, ore veins, buried ruins and the buildings you place are all made of the same stuff.

Loading the 3D view…
The same little hill two ways. A heightmap mesh is a thin sheet with nothing under it. Voxels are solid blocks all the way down, so you can dig into them.
Many gamesHeightmap terrain
  • One height per spot on the map
  • No caves or overhangs in the ground itself
  • The ground can't be dug
EnshroudedVoxel terrain
  • A material for every half-metre cube
  • Caves, overhangs and buried rooms are part of the ground
  • Dig and build almost anywhere
The idea

Five steps in a tiny world

A made-up patch of ground 8 m across, built the way I believe Enshrouded builds Embervale. It plays on its own; pick a step to jump to it, or drag to look around.

Loading the 3D view…
    Simplified example, not real game data.
    The scale

    Why the cubes have to be packed

    10.24 × 10.24 kmmap size
    2.65 kmfrom the world floor to the top
    0.5 msize of one cube
    ≈ 2.2 trillioncubes in total

    Stored one by one at 2 bytes each, that would be about 4.4 terabytes, far too much to download or keep in memory. As far as I can tell, the trick from step 5 does most of the work: most of the world is deep rock or open sky, and a brick of either costs only a few bits. The rest of this page shows how I think that works, with real data from the game files.

    Boxes inside boxes

    From the whole world down to one cube

    Like folders inside folders, the world is split into smaller and smaller boxes. The game seems to keep seven copies of the world at different levels of detail (LOD): probably coarse ones for distant hills, and the finest one, LOD 6 with half-metre cubes, for what is around you.

    resourceVoxelWorldResource10 240 × 2 648 × 10 240 m, 7 levels, 256 material slots
    levelLOD 0 to 6Same world, coarser voxels. LOD 6 has 0.5 m voxels.
    tileTileOne content hash in the .dat files. LOD 6: 128 m square.
    cellCell8 × 8 voxel columns, full world height. LOD 6: 4 m square.
    brickBrick8 × 8 × 8 voxels, stacked bottom-up in the cell. LOD 6: a 4 m cube.
    voxelVoxelTwo bytes: material and fill. Fill is the filled fraction, 0 air to 255 solid.
    LevelTilesVoxels per tileTile sizeVoxelCell and brick edgeCells per tile

    For the curious: a tile container is byte gx, byte gy, then gx·gy little-endian 24-bit offsets, one per cell, relative to the end of the offset table. Cell rows run south to north.

    Columns

    Four real columns, from the bottom of the world up

    As I understand it, the game stores the world as columns 4 m wide that run from the world floor to the sky. Each column is a stack of 4 m bricks, written as runs: "137 bricks of deep rock" costs a couple of bytes. Here are four real columns side by side, drawn to the same scale. Orange bands are the bricks where something changes, like the surface, a cave or an ore vein, and only those need detail.

    Four ways to store a whole brick

    Bricks

    Seven real bricks, opened up

    A brick is a 4 m cube of 8 × 8 × 8 = 512 voxels. Pick one to see it in 3D (partly full voxels are drawn at their fill height), then as eight slices, and finally as the bytes I read for it.

    Loading the 3D view…

    The 8 slices, front to back (height up, x right)

    Bytes

    bitstream (front)material byte (popped from the back)fill byte (popped from the back)

    Runs

    PassVoxelsValueSource
    Bytes

    One column, byte by byte

    At the bottom of it all, a column is a short list of bytes. This one sits at the very edge of the map, under the sea: 152 bytes for 568 m of world, made of 3 bricks of bedrock, a boundary brick, 137 bricks of deep rock and the sea floor. Click a run to see which bytes describe it.

    header run table material byte mixed-brick bitstream fill byte

    Bytes

    Runs

    Run table bits, least significant first

    run lengthtype bitmaterial code10-bit byte length
    Underground

    Slices through the world

    Cut the world open like a cake and this is what I get: every pixel is one voxel, coloured by its material.

    Voxel-resolution vertical section through a granite mountain, 128 m wide, 1540 to 1830 m high, showing coal, iron, amethyst, dirt pockets and a cave
    Half-metre voxels through a granite mountain (tile x 7424–7552 m, z 5832 m, 1540–1830 m high). Coal in black, iron in red, amethyst in purple, Albaneve dirt pockets in brown, a cave pocket in pale blue at the lower right.
    Voxel-resolution vertical section through Springlands, 128 m wide, 800 to 880 m high, with a flint deposit and a buried building
    Springlands (tile x 2944–3072 m, z 1853 m, 800–880 m high): a flint deposit (teal) at the edge of a slope, dirt on the surface and a buried building (orange, building materials).
    Brick-resolution cross-section along z = 1800 m from x = 2000 to 6000 m, 0 to 1600 m high
    The same idea at brick resolution: along z = 1800 m, x = 2000 to 6000 m, 0 to 1600 m high, one 4 m brick per pixel pair. Deep no-drop rock appears as dark pockets under the lowlands.
    In 3D

    Real pieces of Embervale you can orbit

    Each scene is a 16 × 16 m block of LOD 6 cells, decoded with my reading of the game files. Only voxels with an open face are drawn; partly filled voxels are drawn at their fill height. Drag to orbit, scroll or pinch to zoom.

    Loading the 3D view…
    Checks

    Why I think this is right

    Every byte seems accounted for

    In about 78 000 cells and 120 000 mixed bricks across all 7 levels, every cell I read came to exactly top bricks, and every brick ended with its two read pointers meeting.

    Levels mostly agree

    Each LOD 5 voxel (1 m) matches the majority of the 8 LOD 6 voxels inside it for 99.86% of 2.06 million solid voxels sampled.

    Same surface at every level

    In my test, the ocean cell's surface comes out at 567.1 m on LOD 2, 3, 4, 5 and 6, using height = (voxel row + fill / 255) × voxel size.

    Known ground

    The Springlands start tile contains flint and salt and no iron, which matches what you find when you play. I never saw ore fill a whole uniform brick; all of it sat inside mixed bricks.

    So, as far as I can tell, it is kind of correct. This is an educational exercise and I am learning as I go, so some details may still be wrong. If you spot a mistake, I'd love to hear about it.

    Further watching

    Videos I found along the way

    Some interesting videos I found while researching this project.

    This project was made by Jorge Bastida with a fair amount of help from AI.