@@ -23,6 +23,20 @@ then open <http://localhost:8000/>.
2323| ` Space ` / ` Ctrl ` | ascend / descend |
2424| ` Shift ` | boost |
2525| wheel | field of view |
26+
27+ The panel's readout gives the live numbers behind the level of detail:
28+ altitude, viewing distance, the ground a screen pixel covers there, the
29+ switch distance in force next to what the screen alone would ask for,
30+ and the imagery level and span in use.
31+
32+ ** Wind** adds drone-like drift: a slow attitude wobble, a slower
33+ positional sway, and a gust envelope that swells both. It sways the view
34+ only -- your position and heading are untouched, so it never blows you
35+ off course and never disturbs the imagery level of detail. At 0 it is
36+ skipped entirely.
37+
38+ The sun is set by compass bearing (0 = north, 90 = east). Caldera sits at
39+ latitude -27, so its light comes from the north.
2640| ` H ` | hide the settings panel |
2741
2842On a touch device the page switches to a movement joystick plus
@@ -37,6 +51,107 @@ and the sensors only work in a secure context, so a plain
3751` http://192.168.x.x ` address on your LAN will not get readings. Use
3852HTTPS or a tunnel to try it on a real phone.
3953
54+ ## Terrain
55+
56+ Two datasets, switchable in the panel.
57+
58+ ** Caldera, Atacama** (default) is real elevation, 30.5 km of the
59+ Chilean coast around Caldera at 17 m per texel, sea level to 952 m.
60+ Position is reported as real latitude, longitude and altitude in metres.
61+ Regenerate it, or fetch anywhere else, with:
62+
63+ python3 tools/fetch-terrain.py --lat -27.0678 --lon -70.8231 --zoom 13
64+
65+ Zoom 13 is deliberate. Measured against a bilinear upsample of the level
66+ above it, z13 adds ~ 5 m RMS of genuine detail here while z14 adds
67+ 0.1-0.4 m -- nothing. The underlying source is SRTM. Regions covered by
68+ national lidar (the US, via 3DEP) keep gaining real detail to z14-15, so
69+ the useful ceiling is a property of the region, not of the tileset.
70+
71+ Real terrain is much gentler than the synthetic map -- 957 m of relief
72+ over 30 km is 56 texels at true scale, against the 2010 map's 249 -- so
73+ a ** vertical scale** control exaggerates it. The default is 3x. Heights
74+ are held in a float texture, so there is no 0-255 ceiling to clip
75+ against.
76+
77+ ** Satellite imagery** drapes Esri World Imagery over the elevation.
78+ Esri's tiles use the same Web Mercator grid as the terrain tiles, so
79+ they register pixel-for-pixel with no reprojection -- measured alignment
80+ against the elevation-derived coastline is dx=0, dy=0. Because the grids
81+ nest, the imagery is taken one zoom finer than the terrain: z14, 8.5 m
82+ per pixel over 17 m terrain, a 3584px mosaic of 196 tiles (~ 1.3 MB).
83+ Touch devices stay at z13 to keep the texture a quarter of the size.
84+ Turn it off and the hypsometric elevation colouring comes back.
85+
86+ Detail is not capped at that, though. A second, smaller imagery texture
87+ follows the camera at a zoom picked from ** how far away the terrain being
88+ looked at is** -- not from altitude, which is only the same thing when
89+ the camera points straight down -- cross-fading into the base at its
90+ edges and with distance. Fly low and roads and tracks
91+ resolve; climb and it steps back down, then switches off once the base
92+ is enough. The panel reports the level in use.
93+
94+ ** Detail switch** sets the distance at which the finest level gives way
95+ to the next one down; every band below and above it follows by halving
96+ and doubling. Set it to 2.2 km and anything you look at inside 2.2 km
97+ gets z17, out to 4.4 km z16, and so on. The screen-derived figure (shown
98+ as ` auto ` ) is where finer imagery stops being * resolvable* , which is not
99+ the same as where it stops being * worth fetching* -- so the slider
100+ defaults to 2.2 km, well past it.
101+
102+ ** Tile grid + 1 km rings** is a debug overlay: alternate imagery tiles
103+ are tinted, so tile size against distance is visible and the detail
104+ rectangle shows up as a change of grid pitch, and range rings mark every
105+ kilometre with the switch distance in cyan. Off by default, ` ?grid=1 `
106+ to pin it.
107+
108+ The slider runs to 8 km, and its upper end means * the finest level whose
109+ rectangle can cover what you are looking at* : the rectangle is finite,
110+ reaching 2.42 km at z17, 4.85 km at z16 and 9.69 km at z15 (half that on
111+ touch). When reach rather than the slider decides, the readout says
112+ ` rect-limited ` .
113+
114+ Note that ** vertical scale moves the levels** . Heights are exaggerated
115+ but horizontal distance is not, so at the default 2.5x a camera reading
116+ 500 m is looking 5.5 km at real ground when it looks near-level -- far
117+ enough that the base mosaic is already as fine as the screen resolves.
118+ z17 arrives from about 28 degrees down at 2.5x, 38 degrees at 3x, and
119+ straight away at 1x, where a readout of 500 m means the camera really is
120+ 500 m up in the geometry the rays march. Fly lower, look down, or turn
121+ the exaggeration down.
122+
123+ Three bugs used to hide all of this. The shader faded the detail layer
124+ out with distance, on reasoning left over from an earlier
125+ altitude-driven version; the texture LOD used a constant that assumed a
126+ 380px-tall window, so on a normal screen the detail layer was sampled at
127+ the base mosaic's own resolution; and the layer's height input divided
128+ the vertical exaggeration back out, which placed the rectangle at a
129+ third of the distance it needed and left every pixel on screen outside
130+ it. Between them, detail was only ever visible below about 200 m.
131+
132+ How far it can go depends on the region. Beyond its high-resolution
133+ coverage Esri serves a flat grey "Map data not yet available"
134+ placeholder rather than an error, so the demo probes one tile before
135+ loading a level and walks the ceiling down until it finds real imagery.
136+ At Caldera that ceiling is ** z17, 1.06 m/px** ; z18 and up are
137+ placeholders.
138+
139+ The imagery is fetched ** at runtime** , not shipped in ` assets/ ` . The
140+ terrain tiles are open data; Esri's imagery is not -- it is licensed
141+ under Esri's Master License Agreement. Fetching tiles live is the
142+ ordinary usage pattern that every web map follows, but caching a mosaic
143+ into a published repository would be redistribution.
144+
145+ ** Original 2010 map** is the synthetic heightmap the demo shipped with,
146+ unchanged.
147+
148+ Elevation data: Tilezen terrain tiles via AWS Open Data, no API key
149+ required. Imagery: Esri, Maxar, Earthstar Geographics and the GIS User
150+ Community. Attribution for both is required and is shown in the panel;
151+ see
152+ ` assets/terrain-*.json ` and
153+ < https://github.com/tilezen/joerd/blob/master/docs/attribution.md > .
154+
40155## The two modes
41156
42157** Modern** is the default: filtered textures, slope-based sun
@@ -82,9 +197,9 @@ The original wrapped the world at `heightmap->w - 1` = 1791. The
82197heightmap actually tiles seamlessly at 1792, so that left a
83198one-column seam. Not reproduced.
84199
85- ` ?x=&y=&z=&yaw=&pitch=&retro=&scale=&steps=&dist=&fov=&touch= ` pin the
86- camera and render settings from the URL, which is what makes
87- screenshots reproducible.
200+ ` ?x=&y=&z=&yaw=&pitch=&retro=&scale=&steps=&dist=&detail=&grid=&wind=& fov=&touch=&terrain=&vs=&hud= `
201+ pin the camera and render settings from the URL, which is what makes
202+ screenshots reproducible. ` hud=0 ` strips the overlay.
88203
89204## Layout
90205
@@ -99,3 +214,4 @@ screenshots reproducible.
99214 src/gl.js shader/texture helpers
100215 src/shaders/ the ray march
101216 tools/convert-assets.py BMP -> PNG
217+ tools/fetch-terrain.py real elevation tiles -> mosaic + metadata
0 commit comments