mapspinner 0.1.78 → 0.1.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -5,17 +5,18 @@
5
5
  SDK changes must be validated against the test suite and verified in both the dev demo (planet.html) and external consumer examples. No changes ship without passing tests.
6
6
 
7
7
  ## Architecture (GPU one-fractal)
8
- - Height pool: **R16F**, **1024 layers**, **4 mip levels**, 130-texel tiles. The ONLY runtime branch is a
9
- FORMAT capability probe (`_useR16F` = half-float color+storage+linear) that falls back to the
10
- numerically-equivalent R32F when the GPU lacks half-float correctness, not a quality tier.
11
- (`THC_CACHE_LAYERS` clamps to `MAX_ARRAY_TEXTURE_LAYERS`; 1024 was tuned from a live eviction
12
- measurement 512 evicted ~3155/s at the deck where ~594 leaves are visible, 1024 → 0/s. ~35MB vs
13
- the old 138MB R32F/2048 = ~90% VRAM cut.)
14
- - Shader precision: **global `mediump float`** with explicit **highp islands** on every planet-scale
15
- quantity (`vRel`/`vWorld`/`vH`, `defRadius`/`defViewProj*`/`defCam*`, all noise lattices + their args,
16
- `broadShapeM`/`broadShapeLowM`/`faceWarp`/`vtxDisplace` metre accumulators, coordinate-snapped noise
17
- anchors `rockO`/`wOrigin`). Validated SAFE live: `d.assertElevLinear()` pass, `d.pxPerPoly()` ~238k
18
- tris rasterized. fp16 leaking onto a planet-scale value collapses the geometry keep the islands.
8
+ - LIVE height path = **procedural `composeHeight` per-vertex in the VS** (`terrain.glsl`): every vertex
9
+ evaluates broadShapeM + carves directly. There is NO baked height pool on the default path.
10
+ - THC height pool (OPTIONAL, **default-OFF** behind `window.__thc`): **R32F**, **130-texel tiles**,
11
+ **512 layers** (`THC_BAKE_RES`/`THC_POOL_LAYERS`, `gl-render.js`). An O(1) baked-tile fetch that
12
+ replaces composeHeight when enabled. MEASURED NET-NEGATIVE at the deck (cuts VS but pushes the cost to
13
+ FS, full-frame flat-to-worse 2026-06-15) so it stays off; keep it as a lever, do not default it on.
14
+ (Any AGENTS history claiming "R16F/1024 live" was aspirational doc-drift, corrected 2026-06-15.)
15
+ - Shader precision: **global default `highp float`** (`gl-render.js` hdr = `precision highp float`). The
16
+ earlier mediump-default experiment was REVERTED — any world-scale noise UV (freq up to ~9000) evaluated
17
+ in fp16 scrambled the lattice at close range, and chasing per-site highp islands kept missing sites.
18
+ highp-default kills the whole class in one line; the explicit highp islands left in the shader are now
19
+ redundant-but-harmless. int + sampler2DArray stay highp. fp16 on a planet-scale value collapses geometry.
19
20
  - Reduced octaves: `broadShapeM` 14→12, `vtxDisplace` 9→6, single-octave rock detail; tanh ceiling
20
21
  `tanh(x/8000)` gives pointed peaks (CLI `shapeReport allGatesPass`). Distance-gated cheap FS far path.
21
22
  Tightened LOD (`planet-orchestrator` splitFactor + near-radius). Dead atlas apparatus deleted.
@@ -33,13 +34,11 @@ camera you can't aim. Use the DATA diagnostics — `__diag.pxPerPoly()` (on-scre
33
34
  ## The terrain pipeline in one page (read this before touching terrain)
34
35
 
35
36
  Earth-scale terrain SDK, WebGL2, served at `http://localhost:8080/` (entry `planet.html`, `server.js`).
36
- GPU one-fractal: no tile producer. A finer
37
- LOD is a denser sample of the SAME field. The procedural broadShapeM fractal is the LIVE render
38
- path (hasAtlas==0, the default). The baked atlas is opt-in (planet-orchestrator.js opts.atlas===true;
39
- live `window.__toggleAtlas(on)` / `__forceAtlas`); its bake is CLI-validated faithful (atlas-bake.mjs
40
- `interiorExact` gate) and `broadShapeMD` central-differences `atlasHeight` so atlas-on land shades with
41
- relief. Do NOT delete the procedural path while the atlas is opt-in. Recall
42
- "tv8-atlas-flat-is-flat-normals-root-2026-06-07" + "tv8-reliable-visual-witness-method-2026-06-03".
37
+ GPU one-fractal: no tile producer, no atlas. A finer
38
+ LOD is a denser sample of the SAME field. The procedural broadShapeM fractal is the ONLY render
39
+ path. (The baked-atlas apparatus was REMOVED in prior work — only historical comments remain across
40
+ src/; any AGENTS history describing an opt-in atlas / `__toggleAtlas` / `atlas-bake.mjs` is stale
41
+ doc-drift, corrected 2026-06-15. Recall "tv8-reliable-visual-witness-method-2026-06-03".)
43
42
 
