Ortho Earth 2.1 is out

Text moved to the GPU, pictures closer to MapLibre, and nothing broke

2026-10-23 · Kenji Yoshida · @ortho-earth/globe · @ortho-earth/core

@ortho-earth/globe and @ortho-earth/core are now 2.1. With 2.0 the features I wanted were all in place, so this release does not add features. It polishes the ones that are there. Two things went into it. The way the map draws text, which had bothered me for a long time, moved to the GPU. And at the same time, compatibility with MapLibre GL JS went up another step.

What I most want to say about this release, though, is not how much changed. It is that after replacing this much of the machinery, the API is the same as 2.0 and not a single thing broke. This engine has grown more robust than I expected.

1. Map text on the GPU

Place names, road names, icons, road shields: until now every piece of text on the map was drawn one glyph at a time with Canvas2D. The Earth and the buildings were drawn on the GPU, while the text was a 2D picture laid on top by the CPU. That also fixed the order as "the whole map first, then the text", so a MapLibre style that puts lines or fills above its labels could not be drawn as written. In a dense city, drawing the text alone made things heavy. For a long time this was the engine's biggest worry.

In 2.1, text is baked into an SDF glyph atlas (each glyph stored as a distance from its edge) and drawn in one go with WebGPU. Colour, size and halo are decided in the shader, so each glyph is baked once per font. Point labels, labels along lines, icons and road shields, geojson symbol layers, cluster counts, and even the star names and the Moon all go through this one path. While the map is viewed from straight above, text is drawn at its style layer's position, so a style with lines above its labels stacks the same way it does in MapLibre.

Beyond text, the remaining things that were redrawn in 2D on top of the map every frame also moved to the GPU: cluster circles (map.gadget.cluster), the screen grid, CZML and GPX tracks, colour-graded lines (line-gradient) and patterned lines (line-pattern). Only two stay in 2D: annotations and pasted images, which share their drawing code with the editing tools.

2. MapLibre compatibility

The yardstick is MapLibre's own 139 official examples. Each one runs the same code in real MapLibre and in ortho-earth, and the two are compared picture by picture and answer by answer (137 of them are scored). You can browse every result at /maplibre.

LevelPrevious run (Oct 14)2.1 (Oct 23)
3 Same picture6679
2 Same answers5047
1 Runs2111
0 Does not run00

Thirteen more examples now draw the same picture, and the ones that run but give different answers halved. Besides drawing text at its layer's position, these changes did the work:

3. Same API as 2.0

For all the changes inside, the public API is the same as 2.0. Code written for 2.0 runs on 2.1 as it is. Only the speed and the correctness of the picture went up.

npm i @ortho-earth/[email protected]
One name that changed

map.gadget.cluster now builds a cluster source and layers inside, the same way MapLibre does. As a result, the layer names that queryRenderedFeatures returns changed from clusters / unclustered-point to gadget-cluster-clusters / gadget-cluster-unclustered. Only code that queried by those layer names needs updating. Clusters made the MapLibre way (addSource with cluster: true and addLayer) keep the layer names you gave them.

4. Built to be tested: Design For Test

2.1 replaced several of the drawing paths deep inside the engine. Even so, across the 137 official examples not a single one scored lower than in the previous run.

I don't think that was luck. It comes from the design. In semiconductors there is a term, DFT (Design For Test): instead of working out how to test a chip after it is made, you build the means of testing into the design from the start. This engine has been built that way all along.

It seems that what six months built up was not only features. Because it is built to be tested, it can take a big change without breaking. With this release I felt that clearly for the first time.

Kenji Yoshida @ Yokohama