Heightmap PNG-16 and R16: Real Terrain for Unreal Engine

2026-10-164 min read
heightmapPNG-16R16Unreal EngineWorld Machinegamedev

A heightmap for a game engine is not a GIS raster. The engine wants no coordinate system and no heights in metres: it wants a square canvas of 16-bit samples of a supported size, where black is the lowest place and white the highest. Everything else — the scale — a person sets by hand on import. Our "Heightmap PNG-16" format delivers exactly such a canvas, together with the numbers without which it cannot be unfolded into the right terrain.

What is in the archive

A ZIP named after the canvas size, for example heightmap_1009:

  • heightmap_1009.png — a 16-bit greyscale PNG, linear, no gamma. Unreal, Unity, Blender, World Machine and image editors read it.
  • heightmap_1009.r16 — the same canvas as a raw stream of little-endian 16-bit samples with no header. Unreal and World Machine read it; the reader must know the side length from outside — that is why it is in the file name.
  • Georeferencing files — a world file and a .prj: they describe the square window in WGS84 so the canvas can be placed on a map in a GIS.
  • heightmap_info.txt — a bilingual passport: minimum and maximum height in metres, side length on the ground, node step and the height source credit.

Canvas sizes

The canvas side is chosen from the sizes an Unreal landscape imports directly: 127, 253, 505, 1009 (the default), 2017 and 4033 pixels. Any other requested size is snapped to the nearest one in that list. The upper limit depends on the worker machine's memory.

Why square, and why the frame grows

An order frame is almost never square. The canvas is, so the frame is expanded to a square on the ground: the ordered area lands in the canvas entirely, with neighbouring terrain added at the edges. This is not hidden — the order result carries a square-fit warning.

Three numbers the canvas is useless without

A 16-bit sample means nothing on its own: 0 is the lowest point of this canvas, 65,535 the highest. For the terrain to come out at true scale you need three numbers: minimum in metres, maximum in metres and the side length on the ground. They arrive three ways at once: in the passport inside the archive, in the order warning and in the result details.

Z scale for Unreal. At Z scale 100, an Unreal landscape spreads the full sample range over 512 m. Hence the rule:

Z scale = (maximum − minimum) / 512 × 100

The X and Y scale is the node step in centimetres: side length in metres divided by (canvas side − 1), times 100.

Source honesty

Heights come from open global elevation models (Copernicus DEM, SRTM), not from a hillshade picture: hillshade pixels are light and shadow, not heights. The source node step is about 30 m, and at high latitudes the dataset thins its sampling in longitude — visible on a game landscape, so the step is always stated.

If the window has holes without heights, their share is reported in a warning. If there are no heights at all (open ocean), the canvas comes out flat — and that is said plainly too, not silently. If the frame is too large for the height source, the order is refused with advice to take a smaller area.

Importing into Unreal in a minute

  1. Landscape Mode → Import from File → choose the .png or .r16.
  2. Check that the size matches the file name.
  3. Set the X/Y scale from the node step and the Z scale from the formula above.
  4. Compare the height range in the scene with the minimum and maximum in the passport.
← All articles