mapspinner 0.1.42 → 0.1.43

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapspinner",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "WebGL2 Earth-scale terrain rendering SDK for interactive globe applications",
5
5
  "main": "src/index.js",
6
6
  "exports": {
package/src/gl-render.js CHANGED
@@ -780,7 +780,14 @@ export async function initMapspinnerRender(gl, opts = {}) {
780
780
  const camDist = Math.hypot(cam.eye[0], cam.eye[1], cam.eye[2]);
781
781
  const alt = Math.max(0.0, camDist - R);
782
782
  const altAboveTerrain = Math.max(0.001, alt - R * (cam.surfElev || 0));
783
- const horizon = Math.sqrt(Math.max(0.0, camDist*camDist - R*R));
783
+ // FAR-PLANE HORIZON RADIUS = R - 500m (user 2026-06-14: 'nearby mountains disappear at water level;
784
+ // adjust that level to 500m under water'). The far plane tracks the sea-level horizon = sqrt(camDist^2
785
+ // - R^2), which at the deck (camDist~=R) collapses to a few hundred metres -> coastal mountains a km
786
+ // out fall beyond the far plane and vanish. Dropping the horizon reference radius 500m below sea level
787
+ // extends the horizon to tens of km at low altitude so near-shore relief stays in view (negligible
788
+ // depth-precision cost: 500m vs R~6.37e6). Both the cull and the draw use this (single source).
789
+ const RHORIZON = R - 500.0;
790
+ const horizon = Math.sqrt(Math.max(0.0, camDist*camDist - RHORIZON*RHORIZON));
784
791
  // MATCH render()'s near exactly (2026-06-14 jank fix): the cull frustum must use the SAME near
785
792
  // as the draw frustum, else behind-limb/screen-AABB culling diverges from what is actually drawn
786
793
  // at the deck (cull near was max(*0.1,0.1) while render used the <2m 0.05 branch).
@@ -816,7 +823,14 @@ export async function initMapspinnerRender(gl, opts = {}) {
816
823
  const camDist = Math.hypot(cam.eye[0], cam.eye[1], cam.eye[2]);
817
824
  const alt = Math.max(0.0, camDist - R);
818
825
  const altAboveTerrain = Math.max(0.001, alt - R * (cam.surfElev || 0));
819
- const horizon = Math.sqrt(Math.max(0.0, camDist*camDist - R*R));
826
+ // FAR-PLANE HORIZON RADIUS = R - 500m (user 2026-06-14: 'nearby mountains disappear at water level;
827
+ // adjust that level to 500m under water'). The far plane tracks the sea-level horizon = sqrt(camDist^2
828
+ // - R^2), which at the deck (camDist~=R) collapses to a few hundred metres -> coastal mountains a km
829
+ // out fall beyond the far plane and vanish. Dropping the horizon reference radius 500m below sea level
830
+ // extends the horizon to tens of km at low altitude so near-shore relief stays in view (negligible
831
+ // depth-precision cost: 500m vs R~6.37e6). Both the cull and the draw use this (single source).
832
+ const RHORIZON = R - 500.0;
833
+ const horizon = Math.sqrt(Math.max(0.0, camDist*camDist - RHORIZON*RHORIZON));
820
834
  const near = altAboveTerrain < 2.0 ? 0.05 : Math.max(altAboveTerrain * 0.1, 0.05);
821
835
  const _fBlend = Math.min(1.0, Math.max(0.0, (alt - 500000.0) / 4500000.0));
822
836
  const farGround = Math.max(horizon, alt * 8.0);
@@ -634,7 +634,11 @@ highp float composeHeight(vec3 dir0, highp vec2 faceLocal, float tileM){ // W7
634
634
  // the field -> seam-safe + the collision probe shares it. GUARD: a stale/unset uniform (0) would
635
635
  // disable the shelf -> default 600 so it always applies. window.__beachShelf dials S live.
636
636
  highp float bShelf = uBeachShelfM > 1.0 ? uBeachShelfM : 600.0;
637
- if (h < bShelf) h = h * h / bShelf;
637
+ // C1-CONTINUOUS shelf (user 2026-06-14 'hard shading line where landscape meets beach'): the old
638
+ // h*h/S met the identity at h=S with SLOPE 2 (vs 1) -> a derivative kink -> the slope-keyed shading
639
+ // (rock/AO/material) SNAPPED into a hard line at the shelf top. f = (h*h/S)*(2 - h/S) keeps f(0)=0,
640
+ // f'(0)=0 (flat at the waterline = wide beach) AND f(S)=S, f'(S)=1 (smooth join to natural land).
641
+ if (h < bShelf) h = (h * h / bShelf) * (2.0 - h / bShelf);
638
642
  }
639
643
  // displacement now continues UNDERWATER (the old land-only gate served the flat-clamped ocean,
640
644
  // gone since 026d530): the seabed carries the same micro-relief as land = realistic continuation.
@@ -853,7 +857,8 @@ void main() {
853
857
  vH = max(vH, -11000.0); // cap depth at Mariana Trench (~11km)
854
858
  } else {
855
859
  highp float bShelf = uBeachShelfM > 1.0 ? uBeachShelfM : 600.0; // LAND COASTAL SHELF -- mirror composeHeight exactly (wide beach, user 2026-06-14); guard stale/unset uniform
856
- if (vH < bShelf) vH = vH * vH / bShelf;
860
+ if (vH < bShelf) vH = (vH * vH / bShelf) * (2.0 - vH / bShelf); // C1-continuous (mirror composeHeight) -- removes the beach-top slope kink / hard shading line
861
+
857
862
  }
858
863
  vH += vDisp;
859
864
  vH += detailFbm(dir0) * uDetailOverlay * 30.0 * step(0.0, vH);