mapspinner 0.1.24 → 0.1.26
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 +1 -1
- package/src/gl-render.js +7 -0
- package/src/shaders/terrain.glsl +30 -19
package/package.json
CHANGED
package/src/gl-render.js
CHANGED
|
@@ -291,6 +291,13 @@ export async function initMapspinnerRender(gl, opts = {}) {
|
|
|
291
291
|
// FXC unroll-defeat (2026-06-12 AMD d3d11 fix): runtime octave bound for broadShapeM; the shader
|
|
292
292
|
// guards uOctMax<=0 -> 12, so this set is belt-and-braces. Live dial: window.__octMax.
|
|
293
293
|
gl.uniform1i(loc('uOctMax'), (typeof window!=='undefined' && window.__octMax!=null) ? (window.__octMax|0) : 12);
|
|
294
|
+
gl.uniform1i(loc('uInciseRidgeOcts'), (typeof window!=='undefined' && window.__inciseRidgeOcts!=null) ? (window.__inciseRidgeOcts|0) : 4);
|
|
295
|
+
gl.uniform1i(loc('uBroadLowOcts'), (typeof window!=='undefined' && window.__broadLowOcts!=null) ? (window.__broadLowOcts|0) : 8);
|
|
296
|
+
gl.uniform1i(loc('uPeakOcts'), (typeof window!=='undefined' && window.__peakOcts!=null) ? (window.__peakOcts|0) : 3);
|
|
297
|
+
gl.uniform1i(loc('uVtxBaseOcts'), (typeof window!=='undefined' && window.__vtxBaseOcts!=null) ? (window.__vtxBaseOcts|0) : 6);
|
|
298
|
+
gl.uniform1i(loc('uVtxErodeOcts'), (typeof window!=='undefined' && window.__vtxErodeOcts!=null) ? (window.__vtxErodeOcts|0) : 4);
|
|
299
|
+
gl.uniform1i(loc('uDetailFbmOcts'), (typeof window!=='undefined' && window.__detailFbmOcts!=null) ? (window.__detailFbmOcts|0) : 3);
|
|
300
|
+
gl.uniform1i(loc('uFSDetailOcts'), (typeof window!=='undefined' && window.__fsDetailOcts!=null) ? (window.__fsDetailOcts|0) : 3);
|
|
294
301
|
// FXC fold-defeat (2026-06-12, the rock-on-flat patches): the lit-normal FD step is uniform-fed
|
|
295
302
|
// so d3d11/FXC cannot constant-fold the 150/R offset. Live dial: window.__nrmStepM.
|
|
296
303
|
gl.uniform1f(loc('uNrmStepM'), g('nrmStepM', 150.0));
|
package/src/shaders/terrain.glsl
CHANGED
|
@@ -165,10 +165,22 @@ float lakeCarveM(vec3 dir){ float w; return lakeCarveM(dir, w); }
|
|
|
165
165
|
// differently -> the summed ridged crests run in EVERY direction, not just the x/y/z lattice H/V.
|
|
166
166
|
// The matrix rows are a fixed tilted basis (~no axis alignment); det ~= 1 so it doesn't drift scale.
|
|
167
167
|
const mat3 OCT_ROT = mat3( 0.80, 0.36, -0.48, -0.48, 0.86, -0.18, 0.36, 0.36, 0.86);
|
|
168
|
+
// FXC UNROLL-DEFEAT runtime-bounded loops (2026-06-12): uniform int guards prevent FXC from
|
|
169
|
+
// fully unrolling these loops (which triggers mis-translation on AMD D3D11). Each guard falls
|
|
170
|
+
// back to the original octave count when the uniform is 0 or unset (e.g. probe program).
|
|
171
|
+
uniform int uOctMax; // broadShapeM octave count (12); runtime-bound to defeat FXC unrolling
|
|
172
|
+
uniform int uInciseRidgeOcts; // inciseRidgeField octave count (4); runtime-bound to defeat FXC unrolling
|
|
173
|
+
uniform int uBroadLowOcts; // broadShapeLowM octave count (8); runtime-bound to defeat FXC unrolling
|
|
174
|
+
uniform int uPeakOcts; // broadShapeM peak crest octave count (3); runtime-bound to defeat FXC unrolling
|
|
175
|
+
uniform int uVtxBaseOcts; // vtxDisplace base fBm octave count (6); runtime-bound to defeat FXC unrolling
|
|
176
|
+
uniform int uVtxErodeOcts; // vtxDisplace mountain erosion octave count (4); runtime-bound to defeat FXC unrolling
|
|
177
|
+
uniform int uDetailFbmOcts; // detailFbm octave count (3); runtime-bound to defeat FXC unrolling
|
|
178
|
+
uniform int uFSDetailOcts; // FS detail overlay octave count (3); runtime-bound to defeat FXC unrolling
|
|
168
179
|
float inciseRidgeField(vec3 d, float baseFreq, float freqMul){
|
|
169
180
|
vec3 p = d;
|
|
170
181
|
float freq = baseFreq, amp = 1.0, sum = 0.0, norm = 0.0;
|
|
171
|
-
|
|
182
|
+
int irOcts = (uInciseRidgeOcts > 0) ? uInciseRidgeOcts : 4;
|
|
183
|
+
for (int o = 0; o < irOcts; o++){
|
|
172
184
|
sum += amp * (1.0 - abs(snoise3(p * freq)));
|
|
173
185
|
norm += amp; freq *= freqMul; amp *= 0.5; p = OCT_ROT * p; // rotate domain each octave
|
|
174
186
|
}
|
|
@@ -327,7 +339,8 @@ highp float broadShapeLowM(vec3 dir){ // W7: metres (~13000) + freq (~49152) a
|
|
|
327
339
|
if (hasHpf == 0) return 0.0;
|
|
328
340
|
vec3 d = normalize(dir);
|
|
329
341
|
highp float amp = 6500.0, freq = 3.0, sum = 0.0;
|
|
330
|
-
|
|
342
|
+
int blOcts = (uBroadLowOcts > 0) ? uBroadLowOcts : 8;
|
|
343
|
+
for (int o=0; o<blOcts; o++){ sum += amp * snoise3(d*freq); amp *= (o < 6 ? 0.66 : 0.82); freq *= 2.0; }
|
|
331
344
|
return sum - 900.0;
|
|
332
345
|
}
|
|
333
346
|
// ---- SHARED micro-relief helpers (MOVED to the common preamble, THC-Normal W1, so composeHeight()
|
|
@@ -369,13 +382,6 @@ highp vec2 faceWarp(highp vec2 p){ return defRadius * tan((p / defRadius) * 0.78
|
|
|
369
382
|
// PERLIN-EVERYWHERE lever -- shared by the composeHeight elevation term (VS/PROBE) and the FS albedo
|
|
370
383
|
// overlay, so it must be declared in ALL stages (outside the VS/PROBE guard below).
|
|
371
384
|
uniform float uDetailOverlay; // amplitude lever (user-tuned 6; 0 = off; __detailOverlay)
|
|
372
|
-
// FXC UNROLL-DEFEAT (2026-06-12, 'rocks everywhere + no normals on AMD default Chrome'): ANGLE's
|
|
373
|
-
// D3D11 backend runs FXC, which fully unrolls constant-bound loops and applies aggressive math
|
|
374
|
-
// reordering across the unrolled body -- the long-suspected mis-translation domain (vulkan on the
|
|
375
|
-
// SAME AMD GPU renders correctly; d3d11 does not). A runtime loop bound cannot be unrolled. The
|
|
376
|
-
// uniform is set to 12 by gl-render; the max(...) guard keeps an unset uniform (0) from flattening
|
|
377
|
-
// the planet -- worst case the loop still runs the literal octave count.
|
|
378
|
-
uniform int uOctMax; // broadShapeM octave count (12); runtime-bound to defeat FXC unrolling
|
|
379
385
|
uniform float uNrmStepM; // lit-normal FD step in metres (150); uniform-fed to defeat FXC constant folding
|
|
380
386
|
#if defined(_VERTEX_) || defined(_PROBE_)
|
|
381
387
|
highp float broadShapeM(vec3 dir, float reliefMul, float ridgeMul){ // W7: returns metres (~13000) -> highp
|
|
@@ -447,7 +453,8 @@ highp float broadShapeM(vec3 dir, float reliefMul, float ridgeMul){ // W7: ret
|
|
|
447
453
|
// with the braids, the dark raw-photo far field, and the UDN normal-frame bug all fixed, the
|
|
448
454
|
// original steep terrain stands.
|
|
449
455
|
highp float pf = 200.0; float pa = 1.0, ps = 0.0, pn = 0.0; // W7: pf (~4100) feeds the noise lattice -> highp
|
|
450
|
-
|
|
456
|
+
int pkOcts = (uPeakOcts > 0) ? uPeakOcts : 3;
|
|
457
|
+
for (int o = 0; o < pkOcts; o++) {
|
|
451
458
|
ps += pa * (1.0 - abs(snoise3(d * pf + vec3(3.3, 7.7, 1.1))));
|
|
452
459
|
pn += pa; pa *= 0.65; pf *= 2.13;
|
|
453
460
|
}
|
|
@@ -524,7 +531,8 @@ float vtxDisplace(highp vec2 fp, float tileM, float rugged){ // W7: fp = face-
|
|
|
524
531
|
// A coarse leaf's 16-cell mesh simply under-samples the finest octaves (smooth interpolation, not a step);
|
|
525
532
|
// the amplitude is small (amp0 8m * uHiFreqCut 0.25 * ruggedAmp) so any residual aliasing is minor and
|
|
526
533
|
// far less visible than the per-patch steps it removes. (tileM kept in the signature for callers.)
|
|
527
|
-
|
|
534
|
+
int vbOcts = (uVtxBaseOcts > 0) ? uVtxBaseOcts : 6;
|
|
535
|
+
for (int o=0; o<vbOcts; o++){
|
|
528
536
|
float n = vnoise2(fp / wl); // [-1,1]
|
|
529
537
|
sumF += a * n; // smooth fBm
|
|
530
538
|
float r = 1.0 - abs(n); r *= r; // ridged: sharp crest at n=0
|
|
@@ -543,7 +551,8 @@ float vtxDisplace(highp vec2 fp, float tileM, float rugged){ // W7: fp = face-
|
|
|
543
551
|
float mtnGate = smoothstep(0.55, 1.0, rugged); // ramps in over the mountain belt (rugged ~ elevAmp)
|
|
544
552
|
if (mtnGate > 0.0) {
|
|
545
553
|
float ea = 2.5, ewl = 2880.0, esumF = 0.0, esumR = 0.0; // user 2026-06-09: HALF the erosion elevation (5->2.5m) + 3x WIDER again (960->2880m)
|
|
546
|
-
|
|
554
|
+
int veOcts = (uVtxErodeOcts > 0) ? uVtxErodeOcts : 4;
|
|
555
|
+
for (int o = 0; o < veOcts; o++) {
|
|
547
556
|
float en = vnoise2(fp / ewl);
|
|
548
557
|
esumF += ea * en;
|
|
549
558
|
float er = 1.0 - abs(en); er *= er;
|
|
@@ -561,8 +570,9 @@ float vtxDisplace(highp vec2 fp, float tileM, float rugged){ // W7: fp = face-
|
|
|
561
570
|
// relief variation correlate, reading as one landform). World-dir keyed, seam-safe.
|
|
562
571
|
highp float detailFbm(vec3 dir) {
|
|
563
572
|
float ov = 0.0, oa = 0.0;
|
|
564
|
-
float fq = 150.0, am = 1.0;
|
|
565
|
-
|
|
573
|
+
float fq = 150.0, am = 1.0;
|
|
574
|
+
int dfOcts = (uDetailFbmOcts > 0) ? uDetailFbmOcts : 3;
|
|
575
|
+
for (int o = 0; o < dfOcts; o++) {
|
|
566
576
|
ov += am * snoise3(dir * fq + vec3(float(o) * 7.3));
|
|
567
577
|
oa += am;
|
|
568
578
|
fq *= 5.0; am *= 0.75;
|
|
@@ -628,7 +638,7 @@ highp float composeHeight(vec3 dir0, highp vec2 faceLocal, float tileM){ // W7
|
|
|
628
638
|
// anchorpoints (low reliefMul = flat plains, non-mtn, non-wet, non-cold). Fades to zero
|
|
629
639
|
// by reliefMul ~0.5 so mountains are unaffected.
|
|
630
640
|
float flatGate = max(0.0, 1.0 - reliefMul * 2.0);
|
|
631
|
-
h += snoise3(dir0 *
|
|
641
|
+
h += snoise3(dir0 * 1400.0) * flatGate * uDetailOverlay * 35.0;
|
|
632
642
|
// LAKE CARVE + flat-water plane
|
|
633
643
|
float lakeWetV; float lakeCarveRaw = lakeCarveM(dir0, lakeWetV);
|
|
634
644
|
// uCarveWide=1 widens the carve CLIMATE gates so the gorge/lake/dune depth fades in over a wide
|
|
@@ -1371,7 +1381,8 @@ vec3 terrainAlbedoClimate(float h, float slope, float rockSlope, float temp, flo
|
|
|
1371
1381
|
highp vec3 od = normalize(worldPos);
|
|
1372
1382
|
float ov = 0.0, oa = 0.0;
|
|
1373
1383
|
float fq = 150.0, am = 1.0; // octaves: ~42km / 8.5km / 1.7km features
|
|
1374
|
-
|
|
1384
|
+
int fdOcts = (uFSDetailOcts > 0) ? uFSDetailOcts : 3;
|
|
1385
|
+
for (int o = 0; o < fdOcts; o++) {
|
|
1375
1386
|
float wl = 40000000.0 / fq; // feature wavelength (m) ~ 2*pi*R / fq
|
|
1376
1387
|
float nyq = 1.0 - smoothstep(wl * 0.03, wl * 0.12, pxWorld); // fade before sub-pixel
|
|
1377
1388
|
ov += am * nyq * snoise3(od * fq + vec3(float(o) * 7.3));
|
|
@@ -1860,7 +1871,7 @@ void main() {
|
|
|
1860
1871
|
// no extra sampling, seam-safe, zero FPS cost vs the old single-term version.
|
|
1861
1872
|
float aoAmt = (uAoAmt > 0.0 ? uAoAmt : 1.0);
|
|
1862
1873
|
float gorgeAO = 0.0; // canyon AO decoupled (user 2026-06-10: canyons impose ELEVATION only, no material/AO keying)
|
|
1863
|
-
float slopeAO = smoothstep(0.
|
|
1874
|
+
float slopeAO = smoothstep(0.20, 0.90, slope) * 0.35; // gentle-slope AO reveals midday relief (0.20->0.90 from 0.45->0.95, peak 0.35)
|
|
1864
1875
|
float cliffAO = 1.0 - min(gorgeAO + slopeAO, 0.75) * aoAmt; // cap so faces never go black
|
|
1865
1876
|
// STRONGER NORMAL-DRIVEN SHADING (user 2026-06-03: 'normals arent affecting the lit view properly').
|
|
1866
1877
|
// The lit relief was too subtle (witnessed litON SD 6.4 vs flat 5.9 = only ~8% contrast) because
|
|
@@ -1883,7 +1894,7 @@ void main() {
|
|
|
1883
1894
|
// W5: vShadeAO (per-vertex, from the deleted VS gradient) RECOMPUTED here from the Sobel slope (user
|
|
1884
1895
|
// 2026-06-07 'recompute AO from Sobel'). creaseAO = slope*0.45 (steep landform -> valley/crease
|
|
1885
1896
|
// occlusion); microAO from the fine per-pixel gslope. uVertexAO lever + the 0.45 floor preserved.
|
|
1886
|
-
float fsShadeAO = clamp(1.0 - (slope * 0.
|
|
1897
|
+
float fsShadeAO = clamp(1.0 - (slope * 0.55 + gslope * 0.40) * uVertexAO, 0.50, 1.0);
|
|
1887
1898
|
// FADE-IN FIX (user 'a layer fades in at close distance'): vAO was mix(1.0, fsShadeAO, nearFade) where
|
|
1888
1899
|
// nearFade rises 0->1 as pxWorld shrinks 180->8m on approach -> the Sobel crease-AO darkening animated
|
|
1889
1900
|
// IN as the camera neared = the visible 'layer fading in'. fsShadeAO is a per-pixel SOBEL-slope quantity
|
|
@@ -2056,7 +2067,7 @@ void main() {
|
|
|
2056
2067
|
// unaffected because the fill is weighted by (1-dayShade). Raised from the old earthshine 0.012/0.018/
|
|
2057
2068
|
// 0.032 (still read as black) to a clearly-visible dim blue so framed night terrain stays legible.
|
|
2058
2069
|
vec3 nightFill = vec3(0.06, 0.075, 0.11) * uNightLights;
|
|
2059
|
-
vec3 color2 = (color * dayShade + nightFill * (1.0 - dayShade))
|
|
2070
|
+
vec3 color2 = (color * dayShade + nightFill * (1.0 - dayShade));
|
|
2060
2071
|
// HDR -> SDR: ACES tonemap. Exposure 1.7 -> 1.25 so the N.sun + dayShade gradient SPREADS across the
|
|
2061
2072
|
// tonemap's linear range instead of clipping flat to the bright shoulder (the orbit-flatness root).
|
|
2062
2073
|
vec3 c = color2 * uExposure; // exposure 1.25->uExposure(1.0): stop the bright ACES-shoulder wash
|