Loading elevation…

Elevation: GSI tiles (DEM10B), processed · Drawn by Relief

Language

Writing a map engine from scratch · 3

Relief

Mount Fuji and its lakes from the Geospatial Information Authority of Japan's elevation tiles, decoded, shaded, contoured and built into a block, all in code written for this page. Drag the sun, switch to 3D, or draw a profile across the mountain.

View
View
Shading
Shading
Sun

Azimuth 315° · Altitude 32°

Interval
Interval
Profile

How it works

Six steps from 81 elevation tiles to the map and the block above. Each step is a few hundred lines of code and can be switched on and off from the controls.

  1. 01

    Heights packed into a PNG

    Each GSI elevation tile is a 256 × 256 PNG whose colour is a number: 2¹⁶R + 2⁸G + B hundredths of a metre. Relief's own PNG reader walks the chunks, checks each CRC-32, inflates the zlib stream and undoes the per-row filters; 81 tiles are stitched into a 2,049 × 2,049 grid and written back with Relief's own writer as one 16-bit greyscale PNG, 4.16 MB. Browsers will not hand a page 16-bit pixels, so the page decodes it with the same reader; on every one of the 4.2 million samples it agrees with an independent decoder.

    x = 2¹⁶R + 2⁸G + B
    h = x / 100 m   (x = 2²³ means no data)
  2. 02

    Slope from a 3 × 3 window

    The slope at each cell comes from its eight neighbours (Horn's method), which smooths out the steps a grid leaves. The slope and the direction the ground faces give the classic hillshade: the brightness a surface would have under one sun.

    shade = cos z · cos s + sin z · sin s · cos(A − a)
  3. 03

    Light, shadow and water

    The shading runs on the GPU, one fragment per cell, into a texture. Cast shadows walk from each cell towards the sun in growing steps and darken it wherever the ground rises above the ray. Lit slopes are warmed and shaded ones cooled. Lakes are found in the data itself: a lake surface is perfectly flat, so every patch of more than 400 level cells is water, and its surface height is read off the grid.

  4. 04

    Contours by marching squares

    Every four neighbouring cells form a square, and each corner is either above or below the contour height: sixteen cases, each telling which two sides a line crosses. Where two opposite corners are high and the other two low, the average of all four decides which way the line runs. Points are shared along each side, which joins the pieces into lines; a Web Worker does this so dragging stays smooth. Every fifth line is labelled, and the label is turned so its top faces uphill.

  5. 05

    A mesh that adapts to the ground

    For 3D the grid is split into two right triangles, and each is halved again and again down to single cells. Each halving point records how far the ground strays from the triangle's straight edge there. The mesh splits only where that exceeds the error you choose, so flat lakes take a few large triangles and the summit takes many small ones. Neighbours share each split, so the mesh has no cracks.

    1,025² grid · error 5 m → 484,127 triangles
  6. 06

    Drape and block

    The shaded texture, with the contours drawn into it, is laid over the mesh. Walls run down from every edge vertex to 300 m below the lowest cell, banded every 250 m. Exaggeration stretches heights for both the light and the block, so the same ridge looks steeper in both.

Elevation: Geospatial Information Authority of Japan, elevation tiles (DEM10B, made from the contours of the 1:25,000 maps, a 10 m grid averaged to about 15.6 m), stitched, quantised to 0.1 m and re-encoded. The summit of Mt Fuji is 3,776 m; the grid's highest cell is 3,773.0 m because each zoom-13 cell is the average of four finer ones.