Render Approach (3D Earth in the Browser)
This document captures how model-render-web turns the GDEM data on the shared /datasets volume into a 3D view of the Earth in a web browser. It is a decision log; mark each option decided with a date and reason.
Goal
A self-contained web page that renders a 3D globe from real elevation and bathymetry, driven by the ETOPO 2022 dataset (/datasets/dataset-etopo-2022/, 15-arcsecond GeoTIFF tiles, ~6 GB). The page must run in a stock browser (WebGL), and the tiles are far too large to ship raw — the project must convert them into a browser-friendly form.
Source data
ETOPO 2022— global relief model combining land elevation and seafloor bathymetry at 15-arcsecond (~450 m) resolution, as 350 GeoTIFF tiles.- Maintained and versioned by the
model-elevation-earthproject; the manifest is/datasets/manifest.yml(etopo-2022). - Read-only consumption: this project never writes to
/datasets; derived artifacts go indataflow.out/.
Candidate approaches
- Static textures + three.js globe — CHOSEN (decided 2026-08-26)
- Downsample the 350 tiles to a small global grid (e.g. 1-degree / 0.5-degree), render it to an elevation/color texture, and map it onto a three.js sphere. Simple, deterministic, works offline; low fidelity (~100–400 km cells).
- Tiled WebGL globe (quadtree LOD) — deferred (decided 2026-08-26)
- Convert tiles to a tiled pyramid (e.g. raster or quantized-mesh style), fetch only visible tiles at the right zoom. Browser-scale fidelity, much more plumbing. This is the documented upgrade path if regional zoom becomes a requirement.
- Offline preprocessing pipeline + static assets — settled (decided 2026-08-26)
- The build step is GeoTIFF → grid/texture via GDAL on the build host; see the decision log.
Open questions
- In-browser performance budget (texture memory, interaction smoothness) — the assets themselves are decided (see decision log); the regional zoom loads tiles on demand, bounded by the visible window.
Decision log
- 2026-08-26 — Approach: static textures + three.js globe (candidate 1). Reason: deterministic, works offline, matches the minimal-3D-globe TODO milestone; the tiled quadtree (candidate 2) is a documented later upgrade.
- 2026-08-26 — Fidelity: whole-globe overview at 0.5° (720×360 grid). Reason: ~1 MB texture, single page load, no tiling; regional detail is deferred with the quadtree approach.
- 2026-08-26 — Coloring: hypsometric elevation ramp applied to the ETOPO elevation values themselves. Reason: self-contained, fully offline, no second color dataset.
- 2026-08-26 — Toolchain: GDAL 3.8.4 on the build host (
gdalbuildvrt,gdalwarp,gdaldem) plus Python 3 with osgeo/numpy for the raw-grid export and metadata. Reason: available on this host (verified 2026-08-26); no custom reader needed. - 2026-08-26 — **Performance budget: 720×360 Float32 elevation grid (~1 MB)
- 720×360 and 1440×720 hypsometric PNGs (~1.6 MB total)**, two texture loads per page (normal and large views).
- 2026-08-26 — Large view: 2× canvas with a 0.25° texture (1440×720). The globe page offers a Double size control that doubles the canvas height and swaps in the 0.25-degree hypsometric texture, keeping the same per-pixel sharpness as the normal view (canvas size and texture resolution double together). Reason: user request; the 0.25° grid is a second pipeline pass (
etopo-global-0.25deg.tif+etopo-hypsometric-0.25deg.png). - 2026-08-26 — Regional zoom (quadtree-LOD upgrade, started). The globe page now zooms with the mouse wheel and, when the camera is close enough, textures a spherical patch over the visible window from an equirectangular tile pyramid (
scripts/etopo-tiles-build.sh): levels z1..z5 (2×1 up to 32×16 tiles, 256×256 px each, cell size halving from 0.7° to 0.044° per pixel). Only the tiles intersecting the visible window are fetched at the zoom level matching the view; the idle spin pauses while zoomed in so the region stays under the view. Deeper levels (z6+) are generated on demand with--tile Z ROW COL; the pyramid index must then be extended. Reason: user request to start the deferred quadtree upgrade; the full quad-sphere mesh LOD (per-patch subdivision) remains a further stage. - 2026-08-26 — Base globe mapping made explicit: three.js SphereGeometry places texture u=0.5 at local lon +90 (the map renders rotated 90°); the base sphere’s UVs are now remapped to the explicit convention texture-lon L at local lon L, v=1 at the north pole, so Greenwich faces the camera and the detail patch shares one verifiable mapping with the base.
- 2026-08-26 — Page location:
site.in/→site.out/via the existing site build; the render page isglobe.html, published with the homelab. Reason: reuses the registered publish flow and keeps the site self-contained (assets are copied intosite.out/by the build).