44
43
  THE SPOOL `browser` VERB IS A FULL BROWSER, NOT HEADLESS (user correction 2026-06-11): it drives a
45
44
  locally-profiled Chromium with the REAL GPU + real ANGLE backend (witnessed: ANGLE AMD D3D11 -- the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapspinner",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "description": "WebGL2 Earth-scale terrain rendering SDK for interactive globe applications",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -83,7 +83,7 @@ float atm_mieDensity(highp float r) { return exp(-(r - ATM_BOTTOM)/ATM_MIE_
83
83
  // Optical depth (Rayleigh,Mie line integral) from point p0 along dir for distance d.
84
84
  // Cheap fixed-step trapezoid; cheap enough for a fullscreen pass.
85
85
  void atm_opticalDepth(highp vec3 p0, vec3 dir, float d, out float odR, out float odM) { // W7: km-scale p0 -> highp
86
- const int N = 8;
86
+ const int N = 4; // FPS: 8->4 trapezoid steps (2026-06-15). optical depth of a smooth exp density integral -- halving steps shifts the result <1% (witnessed visual-neutral); cuts the nested sky+AP cost.
87
87
  float dt = d / float(N);
88
88
  odR = 0.0; odM = 0.0;
89
89
  for (int i = 0; i < N; i++) {
@@ -143,7 +143,7 @@ vec3 atm_skyRadiance(highp vec3 cameraIn, vec3 viewRay, vec3 sun, out vec3 trans
143
143
  float dEnd = ground ? dGround : max(dTop, 0.0);
144
144
  if (dEnd <= 0.0) { transmittance = vec3(1.0); return vec3(0.0); }
145
145
 
146
- const int N = 16;
146
+ const int N = 8; // FPS: 16->8 single-scatter march steps (2026-06-15). With opticalDepth at 4 the inner cost is 4x lower per step; the sky gradient is a smooth analytic integral so 8 steps is visually negligible (witnessed). Nested cost 16*8=128 -> 8*4=32 (-75%).
147
147
  float dt = dEnd / float(N);
148
148
  vec3 inscatR = vec3(0.0);
149
149
  vec3 inscatM = vec3(0.0);
@@ -302,7 +302,7 @@ highp float cliffTerraceM(vec3 dir, highp float h, out float cliffOut){ // W7:
302
302
  if (region <= 0.0) return 0.0;
303
303
  // EXCLUDE steep mountains (a mesa is a flat-topped raised block, not a peak). Macro slope from
304
304
  // broadShapeLowM over a fixed 1.2km step -> fade mesas out where the broad land is already steep.
305
- const float e = 1200.0;
305
+ const float e = 2400.0; // FPS/quality: 1200->2400 macro-slope FD step (2026-06-15). A wider step better captures the MACRO slope for the mesa flatness gate (less aliasing) and pairs with fewer broadShapeLowM octaves; the gate position is visually unchanged (badlands-only, gated).
306
306
  vec3 ux = normalize(cross(abs(d.y) < 0.99 ? vec3(0.0,1.0,0.0) : vec3(1.0,0.0,0.0), d));
307
307
  highp float h0 = broadShapeLowM(d); // W7: metres, highp
308
308
  highp float gx = (broadShapeLowM(normalize(d + ux * (e/defRadius))) - h0) / e;
@@ -2252,7 +2252,7 @@ void main() {
2252
2252
  float apGate = smoothstep(3.0, 120.0, dKm);
2253
2253
  if (apGate > 0.002) {
2254
2254
  vec3 vRay = segKm / max(dKm, 1e-4);
2255
- const int APN = 8;
2255
+ const int APN = 4; // FPS: 8->4 aerial-perspective march steps (2026-06-15). Distance-gated (apGate 3..120km) so it only shades FAR terrain where the smooth haze integral is visually unaffected by step count.
2256
2256
  float apdt = dKm / float(APN);
2257
2257
  vec3 inscatR = vec3(0.0), inscatM = vec3(0.0);
2258
2258
  float odR = 0.0, odM = 0.0; // optical depth camera->sample