mapspinner 0.1.58 → 0.1.60

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.58",
3
+ "version": "0.1.60",
4
4
  "description": "WebGL2 Earth-scale terrain rendering SDK for interactive globe applications",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -1790,14 +1790,13 @@ void main() {
1790
1790
  // BEACH sand gate tied to uBeachTopM (so the sand TEXTURE scales with the wide beach, not a
1791
1791
  // hardcoded 80m strip) + the shared warp on its LAND edge so the beach->grass line is irregular.
1792
1792
  // FINE BREAK on the grass->sand line (user 2026-06-14 'still a hard straight grass-sand line up
1793
- // close ... it must gain detail'): warpN breaks it at the km scale; add a high-freq (~80-200m)
1794
- // octave so the line stays irregular/fingered when you walk right up to it instead of going
1795
- // straight. Faded in WITH the close-up detail (detailFade-like, via pxWorld) so it never speckles
1796
- // at distance where the macro band is smooth.
1797
- float closeBreak = (1.0 - smoothstep(2.0, 40.0, pxWorld));
1798
- float beachFine = (snoise3(bwDir * 42000.0) + 0.5 * snoise3(bwDir * 95000.0)) * uBeachTopM * 0.45 * closeBreak;
1799
- float beachW = warpN * uBeachTopM * 0.30 + beachFine; // warp amplitude scales with the beach band height
1800
- float beach = (1.0 - smoothstep(uBeachTopM * 0.12 + beachW, uBeachTopM + beachW, vH))
1793
+ // close ... it must gain detail'): warpN positions the band irregularly at the km scale; the
1794
+ // FINE break of the grass->sand line is now the texture DISPLACEMENT height-blend (bSharp below),
1795
+ // NOT a fractal (user 2026-06-14: 'looking like a fractal, use the materials displacement'). Widen
1796
+ // the gate transition band so sand+grass overlap over a broad elevation span -> bSharp picks the
1797
+ // local winner by texture relief -> fingered shoreline that follows the actual texture bumps.
1798
+ float beachW = warpN * uBeachTopM * 0.30; // warp amplitude scales with the beach band height
1799
+ float beach = (1.0 - smoothstep(uBeachTopM * 0.10 + beachW, uBeachTopM * 1.15 + beachW, vH))
1801
1800
  * (1.0 - smoothstep(0.15, 0.42, slope));
1802
1801
  // SAND BLEED (2026-06-13): patchy sand spills above the main beach line, modulated by VS
1803
1802
  // warp noise so the edge reads as wind-blown pockets, not a strict elevation cut. At peak it
@@ -1873,56 +1872,46 @@ void main() {
1873
1872
  // samples through this shared wt, so the warp cannot layer or double-apply.
1874
1873
  wt += vTexWarp * uTexWarp;
1875
1874
  vec3 tw = abs(n); tw = tw * tw; tw /= (tw.x + tw.y + tw.z + 1e-4);
1876
- vec4 albA = surfTriTap(uSurfAlb, wt, tw, lA);
1877
- vec3 nrmA = surfTriNrm(uSurfNrm, wt, tw, lA, n);
1878
- float bAB = clamp(wA / max(wA + wB, 1e-4), 0.0, 1.0);
1879
- vec4 texAlb = albA; vec3 texNrm = nrmA;
1880
- if (wB > 0.02) { // second layer only where a real transition exists (saves 6 taps elsewhere)
1881
- vec4 albB = surfTriTap(uSurfAlb, wt, tw, lB);
1882
- vec3 nrmB = surfTriNrm(uSurfNrm, wt, tw, lB, n);
1883
- // displacement-sharpened transition -- WEIGHT-DOMINANT (user 2026-06-10 'large patches
1884
- // of rock texture in mountains, not slope-keyed'): the old (hA-hB)*4 let the texture's
1885
- // 2.4km displacement features decide the material outright wherever the gate weights sat
1886
- // mid-range, so whole displacement blobs flipped to rock. The slope/snow/climate weight
1887
- // now dominates (x3) and displacement only crisps the edge (x0.8) within the true
1888
- // transition band -- material placement is the gates', texture only shapes the seam.
1889
- // displacement term 0.8 -> 0.3 (user 2026-06-11 'still see bowls of rock texture'):
1890
- // 0.8 still let the displacement photo's bowl-shaped blobs flip whole patches to rock
1891
- // inside the transition band; 0.3 only feathers the seam edge.
1892
- // SOFTENED (2026-06-13): transition sharpening reduced 3->1 so grass/rock/sand/snow
1893
- // boundaries hold a natural blend band instead of a hard die-cut line. The 1.0 slope
1894
- // still prefers the dominant layer but leaves a visible transition zone.
1895
- // DISPLACEMENT-DRIVEN GRADIENT for ALL material pairs (user 2026-06-14 'all textures use the
1896
- // displacement to mix the gradient'): height-blend the top-2 layers by their displacement so
1897
- // every boundary (grass/rock, grass/sand, rock/snow...) follows the texture RELIEF = irregular,
1898
- // not a straight gate line. The displacement weight ramps UP close (0.3 -> 1.3 by the deck)
1899
- // where the hard lines show, and stays low far off so the 2.4km photo's bowl features never
1900
- // flip whole patches to rock (the documented bowl-blob lesson -- that was a DISTANT artifact).
1901
- float dispW = mix(0.3, 1.3, 1.0 - smoothstep(3.0, 60.0, pxWorld));
1902
- float bSharp = clamp((bAB * 2.0 - 1.0) * 1.0 + (albA.a - albB.a) * dispW + 0.5, 0.0, 1.0);
1903
- texAlb = mix(albB, albA, bSharp);
1904
- texNrm = mix(nrmB, nrmA, bSharp);
1905
- }
1906
- // FINE DETAIL OCTAVE (user 2026-06-14 'add one octave at 4x smaller -> world better scaled at
1907
- // 2m'): the base photo tiles at uTexTileM (~2.4km = ~2.3m/texel, smeared at the deck). Sample the
1908
- // SAME dominant material at 4x frequency (~0.6m/texel) and overlay its luminance + normal so
1909
- // close-up the ground gains sub-metre structure. Faded out by ~12m px so it never moires far off.
1910
- // LOW-FREQ = NORMALS ONLY, HIGH-FREQ = TEXTURE + STRONG NORMALS (user 2026-06-14): flatten the
1911
- // base (2.4km) albedo to its luminance so the MACRO biome color carries the chroma -- the base
1912
- // octave contributes only its NORMAL (relief), not color blotches. The 4x detail octave then
1913
- // provides the albedo STRUCTURE + a strong normal.
1914
- texAlb.rgb = vec3(dot(texAlb.rgb, vec3(0.299, 0.587, 0.114))); // low-freq: normals only (albedo -> flat luma)
1875
+ const vec3 LUMA = vec3(0.299, 0.587, 0.114);
1915
1876
  float detailFade = (1.0 - smoothstep(1.0, 12.0, pxWorld));
1877
+ float bAB = clamp(wA / max(wA + wB, 1e-4), 0.0, 1.0);
1878
+ // PER-LAYER material = base octave (NORMALS ONLY -> albedo flattened to luma, macro color carries
1879
+ // chroma) + the 4x DETAIL octave (albedo STRUCTURE + strong normal) + a per-layer DISPLACEMENT
1880
+ // (coarse base, refined by the 4x near the deck). Each top-2 layer is built FULLY here, then the
1881
+ // two are HEIGHT-BLENDED (below) -- so the detail never flips at the boundary (the 'hard lines up
1882
+ // close ever since the higher octave' bug = the detail used the dominant layer only).
1883
+ vec4 albA = surfTriTap(uSurfAlb, wt, tw, lA);
1884
+ vec3 cA = vec3(dot(albA.rgb, LUMA)); vec3 nA = surfTriNrm(uSurfNrm, wt, tw, lA, n); float dispA = albA.a;
1916
1885
  if (detailFade > 0.01) {
1917
1886
  vec4 dA = surfTriTap(uSurfAlb, wt * 4.0, tw, lA);
1918
- float dl = dot(dA.rgb, vec3(0.299, 0.587, 0.114));
1919
- float bl = dot(texAlb.rgb, vec3(0.299, 0.587, 0.114));
1920
- texAlb.rgb *= mix(1.0, clamp(dl / max(bl, 0.04), 0.35, 2.4), detailFade * 1.3); // HIGH-FREQ albedo structure (heavier)
1921
- // detail NORMAL: surfTriNrm returns a PERTURBATION vector (texNrm feeds texDn = texNrm*uTexNrmK*k,
1922
- // NOT a unit normal), so the detail is simply ADDED in the same space -- no normalize (that
1923
- // scrambled magnitudes = the 'weird highest-octave normals').
1924
- vec3 dN = surfTriNrm(uSurfNrm, wt * 4.0, tw, lA, n);
1925
- texNrm = texNrm + dN * detailFade * 1.4; // BIGGER normal effect for the high-freq octave (user 2026-06-14)
1887
+ cA *= mix(1.0, clamp(dot(dA.rgb, LUMA) / max(dot(cA, LUMA), 0.04), 0.35, 2.4), detailFade * 1.3);
1888
+ nA += surfTriNrm(uSurfNrm, wt * 4.0, tw, lA, n) * detailFade * 1.4;
1889
+ dispA = mix(dispA, dA.a, detailFade); // fine displacement poke near the deck
1890
+ }
1891
+ vec4 texAlb = vec4(cA, dispA); vec3 texNrm = nA;
1892
+ if (wB > 0.02) { // second layer only where a real transition exists
1893
+ vec4 albB = surfTriTap(uSurfAlb, wt, tw, lB);
1894
+ vec3 cB = vec3(dot(albB.rgb, LUMA)); vec3 nB = surfTriNrm(uSurfNrm, wt, tw, lB, n); float dispB = albB.a;
1895
+ if (detailFade > 0.01) {
1896
+ vec4 dB = surfTriTap(uSurfAlb, wt * 4.0, tw, lB);
1897
+ cB *= mix(1.0, clamp(dot(dB.rgb, LUMA) / max(dot(cB, LUMA), 0.04), 0.35, 2.4), detailFade * 1.3);
1898
+ nB += surfTriNrm(uSurfNrm, wt * 4.0, tw, lB, n) * detailFade * 1.4;
1899
+ dispB = mix(dispB, dB.a, detailFade);
1900
+ }
1901
+ // HEIGHT-BLEND POKE-THROUGH (user 2026-06-14 'each texture's higher areas should poke through
1902
+ // the other, offset by the ramp'): each layer's height = its DISPLACEMENT + a weight-ramp
1903
+ // offset (so the gate still positions the boundary). The higher height wins, blended over a
1904
+ // soft WIDTH so the loser's high bumps still poke through near the ramp -> interlocking
1905
+ // fingers, never a hard line. This is the ONE blend for ALL pairs (slope-rock, height-snow,
1906
+ // climate/area-biome, beach). bw widens close-up (where the detail is rich) for a softer mesh.
1907
+ float bw = mix(0.12, 0.30, detailFade);
1908
+ float hA = dispA + (bAB - 0.5) * 1.1;
1909
+ float hB = dispB + (0.5 - bAB) * 1.1;
1910
+ float mh = max(hA, hB) - bw;
1911
+ float waH = max(hA - mh, 0.0), wbH = max(hB - mh, 0.0);
1912
+ float bSharp = waH / max(waH + wbH, 1e-4);
1913
+ texAlb = vec4(mix(cB, cA, bSharp), mix(dispB, dispA, bSharp));
1914
+ texNrm = mix(nB, nA, bSharp);
1926
1915
  }
1927
1916
  float k = uTexMix * texFarFade;
1928
1917
  // macro-tinted detail (user 2026-06-10 'the textured patch must be tinted to the same shade
@@ -1951,7 +1940,10 @@ void main() {
1951
1940
  // ground reads unambiguously as its material (grass green / sand tan / rock grey) without the
1952
1941
  // raw photo's darkness ('terrain gets darker' lesson) and without the macro's biome-brown
1953
1942
  // repaint ('neither grass nor sand' defect). Layer-mean normalized like `detail`.
1954
- vec3 texIdent = texC * (dot(albedo, vec3(0.2126, 0.7152, 0.0722)) / max(texL, 0.02));
1943
+ // low-freq albedo is now NORMALS-ONLY (texC is luma structure), so the old raw-photo 'identity'
1944
+ // hue is gone; texIdent == detail = MACRO color * structure (keeps rock its macro tan-grey, not
1945
+ // grey). The 4x detail carries the fine structure for every material.
1946
+ vec3 texIdent = texC * (albedo / max(texL, 0.02));
1955
1947
  albedo = clamp(mix(albedo, mix(detail, texIdent, photoF), k), 0.0, 1.0);
1956
1948
  // displacement-normal relief: WORLD-SPACE UDN perturbation from surfTriNrm (each projection
1957
1949
  // plane's tangent axes, not the radial frame). Amplitude capped low (scramble lesson d262b5e);