mapspinner 0.1.53 → 0.1.55

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.53",
3
+ "version": "0.1.55",
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
@@ -1115,11 +1115,11 @@ export async function initMapspinnerRender(gl, opts = {}) {
1115
1115
  // shows. Cap every visible leaf at level WCAP and DEDUP to its ancestor tile: a coarse,
1116
1116
  // LOD-churn-free cover of the same footprint, typically ~10-50x fewer water vertices.
1117
1117
  // __waterSurface=0 disables live.
1118
- // UNDERWATER: skip the sea-level water surface entirely (user 2026-06-14 'underwater looks weird,
1119
- // we cant see anything / it must draw the sea bed'). The surface mesh drawn from below was an
1120
- // opaque sheet that occluded the seabed; with it gone, the underwater camera sees the seabed
1121
- // terrain directly (with the underwater fog). Above water it draws normally.
1122
- if ((typeof window === 'undefined' || window.__waterSurface !== false) && !_uw) {
1118
+ // The water surface draws in BOTH cases now (user 2026-06-14 'no water surface visible from
1119
+ // underneath'): it's geometrically ABOVE the camera, so underwater it is the up-view CEILING
1120
+ // (Snell's window, shaded in the uUnderwater branch) and the seabed below stays visible (the
1121
+ // down-view ray never hits the surface). With the fog 10x lighter it no longer washes the floor.
1122
+ if (typeof window === 'undefined' || window.__waterSurface !== false) {
1123
1123
  // WCAP 7 -> 9 (coast witness caught it: a level-7 tile's 16-cell mesh chord sags
1124
1124
  // A_cell^2/(8R) ~ 0.8m below the true sphere mid-cell -- BELOW the metres-deep shelf
1125
1125
  // seabed, so the depth test culled the water across entire shorelines. Level-9 cells
@@ -143,7 +143,7 @@ float snoise3(highp vec3 P){ highp vec3 i=floor(P),f=fract(P); highp vec3 u=f*f*
143
143
  // the same class as the historical snoise3-in-VS-only bug). Pure fn of world dir -> seam-safe +
144
144
  // LOD-invariant. Each has an EROSION profile: a wide graded shoulder/valley/bench that blends into
145
145
  // terrain plus a deeper core, and returns a wet/depth mask the FS colours.
146
- const float LAKE_CARVE_DEPTH = 90.0; // metres of bowl depth at basin centre
146
+ const float LAKE_CARVE_DEPTH = 220.0; // 90->220 metres of bowl depth (user 2026-06-14 'lakes super shallow+flat'): deeper basins
147
147
  float lakeBasinField(vec3 dir){ return 0.5 + 0.5 * snoise3(dir * 55.0 + vec3(4.0, 9.0, 1.0)); }
148
148
  float lakeCarveM(vec3 dir, out float wet){
149
149
  float basin = lakeBasinField(dir);
@@ -186,7 +186,7 @@ float inciseRidgeField(vec3 d, float baseFreq, float freqMul){
186
186
  }
187
187
  return sum / norm; // ->1 on the channel network
188
188
  }
189
- const float RIVER_INCISE_DEPTH = 120.0; // metres at the channel thalweg
189
+ const float RIVER_INCISE_DEPTH = 280.0; // 120->280 metres at the channel thalweg (user 2026-06-14 'rivers/channels super shallow+flat'): deeper incision
190
190
  float riverRidgeField(vec3 dir){ return inciseRidgeField(normalize(dir), 40.0, 2.03); }
191
191
  float riverCarveM(vec3 dir, out float wet){
192
192
  float ridge = riverRidgeField(dir);
@@ -1560,6 +1560,16 @@ void main() {
1560
1560
  vec3 deepBlue = vec3(0.005, 0.06, 0.18);
1561
1561
  vec3 waveBright = vec3(0.0, 0.02, 0.06) * length(slopeW);
1562
1562
  vec3 wcol = deepBlue + sunUnder * 0.4 + waveBright;
1563
+ // SNELL'S WINDOW (user 2026-06-14 'no water surface visible from underneath'): looking UP, the
1564
+ // surface is a bright window to the sky within the critical angle (near-vertical view) and a
1565
+ // dark total-internal-reflection mirror at grazing angles. upness = how vertical the view->
1566
+ // surface ray is; brighten toward the refracted sky + a sun disc inside the window.
1567
+ float upness = abs(dot(viewW, wn));
1568
+ float snell = smoothstep(0.50, 0.82, upness);
1569
+ vec3 skyWindow = vec3(0.40, 0.60, 0.85) * (0.5 + 0.9 * ndl);
1570
+ wcol = mix(wcol, skyWindow, snell * 0.85);
1571
+ float sunw = pow(max(dot(viewW, sunDir), 0.0), 180.0); // sun seen through the window
1572
+ wcol += vec3(1.0, 0.92, 0.70) * sunw * (0.4 + 0.6 * snell);
1563
1573
  float macroMuW = dot(uz, sunDir);
1564
1574
  float dayShadeW = mix(uNightFloor, 1.0, smoothstep(-uTermWidth, uTermWidth, macroMuW));
1565
1575
  vec3 cW = wcol * dayShadeW * uExposure;
@@ -2189,6 +2199,11 @@ void main() {
2189
2199
  vec3 absorb = vec3(0.035, 0.010, 0.005) * (1.0 + depth * 0.0001);
2190
2200
  vec3 uwTrans = exp(-absorb * dKm);
2191
2201
  vec3 uwFog = vec3(0.004, 0.09, 0.18) + vec3(0.0, 0.015, 0.03) * depth / 1000.0;
2202
+ // SEABED LIGHTING (user 'floor too flat/dim'): the deep floor gets almost no direct sun, so it
2203
+ // read dim+flat. Lift the brightness and add an up-facing fill (brighter where the surface faces
2204
+ // up, darker on slopes -> 3D relief) + a touch of slope contrast keyed on the lit normal vNrm.
2205
+ float upFill = mix(0.75, 1.35, clamp(dot(vNrm, normalize(vWorld)) * 0.5 + 0.5, 0.0, 1.0));
2206
+ color *= upFill * 1.5;
2192
2207
  color = mix(color * uwTrans + uwFog * (1.0 - uwTrans), uwFog, smoothstep(100000.0, 500000.0, dKm * 1000.0));
2193
2208
  }
2194
2209
  // RIVERS post-lighting (witnessed browser-2115/2118: the river-blue in ALBEDO is multiplied
@@ -2205,8 +2220,10 @@ void main() {
2205
2220
  // bypasses it via vH<0). Gating on vWaterDepth (NOT the whole carve mask) makes the water LINE UP
2206
2221
  // with the flat carved surface -- the graded erosion banks above the waterline stay dry land.
2207
2222
  if (vH >= 0.0 && vWaterDepth > 0.0) {
2208
- // submergence 0..1 over ~0..40m -> shoreline (thin water, terrain shows through) to deep.
2209
- float sub = clamp(vWaterDepth / 40.0, 0.0, 1.0);
2223
+ // submergence 0..1 over ~0..160m (40->160, user 2026-06-14 'water super shallow+flat'): the color
2224
+ // saturated at 40m so every deeper lake/river read one flat tone; stretch it so depth shows as a
2225
+ // shallow-edge -> deep-center gradient (thin transparent rim, deep dark center).
2226
+ float sub = clamp(vWaterDepth / 160.0, 0.0, 1.0);
2210
2227
  // wave-perturbed water normal (small inland ripple), same tangent frame as the ground.
2211
2228
  highp vec3 wOriginL = floor(camWorld / 1024.0) * 1024.0; // W7: ~6.4e6 m snapped anchor -> highp
2212
2229
  highp vec2 wpL = vec2(dot(vWorld - wOriginL, ux), dot(vWorld - wOriginL, uy)); // W7: highp camera-relative wave coord