procedural-terrains 2.0.0 → 2.0.1
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/dist/{FiniteTerrain-B34WMz5S.js → FiniteTerrain-B5_3y6xX.js} +3 -3
- package/dist/{FiniteTerrain-B34WMz5S.js.map → FiniteTerrain-B5_3y6xX.js.map} +1 -1
- package/dist/{InfiniteTerrain-SgoJz3qJ.js → InfiniteTerrain-jeCy6RED.js} +5 -5
- package/dist/{InfiniteTerrain-SgoJz3qJ.js.map → InfiniteTerrain-jeCy6RED.js.map} +1 -1
- package/dist/{MiniTerrain-Blt0H1S0.js → MiniTerrain-Bb5VYkZU.js} +8 -8
- package/dist/MiniTerrain-Bb5VYkZU.js.map +1 -0
- package/dist/{PlanetMaterial-B1_ZPlx5.js → PlanetMaterial-Cs-_x6vr.js} +4 -4
- package/dist/{PlanetMaterial-B1_ZPlx5.js.map → PlanetMaterial-Cs-_x6vr.js.map} +1 -1
- package/dist/{PlanetTerrain-DCvxS1Q8.js → PlanetTerrain-Bsfx7YA6.js} +5 -5
- package/dist/{PlanetTerrain-DCvxS1Q8.js.map → PlanetTerrain-Bsfx7YA6.js.map} +1 -1
- package/dist/{RevisionScope-J__6V9I_.js → RevisionScope-Dl4yjj-0.js} +2 -2
- package/dist/{RevisionScope-J__6V9I_.js.map → RevisionScope-Dl4yjj-0.js.map} +1 -1
- package/dist/{TerrainClouds-BuKvwnWw.js → TerrainClouds-DV6ny7P1.js} +31 -19
- package/dist/TerrainClouds-DV6ny7P1.js.map +1 -0
- package/dist/{TerrainHeightCache-Dsde6EDL.js → TerrainHeightCache-DIZxi9jz.js} +2 -2
- package/dist/{TerrainHeightCache-Dsde6EDL.js.map → TerrainHeightCache-DIZxi9jz.js.map} +1 -1
- package/dist/{TerrainParameters-A3fcNJTR.js → TerrainParameters-DMCjnnxz.js} +10 -8
- package/dist/TerrainParameters-DMCjnnxz.js.map +1 -0
- package/dist/{TerrainWater-Cil7waG3.js → TerrainWater-CX4XdwA0.js} +17 -11
- package/dist/TerrainWater-CX4XdwA0.js.map +1 -0
- package/dist/{WaterMaterial-BUsAp0SS.js → WaterMaterial-C9h1xm9E.js} +7 -5
- package/dist/WaterMaterial-C9h1xm9E.js.map +1 -0
- package/dist/{biomeGLSL-CIkhxIlH.js → biomeGLSL-DWGDDBqT.js} +6 -3
- package/dist/{biomeGLSL-CIkhxIlH.js.map → biomeGLSL-DWGDDBqT.js.map} +1 -1
- package/dist/clouds.js +1 -1
- package/dist/documents.js +6 -6
- package/dist/export.js +2 -2
- package/dist/index.js +1 -1
- package/dist/infinite.js +1 -1
- package/dist/mini.js +1 -1
- package/dist/planet.js +1 -1
- package/dist/{planetGLSL-2xas0f3o.js → planetGLSL-D9Zy2IAw.js} +2 -2
- package/dist/{planetGLSL-2xas0f3o.js.map → planetGLSL-D9Zy2IAw.js.map} +1 -1
- package/dist/real-world.js +1 -1
- package/dist/render.js +1 -1
- package/dist/viewer.js +1 -1
- package/dist/water.js +1 -1
- package/package.json +1 -1
- package/dist/MiniTerrain-Blt0H1S0.js.map +0 -1
- package/dist/TerrainClouds-BuKvwnWw.js.map +0 -1
- package/dist/TerrainParameters-A3fcNJTR.js.map +0 -1
- package/dist/TerrainWater-Cil7waG3.js.map +0 -1
- package/dist/WaterMaterial-BUsAp0SS.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerrainClouds-DV6ny7P1.js","sources":["../../../src/engine/sky/CloudSlabShader.js","../../../src/engine/sky/cloudFieldCPU.js","../../../src/engine/sky/CloudLowResPass.js","../../../src/engine/sky/CloudLightingState.js","../../../src/engine/sky/CloudOccupancyPass.js","../../../src/engine/sky/CloudSlabLayer.js","../../../src/engine/sky/InfiniteCloudLayer.js","../../../src/engine/sky/CloudVolumeShader.js","../../../src/engine/sky/PlanetCloudLayer.js","../../../src/engine/sky/realistic/RealisticCloudResources.js","../../../src/engine/sky/realistic/RealisticCloudLayers.js","../../../src/runtime/effects/TerrainClouds.js"],"sourcesContent":["import * as THREE from 'three';\nimport { CLOUD_NOISE_GLSL, CLOUD_FIELD_GLSL, CLOUD_SLAB_GLSL } from './cloudGLSL.js';\n\n// ============================================================================\n// CloudSlabShader: the flat-mode (studio board) analog of CloudVolumeShader.\n// Instead of a spherical shell it raymarches a horizontal slab between two\n// world-Y planes (uCloudBottom..uCloudTop), fading out past a horizontal radius\n// so the clouds sit over the board like a diorama layer.\n//\n// Shares the noise + cloud-field GLSL and all cloud uniforms with the spherical\n// shader — only the geometry of the marched volume differs. Drawn on a large\n// horizontal plane after opaque terrain has populated the depth buffer; the slab\n// segment is found analytically from the ray vs the two Y planes (clamped to\n// uCloudFar to bound the horizon). Opaque scene depth from a prepass clamps the\n// marched segment, so hidden clouds exit before doing expensive samples.\n//\n// Step counts are compile-time #defines (statically bounded loops) exactly as\n// in the spherical shader, to keep the ANGLE/D3D11 compiler happy.\n// ============================================================================\n\nconst VERTEX = /* glsl */ `\nvarying vec3 vWorldPos;\nvoid main() {\n vec4 wp = modelMatrix * vec4(position, 1.0);\n vWorldPos = wp.xyz;\n gl_Position = projectionMatrix * viewMatrix * wp;\n}\n`;\n\nconst FRAGMENT = /* glsl */ `\nprecision highp float;\n\n${CLOUD_NOISE_GLSL}\n${CLOUD_FIELD_GLSL}\n${CLOUD_SLAB_GLSL}\n\nvarying vec3 vWorldPos;\n\nuniform sampler2D tSceneDepth;\nuniform vec2 uDepthResolution;\nuniform mat4 uProjectionMatrixInverse;\nuniform mat4 uViewMatrixInverse;\nuniform float uDepthBias;\nuniform float uUseDepth;\n\n// Planar occupancy grid (XZ): a small map (built on the CPU from the coverage\n// field, conservative + dilated) telling whether a column over the board holds\n// any cloud. A cheap texture lookup lets the march skip the expensive density\n// over empty columns and reject empty rays — the freed budget also cuts grain.\nuniform sampler2D uCloudOccupancy;\nuniform float uUseOccupancy;\nuniform vec2 uOccCenter; // board-center XZ\nuniform float uOccExtent; // half-size of the mapped square (= fade radius)\n\nfloat occAt(vec3 P) {\n vec2 uv = (P.xz - uOccCenter) / (2.0 * max(uOccExtent, 1.0)) + 0.5;\n return textureLod(uCloudOccupancy, uv, 0.0).r;\n}\n\nvec3 reconstructWorldPosition(vec2 uv, float depth) {\n vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 view = uProjectionMatrixInverse * clip;\n view.xyz /= view.w;\n return (uViewMatrixInverse * vec4(view.xyz, 1.0)).xyz;\n}\n\nvec3 cl_resolveLighting(vec3 P, vec3 rd, float light, float cloudHeight) {\n vec3 legacyAmbient = uCloudShadowColor * uCloudShadowStrength;\n vec3 legacy = mix(legacyAmbient, uCloudColor, light)\n * (0.55 + 0.45 * uCloudScattering * light);\n\n float height01 = clamp(cloudHeight, 0.0, 1.0);\n float sunVisibility = cl_sunVisibility(P, height01);\n float shadowAmount = (1.0 - light) * uCloudShadowStrength;\n float shadowedSun = mix(1.0, light, uCloudShadowStrength);\n vec3 shadowTint = mix(vec3(1.0), uCloudShadowColor, shadowAmount);\n\n vec3 skyAmbient = mix(uCloudAmbientBottom, uCloudAmbientTop, height01);\n skyAmbient += uCloudGroundBounce * (1.0 - height01);\n\n float sunView = max(dot(rd, normalize(uCloudSunDir)), 0.0);\n float silverLining = pow(sunView, 12.0) * uCloudSilverLining * sunVisibility;\n float phase = 0.65 + 0.35 * uCloudScattering + silverLining;\n\n vec3 direct = uCloudDirectLight * sunVisibility * shadowedSun\n * uCloudSunResponse * phase;\n vec3 atmospheric = uCloudColor\n * (skyAmbient * uCloudAmbientResponse + direct)\n * shadowTint;\n\n return mix(legacy, atmospheric, clamp(uCloudAtmosphereInfluence, 0.0, 1.0));\n}\n\nvoid main() {\n vec3 ro = cameraPosition;\n vec3 rd = normalize(vWorldPos - cameraPosition);\n\n // intersect the ray with the two horizontal slab planes\n float t0, t1;\n if (abs(rd.y) < 1e-5) {\n // near-horizontal ray: only inside the slab if the camera already is\n if (ro.y <= uCloudBottom || ro.y >= uCloudTop) discard;\n t0 = 0.0;\n t1 = uCloudFar;\n } else {\n float ta = (uCloudBottom - ro.y) / rd.y;\n float tb = (uCloudTop - ro.y) / rd.y;\n t0 = max(min(ta, tb), 0.0);\n t1 = min(max(ta, tb), uCloudFar);\n }\n if (t1 <= t0) discard;\n\n // clamp the segment to the cloud disc (radius uCloudRadius around the board\n // center): beyond it the radial fade is zero, so this both skips wasted\n // marching AND keeps the step fine on grazing rays (much less stipple).\n {\n vec2 oc = ro.xz - uCloudCenter.xz;\n vec2 dc = rd.xz;\n float A = dot(dc, dc);\n if (A > 1e-8) {\n float B = dot(oc, dc);\n float C = dot(oc, oc) - uCloudRadius * uCloudRadius;\n float disc = B * B - A * C;\n if (disc < 0.0) discard; // ray never crosses the disc\n float sq = sqrt(disc);\n t0 = max(t0, (-B - sq) / A);\n t1 = min(t1, (-B + sq) / A);\n if (t1 <= t0) discard;\n } else {\n // vertical ray: only inside the disc if the camera column is within it\n if (dot(oc, oc) > uCloudRadius * uCloudRadius) discard;\n }\n }\n\n // Preserve the unclipped slab interval as the global sampling domain.\n // Terrain depth may shorten the visible part of the ray, but must not\n // redistribute samples per pixel: doing so makes the cloud field jump at\n // terrain triangle/chunk boundaries and creates geometric-looking holes.\n float slabStart = t0;\n float slabEnd = t1;\n\n vec2 depthUv = gl_FragCoord.xy / max(uDepthResolution, vec2(1.0));\n if (uUseDepth > 0.5 && depthUv.x >= 0.0 && depthUv.x <= 1.0 &&\n depthUv.y >= 0.0 && depthUv.y <= 1.0) {\n float sceneDepth = texture2D(tSceneDepth, depthUv).x;\n if (sceneDepth < 0.99999) {\n vec3 sceneHit = reconstructWorldPosition(depthUv, sceneDepth);\n float hitT = dot(sceneHit - ro, rd);\n if (hitT > 0.0 && hitT < t1) {\n t1 = hitT - uDepthBias;\n if (t1 <= t0) discard;\n }\n }\n }\n\n // distance LOD: fewer effective steps when far (uCloudStepScale<1); loop\n // bound stays CLOUD_STEPS (static for ANGLE), extra iterations no-op.\n // ADAPTIVE step spacing (see CloudVolumeShader): constant world-space sample\n // spacing whatever the view angle, so the grazing/side view no longer stretches\n // the samples into a hatch. Vertical crossings use few steps; long grazing rays\n // use the full budget, still fully covered (stepLen ≤ seg/CLOUD_STEPS).\n float slabSpan = max(uCloudTop - uCloudBottom, 1.0);\n float targetStep = slabSpan / float(CLOUD_STEPS) / clamp(uCloudStepScale, 0.05, 1.0);\n float segLen = slabEnd - slabStart;\n int effSteps = int(clamp(segLen / targetStep, 8.0, float(CLOUD_STEPS)) + 0.5);\n\n float transmittance = 1.0;\n vec3 scatter = vec3(0.0);\n\n // Integrate every interval exactly once, including the clipped last one.\n // Symmetric density taps avoid screen-space stripes and stipple.\n //\n // Occupancy still gates every expensive density evaluation, but it never\n // rejects or leaps over a whole ray. Sparse three-point rejection and coarse\n // strides can miss a thin occupied cell on oblique views, producing hard\n // holes aligned to the occupancy grid.\n for (int i = 0; i < CLOUD_STEPS + uLoopGuard; i++) {\n float sampleIndex = float(i);\n if (sampleIndex < float(effSteps) && transmittance > 0.01) {\n float ta = sampleIndex / float(effSteps);\n float tb = (sampleIndex + 1.0) / float(effSteps);\n float intervalStart = slabStart + segLen * ta;\n float stepLength = min(segLen * (tb - ta), max(t1 - intervalStart, 0.0));\n float t = intervalStart + stepLength * 0.5;\n if (t < t1 && stepLength > 0.0) {\n vec3 P = ro + rd * t;\n float occ = uUseOccupancy > 0.5 ? occAt(P) : 1.0;\n if (occ >= 0.5) {\n // Symmetric quadrature resolves the interval without screen-space\n // random offsets, which made dense side views look like stipple.\n vec3 offset = rd * (stepLength * 0.288675);\n vec2 sampleData = cloudSample(P - offset);\n float dens = 0.5 * (sampleData.x + cloudDensity(P + offset));\n if (dens > 0.001) {\n float light = uCloudSelfShadow > 0.5 ? cl_lightTransmittance(P) : 1.0;\n vec3 lit = cl_resolveLighting(P, rd, light, sampleData.y);\n float dT = exp(-dens * stepLength * uCloudExtinction);\n scatter += transmittance * (1.0 - dT) * lit;\n transmittance *= dT;\n }\n }\n }\n }\n }\n\n float alpha = 1.0 - transmittance;\n if (alpha < 0.004) discard;\n\n vec3 col = scatter / max(alpha, 1e-4);\n col = pow(clamp(col, 0.0, 1.0), vec3(1.0 / 2.2));\n gl_FragColor = vec4(col, alpha);\n}\n`;\n\nexport function createCloudSlabMaterial(steps = 24, lightSteps = 6, octaves = 5, detailOctaves = 4, useErosion = true, lightMode = 0) {\n return new THREE.ShaderMaterial({\n uniforms: {\n uCloudBottom: { value: 900 },\n uCloudTop: { value: 1520 },\n uCloudRadius: { value: 1500 },\n uCloudFar: { value: 9000 },\n uCloudCenter: { value: new THREE.Vector3() },\n uCloudCoverage: { value: 0.5 },\n uCloudSoftness: { value: 0.16 },\n uCloudScale: { value: 1.0 },\n uCloudDetailScale: { value: 3.0 },\n uCloudDetailStrength: { value: 0.35 },\n uCloudErosionScale: { value: 6.0 },\n uCloudErosionStrength: { value: 0.30 },\n uCloudExtinction: { value: 0.013 },\n uCloudLightAbsorption: { value: 3.0 },\n uCloudShadowStrength: { value: 0.6 },\n uCloudScattering: { value: 1.0 },\n uCloudColor: { value: new THREE.Color(1, 1, 1) },\n uCloudShadowColor: { value: new THREE.Color(0.42, 0.47, 0.60) },\n uCloudDirectLight: { value: new THREE.Color(1.0, 0.94, 0.82) },\n uCloudAmbientTop: { value: new THREE.Color(0.18, 0.23, 0.31) },\n uCloudAmbientBottom: { value: new THREE.Color(0.13, 0.16, 0.22) },\n uCloudGroundBounce: { value: new THREE.Color(0.05, 0.04, 0.03) },\n uCloudAtmosphereInfluence: { value: 1.0 },\n uCloudSunResponse: { value: 1.0 },\n uCloudAmbientResponse: { value: 1.0 },\n uCloudSilverLining: { value: 0.25 },\n uCloudWind: { value: new THREE.Vector3() },\n uCloudNoiseOffset: { value: new THREE.Vector3() },\n uCloudVariationOffset: { value: new THREE.Vector3() },\n uCloudNoiseType: { value: 0 },\n uCloudDomainOrigin: { value: new THREE.Vector3() },\n uCloudRotation: { value: 0.0 },\n uCloudTime: { value: 0.0 },\n uCloudSelfShadow: { value: 1.0 },\n uCloudSunDir: { value: new THREE.Vector3(0.4, 0.7, 0.5).normalize() },\n uCloudStepScale: { value: 1.0 },\n uCloudEvolve: { value: 0.03 },\n tSceneDepth: { value: null },\n uDepthResolution: { value: new THREE.Vector2(1, 1) },\n uProjectionMatrixInverse: { value: new THREE.Matrix4() },\n uViewMatrixInverse: { value: new THREE.Matrix4() },\n uDepthBias: { value: 2.0 },\n uUseDepth: { value: 0.0 },\n uCloudOccupancy: { value: null },\n uUseOccupancy: { value: 0.0 },\n uOccCenter: { value: new THREE.Vector2() },\n uOccExtent: { value: 1500 },\n },\n defines: {\n CLOUD_STEPS: Math.max(8, Math.round(steps)),\n CLOUD_LIGHT_STEPS: Math.max(1, Math.round(lightSteps)),\n CLOUD_OCTAVES: Math.max(1, Math.round(octaves)),\n CLOUD_DETAIL_OCTAVES: Math.max(0, Math.round(detailOctaves)),\n CLOUD_USE_EROSION: useErosion ? 1 : 0,\n CLOUD_LIGHT_MODE: lightMode ? 1 : 0,\n },\n vertexShader: VERTEX,\n fragmentShader: FRAGMENT,\n transparent: true,\n depthWrite: false,\n depthTest: false, // occlusion is handled by tSceneDepth per pixel\n // BackSide on a box that ENCLOSES the slab volume: the back faces always\n // project over the volume's screen footprint from inside, outside, above or\n // below (mirrors the planet shell's BackSide sphere). A flat plane left the\n // clouds clipped at grazing angles from below, where horizon-bound rays hit\n // the finite plane beyond its extent and produced no fragment.\n side: THREE.BackSide,\n });\n}\n","// ============================================================================\n// cloudFieldCPU: a compact CPU mirror of the cloud coverage field used ONLY for\n// empty-space culling of cloud chunks (deciding \"could this sector contain any\n// cloud right now?\"). It ports the base-FBM path of cloudShape() from\n// cloudGLSL.js (the `soft` variant — a conservative proxy for all variants;\n// detail/erosion are intentionally ignored so we never cull a chunk the GPU\n// would actually fill). It is NOT used for rendering — the GPU shader stays the\n// source of truth for the visible density.\n// ============================================================================\n\nconst fract = (x) => x - Math.floor(x);\n\n// cl_hash13 (Dave Hoskins) ported from cloudGLSL.js\nfunction hash13(x, y, z) {\n let px = fract(x * 0.1031), py = fract(y * 0.1031), pz = fract(z * 0.1031);\n // dot(p3, p3.zyx + 31.32)\n const s = px * (pz + 31.32) + py * (py + 31.32) + pz * (px + 31.32);\n px += s; py += s; pz += s;\n return fract((px + py) * pz);\n}\n\n// quintic trilinear value noise (cl_vnoise)\nfunction vnoise(x, y, z) {\n const ix = Math.floor(x), iy = Math.floor(y), iz = Math.floor(z);\n const fx = x - ix, fy = y - iy, fz = z - iz;\n const ux = fx * fx * fx * (fx * (fx * 6 - 15) + 10);\n const uy = fy * fy * fy * (fy * (fy * 6 - 15) + 10);\n const uz = fz * fz * fz * (fz * (fz * 6 - 15) + 10);\n const n000 = hash13(ix, iy, iz);\n const n100 = hash13(ix + 1, iy, iz);\n const n010 = hash13(ix, iy + 1, iz);\n const n110 = hash13(ix + 1, iy + 1, iz);\n const n001 = hash13(ix, iy, iz + 1);\n const n101 = hash13(ix + 1, iy, iz + 1);\n const n011 = hash13(ix, iy + 1, iz + 1);\n const n111 = hash13(ix + 1, iy + 1, iz + 1);\n const mix = (a, b, t) => a + (b - a) * t;\n return mix(\n mix(mix(n000, n100, ux), mix(n010, n110, ux), uy),\n mix(mix(n001, n101, ux), mix(n011, n111, ux), uy),\n uz\n );\n}\n\n// CL_ROT * p (column-major mat3 from cloudGLSL.js), result written back into out\nfunction rotMul(px, py, pz, out) {\n out[0] = -0.80 * py - 0.60 * pz;\n out[1] = 0.80 * px + 0.36 * py - 0.48 * pz;\n out[2] = 0.60 * px - 0.48 * py + 0.64 * pz;\n}\n\n// base FBM value noise (cl_fbm_base) — `octaves` iterations, *2.02 freq, CL_ROT\nfunction fbmBase(px, py, pz, octaves) {\n let amp = 0.5, sum = 0, norm = 0;\n let x = px, y = py, z = pz;\n for (let i = 0; i < octaves; i++) {\n sum += amp * vnoise(x, y, z);\n norm += amp;\n amp *= 0.5;\n const nx = -0.80 * y - 0.60 * z;\n const ny = 0.80 * x + 0.36 * y - 0.48 * z;\n const nz = 0.60 * x - 0.48 * y + 0.64 * z;\n x = nx * 2.02; y = ny * 2.02; z = nz * 2.02;\n }\n return sum / Math.max(norm, 1e-4);\n}\n\nconst smoothstep = (e0, e1, x) => {\n const t = Math.min(1, Math.max(0, (x - e0) / Math.max(e1 - e0, 1e-6)));\n return t * t * (3 - 2 * t);\n};\n\n/**\n * Coverage fraction in [0,1] at a planet-local world point, mirroring the base\n * path of cloudShape() (domain rotation about Y + wind drift + base FBM + the\n * coverage threshold). Conservative: omits the detail/erosion terms.\n * @param {number} x @param {number} y @param {number} z world point (planet at origin)\n * @param {object} f field params (already in shader units):\n * scale, windX, windY, windZ, time, rotation, coverage, softness, octaves\n */\nexport function cloudCoverageAt(x, y, z, f) {\n // cl_domain: rotate about Y by f.rotation\n const c = f.rotationCos ?? Math.cos(f.rotation);\n const s = f.rotationSin ?? Math.sin(f.rotation);\n const qx = c * x + s * z;\n const qy = y;\n const qz = -s * x + c * z;\n // baseP = q * scale + wind * time + evolution scroll (must match cloudShape so\n // the occupancy map tracks the forming/dissipating field and never clips it)\n const dx = f.windX * f.time;\n const dy = f.windY * f.time + (f.evolve || 0) * f.time;\n const dz = f.windZ * f.time;\n // `boost` is an UPPER-BOUND margin (≈ detail strength + softness): the GPU adds\n // detail noise on top of the base FBM, so a column that is empty in the base\n // can still grow cloud from detail. Adding the boost before thresholding makes\n // the occupancy a conservative over-estimate that never skips real cloud.\n let px = qx * f.scale + dx + (f.offsetX || 0);\n let py = qy * f.scale + dy + (f.offsetY || 0);\n let pz = qz * f.scale + dz + (f.offsetZ || 0);\n if (f.noiseType === 2) { px *= 0.55; py *= 1.7; pz *= 1.4; }\n let base = fbmBase(px, py, pz, f.octaves);\n if (f.noiseType === 2) {\n const fibers = vnoise(px * 0.65 + 19.7, py * 2.4 + 19.7, pz * 1.6 + 19.7);\n base += 0.04 - 0.08 * smoothstep(0.25, 0.75, fibers);\n } else if (f.noiseType === 1) {\n const billows = 0.67 - Math.abs(vnoise(px * 1.5 + 13.7, py * 1.5 + 13.7, pz * 1.5 + 13.7) - 0.5) * 1.4;\n base = base * 0.35 + billows * 0.65;\n }\n const n = base + (f.boost || 0);\n const threshold = 1.0 - f.coverage;\n return smoothstep(threshold, threshold + f.softness, n);\n}\n\n// Octahedral decode: texel uv in [-1,1]² → unit direction.\nfunction octDecode(u, v, out) {\n let x = u, y = v;\n const z = 1 - Math.abs(x) - Math.abs(y);\n if (z < 0) {\n const ox = x;\n x = (1 - Math.abs(y)) * (ox >= 0 ? 1 : -1);\n y = (1 - Math.abs(ox)) * (y >= 0 ? 1 : -1);\n }\n const len = Math.hypot(x, y, z) || 1;\n out[0] = x / len; out[1] = y / len; out[2] = z / len;\n}\n\n/**\n * Build a directional occupancy map (octahedral, `size`×`size`, R8) marking which\n * directions hold any cloud at mid-shell radius. Conservative: a low coverage\n * threshold + a few dilation passes so the GPU march never skips a column that\n * has (or is about to grow) cloud. Reused as an empty-space-skip acceleration\n * grid by the cloud shader.\n * @param {Uint8Array} out length size*size (reused buffer)\n * @param {number} size\n * @param {number} inner inner shell radius\n * @param {number} outer outer shell radius\n * @param {object} field cloud field params (see cloudCoverageAt)\n * @param {number} [dilate] dilation passes (default 2)\n */\nexport function buildOccupancyOctahedral(out, size, inner, outer, field, dilate = 2, scratch = null) {\n field.rotationCos = Math.cos(field.rotation);\n field.rotationSin = Math.sin(field.rotation);\n const d = [0, 0, 0];\n // sample a few radii up the column (the shape field varies with radius) and\n // take the max so a column with cloud only near the inner/outer edge is kept.\n const radii = [inner + (outer - inner) * 0.2, 0.5 * (inner + outer), outer - (outer - inner) * 0.2];\n for (let j = 0; j < size; j++) {\n for (let i = 0; i < size; i++) {\n const u = ((i + 0.5) / size) * 2 - 1;\n const v = ((j + 0.5) / size) * 2 - 1;\n octDecode(u, v, d);\n let cov = 0;\n for (let r = 0; r < radii.length; r++) {\n const R = radii[r];\n cov = Math.max(cov, cloudCoverageAt(d[0] * R, d[1] * R, d[2] * R, field));\n }\n out[j * size + i] = cov > 0.003 ? 255 : 0;\n }\n }\n return dilateMax(out, size, dilate, scratch);\n}\n\n// 3×3 max dilation, `passes` times, in place (grows the occupied region so\n// edges/wisps and the rebuild lag never clip a real cloud).\nfunction dilateMax(out, size, passes, scratch = null) {\n let src = out;\n let tmp = scratch && scratch.length === out.length ? scratch : new Uint8Array(size * size);\n for (let p = 0; p < passes; p++) {\n for (let j = 0; j < size; j++) {\n for (let i = 0; i < size; i++) {\n let m = 0;\n for (let dj = -1; dj <= 1 && m < 255; dj++) {\n const jj = j + dj; if (jj < 0 || jj >= size) continue;\n for (let di = -1; di <= 1; di++) {\n const ii = i + di; if (ii < 0 || ii >= size) continue;\n if (src[jj * size + ii] > m) m = src[jj * size + ii];\n }\n }\n tmp[j * size + i] = m;\n }\n }\n const swap = src; src = tmp; tmp = swap;\n }\n if (src !== out) out.set(src);\n let occupied = 0;\n for (let i = 0; i < out.length; i++) occupied += out[i] > 0 ? 1 : 0;\n return occupied / Math.max(out.length, 1);\n}\n\n/**\n * Build a planar (XZ) occupancy map for the studio cloud slab: `size`×`size` R8\n * over the square [center ± extent], marking which columns hold any cloud\n * between bottom..top. Conservative (low threshold, 3 Y samples, dilation).\n * @param {Uint8Array} out length size*size (reused buffer)\n * @param {number} size\n * @param {number} cx @param {number} cz board center XZ\n * @param {number} extent half-size of the mapped square (= fade radius)\n * @param {number} bottom @param {number} top slab Y planes\n * @param {object} field cloud field params (see cloudCoverageAt)\n * @param {number} [dilate]\n */\nexport function buildOccupancyPlanar(out, size, cx, cz, extent, bottom, top, field, dilate = 2, scratch = null) {\n field.rotationCos = Math.cos(field.rotation);\n field.rotationSin = Math.sin(field.rotation);\n const ys = [bottom + (top - bottom) * 0.25, 0.5 * (bottom + top), top - (top - bottom) * 0.25];\n for (let j = 0; j < size; j++) {\n const z = cz + (((j + 0.5) / size) * 2 - 1) * extent;\n for (let i = 0; i < size; i++) {\n const x = cx + (((i + 0.5) / size) * 2 - 1) * extent;\n let cov = 0;\n for (let y = 0; y < ys.length; y++) {\n cov = Math.max(cov, cloudCoverageAt(x, ys[y], z, field));\n }\n out[j * size + i] = cov > 0.003 ? 255 : 0;\n }\n }\n return dilateMax(out, size, dilate, scratch);\n}\n","import * as THREE from 'three';\n\n// ============================================================================\n// CloudLowResPass: renders the (expensive, fill-rate-bound) volumetric cloud\n// mesh into a LOW-RESOLUTION offscreen target, then composites it back over the\n// full-res scene with a DEPTH-AWARE (bilateral) upscale. Clouds are the heaviest\n// per-pixel cost in the renderer, so marching them at 1/2 or 1/4 the pixels is a\n// large win; the bilateral upscale recovers crisp edges against the terrain\n// silhouette (a plain bilinear upscale would halo there) and doubles as a mild\n// spatial denoiser.\n//\n// Isolation: the cloud mesh is moved onto a dedicated camera LAYER while this\n// mode is active, so normal (layer-0) scene renders simply never draw it — no\n// reparenting, no per-frame visibility juggling. This pass renders ONLY that\n// layer into the low-res target, then a fullscreen quad composites the result.\n//\n// The pass is self-contained (its own RT + composite material + quad scene) and\n// is shared by both the studio slab and the planet shell layers.\n// ============================================================================\n\n// Dedicated layer the cloud mesh lives on while low-res mode is active. Layer 0\n// is the default (everything else); we keep clouds off it so the main render\n// excludes them automatically.\nexport const CLOUD_LOWRES_LAYER = 2;\n\nconst COMPOSITE_FRAG = /* glsl */ `\nprecision highp float;\nvarying vec2 vUv;\n\nuniform sampler2D tCloud; // low-res clouds, PREMULTIPLIED (rgb = col*a)\nuniform sampler2D tSceneDepth; // full-res opaque scene depth (terrain)\nuniform vec2 uLowTexel; // 1 / lowResSize\nuniform float uDepthSharpness; // bilateral falloff on raw depth difference\nuniform float uAlphaSharpness; // preserve cloud/sky silhouettes\nuniform float uUseDepth; // 1 = depth-aware, 0 = plain bilinear\nuniform float uSmooth; // 1 = depth-aware tent filter (hides the march dither)\n\nfloat depthWeight(vec2 uv, float dC) {\n if (uUseDepth < 0.5) return 1.0;\n float dd = abs(texture2D(tSceneDepth, uv).x - dC) * uDepthSharpness;\n return 1.0 / (1.0 + dd * dd);\n}\n\n// Depth-aware 2x2 bilateral upsample: weight each low-res neighbour by its\n// bilinear footprint AND by how closely the scene depth at that neighbour\n// matches the scene depth at this output pixel. At a terrain silhouette the\n// neighbours on the \"wrong\" side (sky vs surface) are rejected, so the cloud\n// edge stays crisp instead of bleeding across the ridge.\nvoid main() {\n float dC = 1.0;\n if (uUseDepth > 0.5) {\n dC = texture2D(tSceneDepth, vUv).x;\n }\n\n if (uSmooth > 0.5) {\n // tent: centre + four bilinear taps 0.75 texel out on the diagonals (a\n // 3x3 footprint), each kept on this pixel's side of a depth edge\n vec2 o = uLowTexel * 0.75;\n vec4 sum = texture2D(tCloud, vUv) * 0.36;\n float ws = 0.36;\n for (int k = 0; k < 4; k++) {\n vec2 uv = vUv + o * vec2(k == 0 || k == 2 ? 1.0 : -1.0, k < 2 ? 1.0 : -1.0);\n float w = 0.16 * depthWeight(uv, dC);\n sum += texture2D(tCloud, uv) * w;\n ws += w;\n }\n gl_FragColor = sum / ws;\n return;\n }\n\n vec2 p = vUv / uLowTexel - 0.5;\n vec2 f = fract(p);\n vec2 base = (floor(p) + 0.5) * uLowTexel;\n\n vec2 guideUv = (floor(vUv / uLowTexel) + 0.5) * uLowTexel;\n float guideA = texture2D(tCloud, clamp(guideUv, vec2(0.0), vec2(1.0))).a;\n\n vec4 acc = vec4(0.0);\n float wsum = 0.0;\n for (int j = 0; j < 2; j++) {\n for (int i = 0; i < 2; i++) {\n vec2 off = vec2(float(i), float(j)) * uLowTexel;\n vec2 uv = base + off;\n float bw = (i == 0 ? 1.0 - f.x : f.x) * (j == 0 ? 1.0 - f.y : f.y);\n float dw = 1.0;\n if (uUseDepth > 0.5) {\n float dN = texture2D(tSceneDepth, uv).x;\n float dd = abs(dN - dC) * uDepthSharpness;\n dw = 1.0 / (1.0 + dd * dd);\n }\n vec4 cloud = texture2D(tCloud, uv);\n float ad = abs(cloud.a - guideA) * uAlphaSharpness;\n float aw = 1.0 / (1.0 + ad * ad);\n float w = bw * dw * aw + 1e-5;\n acc += cloud * w;\n wsum += w;\n }\n }\n gl_FragColor = acc / wsum; // premultiplied; blended \"over\" by the material\n}\n`;\n\nconst COMPOSITE_VERT = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nexport class CloudLowResPass {\n constructor() {\n this.scale = 0.5; // 1.0 = off (caller skips), 0.5 = half, 0.25 = quarter\n this.depthAware = true;\n this.smooth = false; // tent upsample instead of the sharp bilateral\n this.rt = null;\n this._size = new THREE.Vector2();\n this._prevClear = new THREE.Color();\n this._didRender = false;\n\n this._composite = new THREE.ShaderMaterial({\n uniforms: {\n tCloud: { value: null },\n tSceneDepth: { value: null },\n uLowTexel: { value: new THREE.Vector2(1, 1) },\n uDepthSharpness: { value: 1800.0 },\n uAlphaSharpness: { value: 10.0 },\n uUseDepth: { value: 1.0 },\n uSmooth: { value: 0.0 },\n },\n vertexShader: COMPOSITE_VERT,\n fragmentShader: COMPOSITE_FRAG,\n transparent: true,\n depthTest: false,\n depthWrite: false,\n // premultiplied \"over\": dst = src.rgb + dst*(1 - src.a)\n blending: THREE.CustomBlending,\n blendEquation: THREE.AddEquation,\n blendSrc: THREE.OneFactor,\n blendDst: THREE.OneMinusSrcAlphaFactor,\n blendSrcAlpha: THREE.OneFactor,\n blendDstAlpha: THREE.OneMinusSrcAlphaFactor,\n });\n this._quad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), this._composite);\n this._quad.frustumCulled = false;\n this._quadScene = new THREE.Scene();\n this._quadScene.add(this._quad);\n this._quadCam = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);\n }\n\n /** Put a cloud mesh on (or off) the dedicated low-res layer. */\n setMeshLayer(mesh, lowRes) {\n if (!mesh) return;\n mesh.layers.set(lowRes ? CLOUD_LOWRES_LAYER : 0);\n }\n\n _ensureRT(renderer, baseSize = null) {\n const ds = baseSize || renderer.getDrawingBufferSize(this._size);\n const w = Math.max(1, Math.round(ds.x * this.scale));\n const h = Math.max(1, Math.round(ds.y * this.scale));\n if (this.rt && this.rt.width === w && this.rt.height === h) return;\n if (this.rt) this.rt.dispose();\n this.rt = new THREE.WebGLRenderTarget(w, h, {\n depthBuffer: false,\n stencilBuffer: false,\n });\n this.rt.texture.minFilter = THREE.LinearFilter;\n this.rt.texture.magFilter = THREE.LinearFilter;\n this.rt.texture.generateMipmaps = false;\n }\n\n /**\n * Render ONLY the cloud layer of `scene` into the low-res target. The mesh\n * must already be on CLOUD_LOWRES_LAYER (see setMeshLayer) and visible.\n *\n * The cloud shader derives its depth-occlusion UV from gl_FragCoord /\n * uDepthResolution, so while we draw at low resolution that uniform must be\n * the LOW-RES size (the depth texture is sampled with normalized UVs, so the\n * full-res depth still lines up). renderDepthPrepass resets it to full res\n * every frame, so we only need to set it here.\n */\n renderCloud(renderer, scene, camera, mesh, baseSize = null) {\n this._ensureRT(renderer, baseSize);\n\n const depthRes = mesh?.material?.uniforms?.uDepthResolution;\n if (depthRes) depthRes.value.set(this.rt.width, this.rt.height);\n\n const savedMask = camera.layers.mask;\n const prevRT = renderer.getRenderTarget();\n const prevAutoClear = renderer.autoClear;\n const prevAlpha = renderer.getClearAlpha();\n renderer.getClearColor(this._prevClear);\n const prevBg = scene.background;\n\n // Mutating the shared renderer/camera state must be exception-safe: a throw\n // mid-render (common while the cloud program is still linking right after a\n // mode switch) would otherwise leave the camera stuck on the cloud-only\n // layer and the render target stuck on this offscreen RT, so every later\n // frame renders into nowhere and the scene appears frozen until a reload.\n try {\n camera.layers.set(CLOUD_LOWRES_LAYER); // only the cloud draws\n scene.background = null; // keep the target transparent\n renderer.autoClear = false;\n renderer.setRenderTarget(this.rt);\n renderer.setClearColor(0x000000, 0);\n renderer.clear(true, false, false);\n renderer.render(scene, camera);\n this._didRender = true;\n } finally {\n renderer.setRenderTarget(prevRT);\n renderer.setClearColor(this._prevClear, prevAlpha);\n renderer.autoClear = prevAutoClear;\n camera.layers.mask = savedMask;\n scene.background = prevBg;\n }\n }\n\n /** Composite the low-res clouds over the CURRENT render target (no clear). */\n composite(renderer, sceneDepthTex) {\n if (!this._didRender || !this.rt) return;\n const u = this._composite.uniforms;\n u.tCloud.value = this.rt.texture;\n u.tSceneDepth.value = sceneDepthTex;\n u.uLowTexel.value.set(1 / this.rt.width, 1 / this.rt.height);\n u.uUseDepth.value = (this.depthAware && sceneDepthTex) ? 1.0 : 0.0;\n u.uSmooth.value = this.smooth ? 1.0 : 0.0;\n\n const prevAutoClear = renderer.autoClear;\n renderer.autoClear = false;\n try {\n renderer.render(this._quadScene, this._quadCam);\n } finally {\n renderer.autoClear = prevAutoClear;\n this._didRender = false;\n }\n }\n\n dispose() {\n if (this.rt) { this.rt.dispose(); this.rt = null; }\n this._quad.geometry.dispose();\n this._composite.dispose();\n }\n}\n","const DEFAULT_TINT = [1.0, 0.98, 0.92];\nconst DEFAULT_SUN = [1.0, 0.94, 0.82];\nconst DEFAULT_SKY = [0.36, 0.46, 0.62];\nconst DEFAULT_BOUNCE = [0.20, 0.16, 0.11];\n\nfunction clamp01(value) {\n return Math.max(0, Math.min(1, Number.isFinite(value) ? value : 0));\n}\n\nfunction rgb(value, fallback) {\n if (Array.isArray(value)) {\n return [\n Number.isFinite(value[0]) ? value[0] : fallback[0],\n Number.isFinite(value[1]) ? value[1] : fallback[1],\n Number.isFinite(value[2]) ? value[2] : fallback[2],\n ];\n }\n return [...fallback];\n}\n\nfunction multiply(a, b, scale = 1) {\n return [\n a[0] * b[0] * scale,\n a[1] * b[1] * scale,\n a[2] * b[2] * scale,\n ];\n}\n\nfunction scale(a, amount) {\n return [a[0] * amount, a[1] * amount, a[2] * amount];\n}\n\nfunction mix(a, b, amount) {\n const t = clamp01(amount);\n return [\n a[0] + (b[0] - a[0]) * t,\n a[1] + (b[1] - a[1]) * t,\n a[2] + (b[2] - a[2]) * t,\n ];\n}\n\nfunction vectorArray(value, fallback = [0.4, 0.7, 0.5]) {\n if (Array.isArray(value)) return rgb(value, fallback);\n if (value && Number.isFinite(value.x) && Number.isFinite(value.y) && Number.isFinite(value.z)) {\n return [value.x, value.y, value.z];\n }\n return [...fallback];\n}\n\n/**\n * Resolve the active sky/terrain lighting into the compact radiance state used\n * by every cloud renderer. This stays independent from THREE so it can be\n * validated without a WebGL context.\n */\nexport function resolveCloudLightingState({\n proceduralSkyActive = false,\n timeOfDay = null,\n params = {},\n sunDirection = null,\n terrainSunColor = DEFAULT_SUN,\n terrainSunIntensity = 1.25,\n terrainSkyAmbient = DEFAULT_SKY,\n terrainGroundBounce = DEFAULT_BOUNCE,\n} = {}) {\n const direction = vectorArray(sunDirection);\n\n if (proceduralSkyActive && timeOfDay) {\n const tint = rgb(params.visualsAtmosphereTint, DEFAULT_TINT);\n const brightness = Math.max(0, params.skyboxBrightness ?? 1.0)\n * Math.max(0, params.visualsSkyIntensity ?? 1.08);\n const ambientScale = Math.max(0, timeOfDay.ambientIntensity ?? 0.5) * brightness;\n const haze = clamp01(params.skyboxHaze ?? 0.55);\n const zenith = rgb(timeOfDay.zenith, DEFAULT_SKY);\n const horizon = rgb(timeOfDay.horizon, DEFAULT_SKY);\n const fog = rgb(timeOfDay.fogColor, horizon);\n const bottomSky = mix(horizon, fog, haze * 0.75);\n\n return {\n source: 'procedural-sky',\n sunDirection: direction,\n directLightColor: scale(\n rgb(timeOfDay.sunColor, DEFAULT_SUN),\n Math.max(0, timeOfDay.lightIntensity ?? 1),\n ),\n ambientTopColor: multiply(zenith, tint, ambientScale),\n ambientBottomColor: multiply(bottomSky, tint, ambientScale),\n groundBounceColor: multiply(fog, tint, ambientScale * 0.18),\n };\n }\n\n const sky = rgb(terrainSkyAmbient, DEFAULT_SKY);\n return {\n source: 'terrain-lighting',\n sunDirection: direction,\n directLightColor: scale(\n rgb(terrainSunColor, DEFAULT_SUN),\n Math.max(0, terrainSunIntensity ?? 1.25),\n ),\n // Match the scale used by the terrain shaders so manual Lighting changes\n // affect terrain and clouds in the same direction and approximate amount.\n ambientTopColor: scale(sky, 0.50),\n ambientBottomColor: scale(sky, 0.35),\n groundBounceColor: scale(rgb(terrainGroundBounce, DEFAULT_BOUNCE), 0.25),\n };\n}\n\nfunction setColor(uniform, value) {\n if (uniform?.value?.setRGB && value) uniform.value.setRGB(value[0], value[1], value[2]);\n}\n\n/**\n * Copy a resolved state to a cloud material's uniforms.\n */\nexport function applyCloudLightingState(uniforms, state) {\n if (!uniforms || !state) return;\n setColor(uniforms.uCloudDirectLight, state.directLightColor);\n setColor(uniforms.uCloudAmbientTop, state.ambientTopColor);\n setColor(uniforms.uCloudAmbientBottom, state.ambientBottomColor);\n setColor(uniforms.uCloudGroundBounce, state.groundBounceColor);\n if (uniforms.uCloudSunDir?.value?.set) {\n uniforms.uCloudSunDir.value.set(\n state.sunDirection[0],\n state.sunDirection[1],\n state.sunDirection[2],\n ).normalize();\n }\n}\n","import * as THREE from 'three';\nimport { CLOUD_NOISE_GLSL } from './cloudGLSL.js';\n\nconst VERTEX = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nconst buildOccupancyFragment = (planet) => /* glsl */ `\nprecision highp float;\n#define CLOUD_OCTAVES 3\n${CLOUD_NOISE_GLSL}\n\nvarying vec2 vUv;\nuniform float uCloudCoverage;\nuniform float uCloudSoftness;\nuniform float uCloudScale;\nuniform float uCloudDetailStrength;\nuniform vec3 uCloudWind;\nuniform float uCloudRotation;\nuniform float uCloudTime;\nuniform float uCloudEvolve;\nuniform vec3 uCloudNoiseOffset;\nuniform vec3 uCloudVariationOffset;\nuniform vec3 uCloudDomainOrigin;\nuniform vec2 uOccCenter;\nuniform float uOccExtent;\nuniform float uCloudBottom;\nuniform float uCloudTop;\nuniform float uCloudInner;\nuniform float uCloudOuter;\n\nvec3 occDomain(vec3 p) {\n float c = cos(uCloudRotation), s = sin(uCloudRotation);\n return vec3(c * p.x + s * p.z, p.y, -s * p.x + c * p.z);\n}\n\nfloat occShape(vec3 p) {\n vec3 drift = uCloudWind * uCloudTime;\n vec3 q = occDomain(p - uCloudDomainOrigin) * uCloudScale\n + uCloudNoiseOffset\n + uCloudVariationOffset\n + drift\n + vec3(0.0, uCloudTime * uCloudEvolve, 0.0);\n q = cl_formationPoint(q);\n float base = cl_formationBase(q, cl_fbm_base(q));\n // A generous margin replaces the old CPU dilation/boost and deliberately\n // over-estimates occupancy so the visible raymarch never clips wisps.\n float threshold = 1.0 - uCloudCoverage\n - max(uCloudSoftness, 0.06)\n - uCloudDetailStrength * 0.5\n - 0.04;\n return step(threshold, base);\n}\n\nvec3 octDecode(vec2 f) {\n vec3 n = vec3(f.xy, 1.0 - abs(f.x) - abs(f.y));\n if (n.z < 0.0) {\n n.xy = (1.0 - abs(n.yx)) * sign(n.xy);\n }\n return normalize(n);\n}\n\nvoid main() {\n float occupied = 0.0;\n ${planet ? `\n vec3 dir = octDecode(vUv * 2.0 - 1.0);\n float span = uCloudOuter - uCloudInner;\n occupied = max(occupied, occShape(dir * (uCloudInner + span * 0.20)));\n occupied = max(occupied, occShape(dir * (uCloudInner + span * 0.50)));\n occupied = max(occupied, occShape(dir * (uCloudInner + span * 0.80)));\n ` : `\n vec2 xz = uOccCenter + (vUv * 2.0 - 1.0) * uOccExtent;\n float span = uCloudTop - uCloudBottom;\n occupied = max(occupied, occShape(vec3(xz.x, uCloudBottom + span * 0.25, xz.y)));\n occupied = max(occupied, occShape(vec3(xz.x, uCloudBottom + span * 0.50, xz.y)));\n occupied = max(occupied, occShape(vec3(xz.x, uCloudBottom + span * 0.75, xz.y)));\n `}\n gl_FragColor = vec4(occupied, 0.0, 0.0, 1.0);\n}\n`;\n\nconst DILATE_FRAGMENT = /* glsl */ `\nprecision highp float;\nvarying vec2 vUv;\nuniform sampler2D tInput;\nuniform vec2 uTexel;\nvoid main() {\n float occupied = 0.0;\n for (int y = -1; y <= 1; y++) {\n for (int x = -1; x <= 1; x++) {\n occupied = max(\n occupied,\n texture2D(tInput, vUv + vec2(float(x), float(y)) * uTexel).r\n );\n }\n }\n gl_FragColor = vec4(occupied, 0.0, 0.0, 1.0);\n}\n`;\n\n/**\n * Produces the small empty-space acceleration texture entirely on the GPU.\n * The result stays resident as a render-target texture: no CPU FBM loop, no\n * DataTexture upload and no GPU readback on the animation path.\n */\nexport class CloudOccupancyPass {\n constructor(renderer, uniforms, { size = 64, planet = false } = {}) {\n this.renderer = renderer;\n this.size = size;\n this.scene = new THREE.Scene();\n this.camera = new THREE.Camera();\n this.targets = [0, 1].map((index) => {\n const target = new THREE.WebGLRenderTarget(size, size, {\n type: THREE.UnsignedByteType,\n format: THREE.RedFormat,\n internalFormat: 'R8',\n minFilter: THREE.LinearFilter,\n magFilter: THREE.LinearFilter,\n depthBuffer: false,\n generateMipmaps: false,\n });\n target.texture.name = `CloudOccupancyGPU${planet ? 'Planet' : 'Studio'}${index}`;\n return target;\n });\n this.generateMaterial = new THREE.ShaderMaterial({\n uniforms,\n vertexShader: VERTEX,\n fragmentShader: buildOccupancyFragment(planet),\n depthTest: false,\n depthWrite: false,\n blending: THREE.NoBlending,\n });\n this.dilateMaterial = new THREE.ShaderMaterial({\n uniforms: {\n tInput: { value: null },\n uTexel: { value: new THREE.Vector2(1 / size, 1 / size) },\n },\n vertexShader: VERTEX,\n fragmentShader: DILATE_FRAGMENT,\n depthTest: false,\n depthWrite: false,\n blending: THREE.NoBlending,\n });\n this.mesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), this.generateMaterial);\n this.mesh.frustumCulled = false;\n this.scene.add(this.mesh);\n }\n\n get texture() { return this.targets[0].texture; }\n\n setUniforms(uniforms) {\n this.generateMaterial.uniforms = uniforms;\n }\n\n render() {\n const r = this.renderer;\n const prevTarget = r.getRenderTarget();\n const prevViewport = r.getViewport(new THREE.Vector4());\n const prevScissor = r.getScissor(new THREE.Vector4());\n const prevScissorTest = r.getScissorTest();\n try {\n r.setScissorTest(false);\n r.setViewport(0, 0, this.size, this.size);\n this.mesh.material = this.generateMaterial;\n r.setRenderTarget(this.targets[0]);\n r.render(this.scene, this.camera);\n for (let pass = 0; pass < 2; pass++) {\n const source = this.targets[pass % 2];\n const destination = this.targets[(pass + 1) % 2];\n this.dilateMaterial.uniforms.tInput.value = source.texture;\n this.mesh.material = this.dilateMaterial;\n r.setRenderTarget(destination);\n r.render(this.scene, this.camera);\n }\n } finally {\n r.setRenderTarget(prevTarget);\n r.setViewport(prevViewport);\n r.setScissor(prevScissor);\n r.setScissorTest(prevScissorTest);\n this.mesh.material = this.generateMaterial;\n }\n }\n\n dispose() {\n for (const target of this.targets) target.dispose();\n this.mesh.geometry.dispose();\n this.generateMaterial.dispose();\n this.dilateMaterial.dispose();\n }\n}\n","import * as THREE from 'three';\nimport { createCloudSlabMaterial } from './CloudSlabShader.js';\nimport { resolveCloudQuality, cloudNoiseOffset, resolveCloudNoiseType } from './CloudSettings.js';\nimport { renderTerrainCloudShadow } from './CloudShadowPass.js';\nimport { buildOccupancyPlanar } from './cloudFieldCPU.js';\nimport { CloudLowResPass } from './CloudLowResPass.js';\nimport { applyCloudLightingState } from './CloudLightingState.js';\nimport { CloudOccupancyPass } from './CloudOccupancyPass.js';\n\n// Resolution of the planar (XZ) occupancy grid for the studio cloud slab.\nconst OCC_SIZE = 64;\nfunction scheduleFrames(fn, frames = 1) {\n const raf = globalThis.requestAnimationFrame;\n if (typeof raf !== 'function') return setTimeout(fn, Math.max(1, frames) * 16);\n let remaining = Math.max(1, frames);\n const step = () => {\n remaining--;\n if (remaining <= 0) fn();\n else raf(step);\n };\n return raf(step);\n}\n\n// ============================================================================\n// CloudSlabLayer: studio/flat-board manager for the planar volumetric cloud\n// slab. The twin of PlanetCloudLayer — same cloud params, same quality/fallback\n// resolution, but it sits over the board between two horizontal planes.\n//\n// The mesh is one large horizontal plane that only supplies fragments; the\n// volume comes from the slab raymarch. The layer keeps a `_ready` gate so the\n// (heavy) program is warmed in the background on first enable and the slab only\n// becomes visible once compiled — no first-frame hang.\n// ============================================================================\n\nexport class CloudSlabLayer {\n /**\n * @param {THREE.Scene} scene\n * @param {object} opts\n * @param {(mats: THREE.Material[]) => Promise<void>} [opts.compile] warmup hook\n */\n constructor(scene, opts = {}) {\n this.scene = scene;\n this._compile = opts.compile || null;\n // The first material is the selected final specialization. A previous\n // bootstrap specialization was compiled first and then replaced, creating\n // both extra startup work and a visible temporal quality phase.\n const initial = opts.initialConfig || {};\n this._steps = initial.steps ?? 12;\n this._lightSteps = initial.lightSteps ?? 6;\n this._octaves = initial.octaves ?? 5;\n this._detailOctaves = initial.detailOctaves ?? 4;\n this._useErosion = initial.useErosion !== false;\n this._lightMode = initial.lightMode ?? 1;\n this._stepLOD = false;\n this._adaptiveScaleMultiplier = 1;\n this._adaptiveStepScale = 1;\n this._baseRenderScale = 1;\n this._lowRes = false; // half/quarter-res cloud render + bilateral upscale\n this._lowResPass = new CloudLowResPass();\n this._enabled = false;\n this._inScene = true; // gated off while another world mode is active\n this._inRange = true;\n this._ready = !this._compile;\n this._warming = false;\n this._maxDistance = Infinity;\n this._rotation = 0;\n this._wind = new THREE.Vector3();\n this._boardSize = 2048;\n this._depthTarget = null;\n this._depthTexture = null;\n this._depthSize = new THREE.Vector2();\n this._prevClearColor = new THREE.Color();\n this._compileToken = 0;\n this._pendingCompile = null;\n this._targetConfig = {\n steps: this._steps,\n lightSteps: this._lightSteps,\n octaves: this._octaves,\n detailOctaves: this._detailOctaves,\n useErosion: this._useErosion,\n lightMode: this._lightMode,\n };\n\n // planar occupancy grid (empty-space-skip acceleration), rebuilt on a throttle\n this._occData = new Uint8Array(OCC_SIZE * OCC_SIZE);\n this._occScratch = new Uint8Array(OCC_SIZE * OCC_SIZE);\n this._occupancyRatio = 0;\n this._occupancyUseful = true;\n this._occTex = new THREE.DataTexture(this._occData, OCC_SIZE, OCC_SIZE, THREE.RedFormat, THREE.UnsignedByteType);\n this._occTex.minFilter = THREE.LinearFilter;\n this._occTex.magFilter = THREE.LinearFilter;\n this._occTex.wrapS = THREE.ClampToEdgeWrapping;\n this._occTex.wrapT = THREE.ClampToEdgeWrapping;\n this._occTex.generateMipmaps = false;\n this._occTex.needsUpdate = true;\n this._occBuiltAt = 0;\n this._occupancyPass = null;\n\n this._renderer = opts.renderer || null;\n this.material = this._createMaterial();\n if (opts.renderer && this._usesOccupancy) {\n this._occupancyPass = new CloudOccupancyPass(\n opts.renderer,\n this.material.uniforms,\n { size: OCC_SIZE, planet: false },\n );\n }\n this._applyOccupancyUniforms();\n\n // a unit box that ENCLOSES the slab volume (scaled in applyParams). Drawn\n // BackSide so its far faces always cover the volume's screen footprint from\n // any angle — a flat plane clipped the clouds at grazing views from below.\n const geo = new THREE.BoxGeometry(1, 1, 1);\n this.mesh = new THREE.Mesh(geo, this.material);\n this.mesh.frustumCulled = false;\n this.mesh.renderOrder = 20;\n this.mesh.visible = false;\n this.scene.add(this.mesh);\n }\n\n get active() {\n return this._enabled && this._inScene && this._inRange && this._ready;\n }\n\n // Subclass hooks (the realistic renderer swaps the material and has no\n // occupancy grid).\n get _usesOccupancy() { return true; }\n\n _createMaterial() {\n return createCloudSlabMaterial(\n this._steps,\n this._lightSteps,\n this._octaves,\n this._detailOctaves,\n this._useErosion,\n this._lightMode\n );\n }\n\n get ready() {\n return !this._enabled || (this._ready && !this._warming && this._configMatches(this._targetConfig));\n }\n\n async waitUntilReady({ timeoutMs = 120000, isCurrent = () => true } = {}) {\n const startedAt = performance.now();\n while (isCurrent()) {\n if (this.ready) return true;\n if (!this._warming && this._enabled && this._compile) this._compileCurrentMaterial();\n const pending = this._pendingCompile?.promise;\n if (pending) await Promise.race([\n pending.catch(() => null),\n new Promise((resolve) => setTimeout(resolve, 32)),\n ]);\n else await new Promise((resolve) => setTimeout(resolve, 32));\n if (performance.now() - startedAt > timeoutMs) {\n throw new Error('Final cloud shader did not become ready before the boot timeout');\n }\n }\n return false;\n }\n\n /** Show/hide the slab for the active world mode (studio only). */\n setInScene(on) {\n this._inScene = !!on;\n if (!this._inScene) this.mesh.visible = false;\n }\n\n /**\n * @param {object} params engine params (cloud* keys)\n * @param {number} maxHeight terrain height ceiling (unused — kept for API parity)\n * @param {number} boardSize world size of ONE cell (drives noise feature size)\n * @param {object} [perf] centralized performance settings\n * @param {object} [layout] coverage: { extent, radius?, center:{x,z} }.\n * extent = world span the clouds must cover (union of cells); center =\n * world-space middle of that span. Defaults to a single origin-centred cell.\n */\n applyParams(params, maxHeight, boardSize, perf, layout = {}) {\n this._boardSize = boardSize || this._boardSize;\n // Coverage tracks the whole tile assembly; feature size stays per-cell so a\n // slider value keeps the same look as the assembly grows.\n const extent = layout.extent || this._boardSize;\n const cx = layout.center?.x ?? 0;\n const cz = layout.center?.z ?? 0;\n this._coverSize = extent;\n this._center = { x: cx, z: cz };\n\n const config = perf ? { ...params, ...perf } : params;\n const q = resolveCloudQuality(config);\n this._enabled = !!params.cloudsEnabled && !q.disabled;\n\n const maxDistMult = config.cloudMaxDistance ?? 6;\n this._maxDistance = maxDistMult * extent;\n\n const u = this.material.uniforms;\n // Altitude is an ABSOLUTE world height (y=0 is the ground/sea base), so the\n // layer can sit anywhere from ground level up — not pinned above the peaks.\n const bottom = params.cloudAltitude ?? 240;\n const thickness = Math.max(20, params.cloudThickness ?? 620);\n const top = bottom + thickness;\n u.uCloudBottom.value = bottom;\n u.uCloudTop.value = top;\n\n const radius = Math.max(1, layout.radius ?? extent * 0.62);\n u.uCloudRadius.value = radius;\n u.uCloudFar.value = extent * 4.0; // bound horizon marching\n u.uCloudCenter.value.set(cx, 0, cz);\n\n // occupancy grid maps the square [center ± radius] (clouds are zero past it)\n u.uOccCenter.value.set(cx, cz);\n u.uOccExtent.value = radius;\n\n // size + place the enclosing box: horizontal extent just past the radial\n // fade (clouds are zero beyond uCloudRadius), height = slab thickness with a\n // hair of margin so the bottom/top planes sit inside the box faces.\n const horiz = radius * 2.1;\n const height = Math.max(1, (top - bottom) * 1.04);\n this.mesh.scale.set(horiz, height, horiz);\n this.mesh.position.set(cx, (bottom + top) * 0.5, cz);\n\n // frequencies are user-relative; scale by board size so a slider value maps\n // to the same world feature size regardless of board dimensions.\n const fScale = 1.0 / Math.max(this._boardSize, 1);\n u.uCloudScale.value = (params.cloudScale ?? 2.2) * fScale;\n u.uCloudDetailScale.value = (params.cloudDetailScale ?? 7.0) * fScale;\n u.uCloudErosionScale.value = (params.cloudErosionScale ?? 15.0) * fScale;\n u.uCloudVariationOffset.value.fromArray(cloudNoiseOffset(params.cloudNoiseSeed));\n u.uCloudNoiseType.value = resolveCloudNoiseType(params);\n this._occBuiltAt = 0;\n u.uCloudDetailStrength.value = params.cloudDetailStrength ?? 0.35;\n u.uCloudErosionStrength.value = params.cloudErosionStrength ?? 0.30;\n\n u.uCloudCoverage.value = params.cloudCoverage ?? 0.5;\n u.uCloudSoftness.value = Math.max(0.01, params.cloudSoftness ?? 0.16);\n\n u.uCloudExtinction.value = (params.cloudDensity ?? 1.0) * 8.0 / thickness;\n u.uCloudLightAbsorption.value = params.cloudLightAbsorption ?? 3.0;\n u.uCloudShadowStrength.value = params.cloudShadowStrength ?? 0.6;\n u.uCloudScattering.value = params.cloudScatteringStrength ?? 1.0;\n u.uCloudAtmosphereInfluence.value = params.cloudAtmosphereInfluence ?? 1.0;\n u.uCloudSunResponse.value = params.cloudSunResponse ?? 1.0;\n u.uCloudAmbientResponse.value = params.cloudAmbientResponse ?? 1.0;\n u.uCloudSilverLining.value = params.cloudSilverLining ?? 0.25;\n u.uCloudSelfShadow.value = q.selfShadow ? 1.0 : 0.0;\n this._stepLOD = q.stepLOD;\n if (!this._stepLOD) u.uCloudStepScale.value = 1.0;\n\n // low-res cloud render + depth-aware upscale (perf). scale 1.0 = off.\n this._baseRenderScale = config.cloudRenderScale ?? 1.0;\n this.setAdaptiveQuality(this._adaptiveScaleMultiplier, this._adaptiveStepScale);\n\n if (params.cloudColor) u.uCloudColor.value.setRGB(...params.cloudColor);\n if (params.cloudShadowColor) u.uCloudShadowColor.value.setRGB(...params.cloudShadowColor);\n\n // Wind drift in NOISE-SPACE units/sec (not world units): the pattern lives in\n // baseP = q*uCloudScale + drift, so a drift of ~uCloudScale crosses the whole\n // board. Keeping it board-independent (no fScale) means clouds traverse the\n // visible area in a consistent time at any board size — and, crucially, makes\n // the drift the same order as the evolution so clouds actually MOVE across the\n // sky instead of only morphing in place. The old `0.6 * fScale` was ~100×\n // weaker, so the motion read as static.\n const wa = (params.cloudWindDir ?? 45) * Math.PI / 180;\n const wspeed = (params.cloudWindSpeed ?? 1.0) * 0.045;\n this._wind.set(Math.cos(wa), 0, Math.sin(wa)).multiplyScalar(wspeed);\n u.uCloudWind.value.copy(this._wind);\n\n this._rotSpeed = (params.cloudRotationSpeed ?? 0.35) * 0.01;\n\n // evolution rate in noise-space units/sec (form/morph/dissipate in place)\n u.uCloudEvolve.value = (params.cloudEvolveSpeed ?? 1.0) * 0.03;\n\n // recompile if the step counts or noise settings changed (quality / fallback)\n // We check and rebuild at the end so _rebuildMaterial can copy the fully updated uniforms to the new material.\n const needsRebuild = q.steps !== this._steps ||\n q.lightSteps !== this._lightSteps ||\n q.octaves !== this._octaves ||\n q.detailOctaves !== this._detailOctaves ||\n q.useErosion !== this._useErosion ||\n q.lightMode !== this._lightMode;\n if (needsRebuild) {\n this._targetConfig = {\n steps: q.steps,\n lightSteps: q.lightSteps,\n octaves: q.octaves,\n detailOctaves: q.detailOctaves,\n useErosion: q.useErosion,\n lightMode: q.lightMode,\n };\n if (this._ready) {\n this._rebuildMaterial(q.steps, q.lightSteps, q.octaves, q.detailOctaves, q.useErosion, q.lightMode);\n }\n }\n\n // warm the program in the background on first enable (no first-frame hang)\n if (this._enabled && !this._ready && !this._warming && this._compile) {\n this._compileCurrentMaterial();\n }\n }\n\n setLighting(lightingState) {\n applyCloudLightingState(this.material?.uniforms, lightingState);\n }\n\n setAdaptiveQuality(scaleMultiplier = 1, stepMultiplier = 1) {\n this._adaptiveScaleMultiplier = Math.max(0, Math.min(1, scaleMultiplier));\n this._adaptiveStepScale = Math.max(0.5, Math.min(1, stepMultiplier));\n const scale = Math.max(\n 0.25,\n Math.min(1, this._baseRenderScale * this._adaptiveScaleMultiplier),\n );\n this._lowRes = scale < 0.999 && this._enabled;\n this._lowResPass.scale = scale;\n this._lowResPass.setMeshLayer(this.mesh, this._lowRes);\n }\n\n get effectiveRenderScale() {\n return this._lowResPass?.scale ?? 1;\n }\n\n _configMatches(config) {\n return !!config &&\n config.steps === this._steps &&\n config.lightSteps === this._lightSteps &&\n config.octaves === this._octaves &&\n config.detailOctaves === this._detailOctaves &&\n config.useErosion === this._useErosion &&\n config.lightMode === this._lightMode;\n }\n\n _upgradeToTargetConfig() {\n const c = this._targetConfig;\n if (!this._ready || this._warming || this._configMatches(c)) return;\n scheduleFrames(() => {\n if (!this._ready || this._warming || this._configMatches(c)) return;\n this._rebuildMaterial(c.steps, c.lightSteps, c.octaves, c.detailOctaves, c.useErosion, c.lightMode);\n }, 1);\n }\n\n // Compile a material in the background without touching the _ready/_warming\n // gate (used for live rebuilds, where the OLD material stays visible until the\n // new program is ready). Returns a token to detect superseding rebuilds.\n _compileMaterial(material) {\n const token = ++this._compileToken;\n if (!this._compile) return { token, promise: Promise.resolve({ ready: true }) };\n\n let promise;\n try {\n promise = Promise.resolve(this._compile([material]));\n } catch (e) {\n promise = Promise.reject(e);\n }\n\n const done = promise.then((result) => {\n if (result?.ready === false || result?.aborted === true) {\n throw new Error('Cloud shader did not become ready');\n }\n return result;\n });\n this._pendingCompile = { material, promise: done };\n const clearPending = () => {\n if (this._pendingCompile?.promise === done) this._pendingCompile = null;\n };\n done.then(clearPending, clearPending);\n\n return { token, promise: done };\n }\n\n // Warm the CURRENT material and flip the _ready gate when done (first-enable\n // path — clouds stay hidden until the very first program is compiled so there\n // is no first-frame FXC hang).\n _compileCurrentMaterial() {\n if (!this._compile) {\n this._ready = true;\n this._warming = false;\n return Promise.resolve();\n }\n\n const material = this.material;\n this._ready = false;\n this._warming = true;\n const { token, promise } = this._compileMaterial(material);\n\n promise.then(() => {\n if (token === this._compileToken && this.material === material) {\n this._ready = true;\n this._warming = false;\n this._upgradeToTargetConfig();\n }\n }, () => {\n if (token === this._compileToken && this.material === material) {\n this._ready = false;\n this._warming = false;\n }\n });\n\n return promise;\n }\n\n _disposeWhenSafe(material, pending) {\n if (!material) return;\n if (pending) pending.then(() => material.dispose(), () => material.dispose());\n else material.dispose();\n }\n\n /** Point the current material at the occupancy texture (after create/rebuild). */\n _applyOccupancyUniforms() {\n const u = this.material.uniforms;\n if (this._occupancyPass) this._occupancyPass.setUniforms(u);\n if (u.uCloudOccupancy) {\n u.uCloudOccupancy.value = this._occupancyPass?.texture || this._occTex;\n }\n }\n\n /** Rebuild the planar occupancy grid from the current field params (cheap,\n * throttled by the caller). */\n _rebuildOccupancy() {\n const u = this.material.uniforms;\n if (this._occupancyPass) {\n this._occupancyPass.render();\n this._occupancyRatio = null;\n this._occupancyUseful = true;\n u.uUseOccupancy.value = 1.0;\n return;\n }\n const w = u.uCloudWind.value;\n const occupancyRatio = buildOccupancyPlanar(\n this._occData, OCC_SIZE,\n u.uOccCenter.value.x, u.uOccCenter.value.y, u.uOccExtent.value,\n u.uCloudBottom.value, u.uCloudTop.value,\n {\n scale: u.uCloudScale.value,\n noiseType: u.uCloudNoiseType.value,\n offsetX: u.uCloudVariationOffset.value.x,\n offsetY: u.uCloudVariationOffset.value.y,\n offsetZ: u.uCloudVariationOffset.value.z,\n windX: w.x, windY: w.y, windZ: w.z,\n time: u.uCloudTime.value,\n rotation: u.uCloudRotation.value,\n coverage: u.uCloudCoverage.value,\n softness: u.uCloudSoftness.value,\n octaves: this._octaves,\n evolve: u.uCloudEvolve.value,\n // conservative upper-bound margin for the detail noise the GPU adds\n boost: (u.uCloudDetailStrength.value || 0) * 0.5 + 0.03,\n }, 2, this._occScratch\n );\n this._occTex.needsUpdate = true;\n this._occupancyRatio = occupancyRatio;\n this._occupancyUseful = occupancyRatio > 0 && occupancyRatio < 0.78;\n u.uUseOccupancy.value = this._occupancyUseful ? 1.0 : 0.0;\n }\n\n getTerrainShadowState() {\n const u = this.material?.uniforms;\n if (!u) return null;\n return {\n center: u.uOccCenter.value,\n extent: u.uOccExtent.value,\n altitude: (u.uCloudBottom.value + u.uCloudTop.value) * 0.5,\n scale: u.uCloudScale.value,\n coverage: u.uCloudCoverage.value,\n softness: u.uCloudSoftness.value,\n wind: u.uCloudWind.value,\n time: u.uCloudTime.value,\n rotation: u.uCloudRotation.value,\n evolve: u.uCloudEvolve.value,\n };\n }\n\n renderTerrainShadow(sun, tiles) {\n return renderTerrainCloudShadow(this, sun, false, tiles);\n }\n\n _rebuildMaterial(steps, lightSteps, octaves, detailOctaves, useErosion, lightMode = this._lightMode) {\n this._steps = steps;\n this._lightSteps = lightSteps;\n this._octaves = octaves;\n this._detailOctaves = detailOctaves;\n this._useErosion = useErosion;\n this._lightMode = lightMode;\n const previous = this.material;\n const pendingPrevious = this._pendingCompile?.material === previous\n ? this._pendingCompile.promise\n : null;\n const next = createCloudSlabMaterial(\n steps,\n lightSteps,\n octaves,\n detailOctaves,\n useErosion,\n lightMode\n );\n const copyLiveUniforms = () => {\n const a = previous.uniforms, b = next.uniforms;\n for (const k in b) {\n if (!(k in a)) continue;\n const av = a[k].value, bv = b[k].value;\n if (av && av.copy && bv && bv.copy) bv.copy(av);\n else b[k].value = a[k].value;\n }\n };\n copyLiveUniforms();\n\n if (!this._ready) {\n // First program not shown yet — swap now (nothing visible) and keep\n // warming; the _ready gate reveals the clouds once compiled.\n this.mesh.material = next;\n this.material = next;\n this.mesh.visible = false;\n this._disposeWhenSafe(previous, pendingPrevious);\n this._compileCurrentMaterial();\n return;\n }\n\n // Clouds are already on screen: compile the new program in the BACKGROUND\n // and keep the old material rendering until it's ready, then swap with no\n // flicker (mirrors PlanetCloudLayer). Changing raymarch steps no longer\n // makes the clouds vanish.\n const { token, promise } = this._compileMaterial(next);\n promise.then(() => {\n if (token !== this._compileToken || this.material !== previous) {\n next.dispose();\n return;\n }\n // Shape/variation controls may change while the new quality program links.\n copyLiveUniforms();\n this.mesh.material = next;\n this.material = next;\n this._applyOccupancyUniforms();\n this._disposeWhenSafe(previous, pendingPrevious);\n }, () => next.dispose());\n }\n\n update(dt, cameraPos, sunDir) {\n if (!this._enabled || !this._inScene || !this._ready) {\n if (this.mesh.visible) this.mesh.visible = false;\n return;\n }\n const c = this._center || { x: 0, z: 0 };\n const dist = Math.hypot(cameraPos.x - c.x, cameraPos.y, cameraPos.z - c.z);\n this._inRange = dist <= this._maxDistance;\n this.mesh.visible = this._inRange;\n if (!this._inRange) return;\n\n const u = this.material.uniforms;\n // step-LOD: ramp the effective march steps down to 0.4 toward the cull edge\n let distanceStepScale = 1.0;\n if (this._stepLOD && Number.isFinite(this._maxDistance)) {\n const near = this._coverSize || this._boardSize;\n const far = this._maxDistance;\n const f = far > near ? (dist - near) / (far - near) : 0;\n distanceStepScale = Math.max(0.4, Math.min(1.0, 1.0 - f * 0.6));\n }\n u.uCloudStepScale.value = distanceStepScale * this._adaptiveStepScale;\n u.uCloudTime.value += dt;\n this._rotation += dt * (this._rotSpeed || 0);\n u.uCloudRotation.value = this._rotation;\n this._syncDomainRebase();\n if (sunDir) u.uCloudSunDir.value.copy(sunDir);\n\n // refresh the empty-space-skip occupancy grid on a throttle\n const now = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const occupancyInterval = this._occupancyUseful ? 250 : 1000;\n if (now - this._occBuiltAt > occupancyInterval) {\n this._occBuiltAt = now;\n this._rebuildOccupancy();\n }\n }\n\n // InfiniteCloudLayer overrides this to keep its camera-local sample domain\n // continuous while the bounded render volume recenters.\n _syncDomainRebase() {}\n\n /** Bind depth produced by the real scene render (no duplicate scene pass). */\n useSceneDepth(depthTexture, camera, baseSize = null) {\n const u = this.material.uniforms;\n if (!this.active || !depthTexture) {\n u.uUseDepth.value = 0.0;\n return false;\n }\n const size = baseSize || depthTexture.image || {};\n const width = size.x ?? size.width ?? 1;\n const height = size.y ?? size.height ?? 1;\n u.tSceneDepth.value = depthTexture;\n u.uDepthResolution.value.set(width, height);\n u.uProjectionMatrixInverse.value.copy(camera.projectionMatrixInverse);\n u.uViewMatrixInverse.value.copy(camera.matrixWorld);\n u.uUseDepth.value = 1.0;\n return true;\n }\n\n renderDepthPrepass(renderer, camera, baseSize = null) {\n if (!this.active) {\n this.material.uniforms.uUseDepth.value = 0.0;\n return false;\n }\n\n this._ensureDepthTarget(renderer, baseSize);\n\n const wasVisible = this.mesh.visible;\n const prevTarget = renderer.getRenderTarget();\n const prevClearAlpha = renderer.getClearAlpha();\n renderer.getClearColor(this._prevClearColor);\n\n try {\n this.mesh.visible = false;\n renderer.setRenderTarget(this._depthTarget);\n renderer.setClearColor(0x000000, 1);\n renderer.clear(true, true, true);\n renderer.render(this.scene, camera);\n } finally {\n this.mesh.visible = wasVisible;\n renderer.setRenderTarget(prevTarget);\n renderer.setClearColor(this._prevClearColor, prevClearAlpha);\n }\n\n return this.useSceneDepth(this._depthTexture, camera, this._depthTarget);\n }\n\n /** True while low-res cloud mode is active (mesh lives on the offscreen layer\n * and is composited rather than drawn inline). The engine uses this to know\n * it must call compositeLowRes after the main render. */\n get usesLowRes() {\n return this._lowRes && this.active;\n }\n\n /** Render the clouds into the low-res target (call after renderDepthPrepass,\n * before the main scene render). Returns true if it ran. */\n renderLowRes(renderer, camera, baseSize = null) {\n if (!this.usesLowRes) return false;\n this._lowResPass.renderCloud(renderer, this.scene, camera, this.mesh, baseSize);\n return true;\n }\n\n /** Composite the low-res clouds over the current target (call after the main\n * scene render). */\n compositeLowRes(renderer, sceneDepthTexture = this._depthTexture) {\n if (!this.usesLowRes) return;\n this._lowResPass.composite(renderer, sceneDepthTexture);\n }\n\n _ensureDepthTarget(renderer, baseSize = null) {\n const size = baseSize || renderer.getDrawingBufferSize(this._depthSize);\n const w = Math.max(1, Math.round(size.x));\n const h = Math.max(1, Math.round(size.y));\n if (this._depthTarget && this._depthTarget.width === w && this._depthTarget.height === h) return;\n\n if (this._depthTarget) this._depthTarget.dispose();\n this._depthTexture = new THREE.DepthTexture(w, h);\n this._depthTexture.type = THREE.UnsignedIntType;\n this._depthTexture.format = THREE.DepthFormat;\n this._depthTarget = new THREE.WebGLRenderTarget(w, h, {\n depthTexture: this._depthTexture,\n depthBuffer: true,\n stencilBuffer: false,\n });\n this._depthTarget.texture.minFilter = THREE.NearestFilter;\n this._depthTarget.texture.magFilter = THREE.NearestFilter;\n this._depthTarget.texture.generateMipmaps = false;\n }\n\n dispose() {\n this._shadowPass?.dispose();\n if (this._depthTarget) {\n this._depthTarget.dispose();\n this._depthTarget = null;\n this._depthTexture = null;\n }\n if (this._occTex) { this._occTex.dispose(); this._occTex = null; }\n if (this._occupancyPass) {\n this._occupancyPass.dispose();\n this._occupancyPass = null;\n }\n if (this._lowResPass) { this._lowResPass.dispose(); this._lowResPass = null; }\n this.scene.remove(this.mesh);\n this.mesh.geometry.dispose();\n this.material.dispose();\n this.mesh = null;\n this.material = null;\n }\n}\n","import * as THREE from 'three';\nimport { CloudSlabLayer } from './CloudSlabLayer.js';\n\n/**\n * Camera-following bounded cloud slab for Infinite mode. The mesh and occupancy\n * region snap on terrain chunk boundaries, while a noise-space offset preserves\n * the same logical procedural field across every rebase.\n */\nexport class InfiniteCloudLayer extends CloudSlabLayer {\n constructor(scene, opts = {}) {\n super(scene, opts);\n this.mesh.name = 'infinite-cloud-layer';\n this._chunkSize = Math.max(1, opts.chunkSize || 256);\n this._viewRadius = Math.max(1, opts.viewRadius || 8);\n this._logicalCenter = new THREE.Vector2();\n this._rebaseScratch = new THREE.Vector3();\n }\n\n applyParams(params, maxHeight, boardSize, perf, layout = {}) {\n this._chunkSize = Math.max(1, layout.chunkSize || this._chunkSize);\n this._viewRadius = Math.max(1, layout.viewRadius || this._viewRadius);\n const viewDistance = this._chunkSize * (this._viewRadius + 1);\n const cloudRadius = viewDistance * 1.15;\n const extent = cloudRadius / 0.62;\n\n super.applyParams(params, maxHeight, boardSize, perf, {\n extent,\n center: { x: this._logicalCenter.x, z: this._logicalCenter.y },\n });\n\n // The bounded volume follows the camera, so distance culling would only\n // introduce a height-dependent pop and is unnecessary.\n this._maxDistance = Infinity;\n this.material.uniforms.uCloudFar.value = cloudRadius * 2.5;\n this._syncDomainRebase();\n }\n\n _recenter(cameraPos) {\n const x = Math.floor(cameraPos.x / this._chunkSize) * this._chunkSize;\n const z = Math.floor(cameraPos.z / this._chunkSize) * this._chunkSize;\n if (x === this._logicalCenter.x && z === this._logicalCenter.y) return false;\n\n this._logicalCenter.set(x, z);\n this._center = { x, z };\n const u = this.material.uniforms;\n u.uCloudCenter.value.set(x, 0, z);\n u.uOccCenter.value.set(x, z);\n this.mesh.position.x = x;\n this.mesh.position.z = z;\n this._occBuiltAt = 0;\n this._syncDomainRebase();\n return true;\n }\n\n _syncDomainRebase() {\n const u = this.material?.uniforms;\n if (!u?.uCloudDomainOrigin || !u?.uCloudNoiseOffset) return;\n const x = this._logicalCenter.x;\n const z = this._logicalCenter.y;\n const angle = u.uCloudRotation.value;\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const scale = u.uCloudScale.value;\n\n u.uCloudDomainOrigin.value.set(x, 0, z);\n this._rebaseScratch.set(\n c * x + s * z,\n 0,\n -s * x + c * z,\n ).multiplyScalar(scale);\n u.uCloudNoiseOffset.value.copy(this._rebaseScratch);\n }\n\n update(dt, cameraPos, sunDir) {\n this._recenter(cameraPos);\n super.update(dt, cameraPos, sunDir);\n }\n}\n","import * as THREE from 'three';\nimport { CLOUD_NOISE_GLSL, CLOUD_FIELD_GLSL, CLOUD_VOLUME_GLSL } from './cloudGLSL.js';\n\n// ============================================================================\n// CloudVolumeShader: a transparent material that raymarches the spherical\n// cloud shell. It is drawn on a sphere mesh at the OUTER radius using\n// THREE.BackSide so the shell's screen footprint is always covered (from\n// outside the back faces project over the full disc; from inside they surround\n// the camera). The mesh only defines the render area — the visual volume comes\n// entirely from the fragment raymarch.\n//\n// Occlusion by the planet is analytic: the march segment is clamped to the\n// inner (planet) sphere, so the far half of the shell behind the globe is\n// never accumulated. depthTest is therefore disabled (the planet's depth would\n// otherwise wrongly cull near-side clouds drawn on far-side back faces).\n//\n// Step counts are compile-time #defines (CLOUD_STEPS / CLOUD_LIGHT_STEPS) so\n// the loops stay statically bounded for the D3D11/ANGLE compiler. Changing\n// quality swaps the defines and recompiles.\n// ============================================================================\n\nconst VERTEX = /* glsl */ `\nvarying vec3 vWorldPos;\nvoid main() {\n vec4 wp = modelMatrix * vec4(position, 1.0);\n vWorldPos = wp.xyz;\n gl_Position = projectionMatrix * viewMatrix * wp;\n}\n`;\n\nconst FRAGMENT = /* glsl */ `\nprecision highp float;\n\n${CLOUD_NOISE_GLSL}\n${CLOUD_FIELD_GLSL}\n${CLOUD_VOLUME_GLSL}\n\nvarying vec3 vWorldPos;\n\n// scene-depth occlusion (terrain hides clouds behind it). Active only when a\n// depth prepass has populated tSceneDepth (uUseDepth = 1); the analytic inner-\n// sphere clamp above already handles the far hemisphere, this adds true relief\n// occlusion so clouds no longer show through the surface up close.\nuniform sampler2D tSceneDepth;\nuniform vec2 uDepthResolution;\nuniform mat4 uProjectionMatrixInverse;\nuniform mat4 uViewMatrixInverse;\nuniform float uDepthBias;\nuniform float uUseDepth;\n\n#if defined(CLOUD_CHUNK) && CLOUD_CHUNK > 0\n// Per-chunk angular sector: 4 inward planes through the planet origin. The march\n// is clipped to dot(N_k, P) >= 0 for every k, so each cube-face cell owns a\n// DISJOINT slice of the shell. Back-to-front \"over\" compositing across the\n// chunk meshes (Three sorts transparents by distance) reconstructs exactly the\n// single continuous march — no double counting, same visual.\nuniform vec3 uCellNormals[4];\n#endif\n\nvec3 reconstructWorldPosition(vec2 uv, float depth) {\n vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 view = uProjectionMatrixInverse * clip;\n view.xyz /= view.w;\n return (uViewMatrixInverse * vec4(view.xyz, 1.0)).xyz;\n}\n\nvec3 cl_resolveLighting(vec3 P, vec3 rd, float light, float cloudHeight) {\n vec3 legacyAmbient = uCloudShadowColor * uCloudShadowStrength;\n vec3 legacy = mix(legacyAmbient, uCloudColor, light)\n * (0.55 + 0.45 * uCloudScattering * light);\n\n float height01 = clamp(cloudHeight, 0.0, 1.0);\n float sunVisibility = cl_sunVisibility(P, height01);\n float shadowAmount = (1.0 - light) * uCloudShadowStrength;\n float shadowedSun = mix(1.0, light, uCloudShadowStrength);\n vec3 shadowTint = mix(vec3(1.0), uCloudShadowColor, shadowAmount);\n\n vec3 skyAmbient = mix(uCloudAmbientBottom, uCloudAmbientTop, height01);\n skyAmbient += uCloudGroundBounce * (1.0 - height01);\n\n float sunView = max(dot(rd, normalize(uCloudSunDir)), 0.0);\n float silverLining = pow(sunView, 12.0) * uCloudSilverLining * sunVisibility;\n float phase = 0.65 + 0.35 * uCloudScattering + silverLining;\n\n vec3 direct = uCloudDirectLight * sunVisibility * shadowedSun\n * uCloudSunResponse * phase;\n vec3 atmospheric = uCloudColor\n * (skyAmbient * uCloudAmbientResponse + direct)\n * shadowTint;\n\n return mix(legacy, atmospheric, clamp(uCloudAtmosphereInfluence, 0.0, 1.0));\n}\n\n// Directional occupancy grid: a small octahedral map (built on the CPU from the\n// coverage field, conservative + dilated) telling whether a column/direction\n// holds any cloud. A cheap texture lookup lets the march skip the expensive\n// density (FBM + worley + self-shadow) over empty sky and reject empty rays\n// outright — the freed step budget also concentrates inside real cloud, cutting\n// grazing-angle grain.\nuniform sampler2D uCloudOccupancy;\nuniform float uUseOccupancy;\n\nvec2 octEncode(vec3 n) {\n n /= (abs(n.x) + abs(n.y) + abs(n.z));\n vec2 p = n.xy;\n if (n.z < 0.0) p = (1.0 - abs(p.yx)) * sign(p);\n return p * 0.5 + 0.5;\n}\n\nfloat occAt(vec3 P) {\n return textureLod(uCloudOccupancy, octEncode(normalize(P)), 0.0).r;\n}\n\nvoid main() {\n // planet is centered at the world origin, so camera position IS the ray\n // origin in planet-local space.\n vec3 ro = cameraPosition;\n vec3 rd = normalize(vWorldPos - cameraPosition);\n\n vec2 outer = cl_raySphere(ro, rd, uCloudOuter);\n if (outer.y <= 0.0 || outer.x >= outer.y) discard; // shell not ahead\n\n vec2 inner = cl_raySphere(ro, rd, uCloudInner);\n float tStart = max(outer.x, 0.0);\n float tEnd = outer.y;\n\n // planet (inner sphere) occludes the far side of the shell\n if (inner.x > 0.0 && inner.x < tEnd) tEnd = inner.x;\n // camera below the shell (on / near the surface): start past the inner exit\n float ro2 = dot(ro, ro);\n if (ro2 < uCloudInner * uCloudInner && inner.y > tStart) tStart = inner.y;\n\n // Save the pure shell segment BEFORE depth/chunk modifications. The global\n // sampling lattice (stepLen + baseT) is derived from this so every chunk on\n // a ray shares the exact same sample positions — no seam lines.\n float shellStart = tStart;\n float shellEnd = tEnd;\n\n // terrain depth occlusion: clamp the marched segment to the opaque scene hit\n if (uUseDepth > 0.5) {\n vec2 depthUv = gl_FragCoord.xy / max(uDepthResolution, vec2(1.0));\n if (depthUv.x >= 0.0 && depthUv.x <= 1.0 && depthUv.y >= 0.0 && depthUv.y <= 1.0) {\n float sceneDepth = texture2D(tSceneDepth, depthUv).x;\n if (sceneDepth < 0.99999) {\n vec3 sceneHit = reconstructWorldPosition(depthUv, sceneDepth);\n float hitT = dot(sceneHit - ro, rd);\n if (hitT > 0.0 && hitT < tEnd) tEnd = hitT - uDepthBias;\n }\n }\n }\n\n if (tEnd <= tStart) discard;\n\n // GLOBAL sampling lattice from the PURE shell segment (before depth clamp and\n // chunk clip). This guarantees the lattice is identical for all chunks on a\n // given ray, so back-to-front \"over\" compositing reconstructs a seamless\n // single march. The depth clamp and chunk clip only narrow the marched range\n // — the step positions themselves never change.\n // ADAPTIVE step spacing: aim for a roughly CONSTANT world-space sample\n // spacing (≈ one shell thickness split into CLOUD_STEPS) regardless of view\n // angle. A near-vertical ray crosses ~one thickness and uses few steps; a\n // grazing ray crosses a long chord and uses the full budget — so both sample\n // at the same fine spacing and the start-offset jitter never stretches into a\n // visible hatch. Long chords are still fully covered (effSteps caps at\n // CLOUD_STEPS, so stepLen never exceeds seg/CLOUD_STEPS — no hard cutoff).\n float shellSpan = max(uCloudOuter - uCloudInner, 1.0);\n float targetStep = shellSpan / float(CLOUD_STEPS) / clamp(uCloudStepScale, 0.05, 1.0);\n float seg = shellEnd - shellStart;\n int effSteps = int(clamp(seg / targetStep, 8.0, float(CLOUD_STEPS)) + 0.5);\n float stepLen = seg / float(effSteps);\n // Stable, ordered start-offset dither (see cl_ign). Spatial only — NO time\n // term — so the sampling lattice is frame-stable: residual banding stays put\n // as a soft gradient instead of crawling as grain when the camera moves.\n float dither = cl_ign(gl_FragCoord.xy);\n float baseT = shellStart + stepLen * dither;\n\n#if defined(CLOUD_CHUNK) && CLOUD_CHUNK > 0\n // clip the marched range to this chunk's angular sector (4 origin planes),\n // keeping stepLen/baseT (the global lattice) unchanged. Add a small overlap\n // margin (chunkEps) to ensure no seams between adjacent chunks due to float precision.\n float chunkEps = 0.05 * stepLen;\n for (int k = 0; k < 4 + uLoopGuard; k++) {\n vec3 N = uCellNormals[k];\n float nro = dot(N, ro);\n float nrd = dot(N, rd);\n if (abs(nrd) < 1e-9) {\n if (nro < 0.0) discard; // ray runs parallel to and outside the plane\n } else {\n float tp = -nro / nrd;\n if (nrd > 0.0) tStart = max(tStart, tp - chunkEps);\n else tEnd = min(tEnd, tp + chunkEps);\n }\n }\n if (tEnd <= tStart) discard;\n#endif\n\n float transmittance = 1.0;\n vec3 scatter = vec3(0.0);\n\n#if defined(CLOUD_CHUNK) && CLOUD_CHUNK > 0\n // chunk mode (experimental): uniform global lattice so adjacent chunks share\n // sample positions. Kept for the opt-in chunked path.\n float n0 = max(0.0, ceil((tStart - baseT) / stepLen));\n float t = baseT + n0 * stepLen;\n for (int i = 0; i < CLOUD_STEPS + uLoopGuard; i++) {\n if (t < tEnd && transmittance > 0.01) {\n vec3 P = ro + rd * t;\n vec2 sampleData = cloudSample(P);\n float dens = sampleData.x;\n if (dens > 0.001) {\n float light = uCloudSelfShadow > 0.5 ? cl_lightTransmittance(P) : 1.0;\n vec3 lit = cl_resolveLighting(P, rd, light, sampleData.y);\n float dT = exp(-dens * stepLen * uCloudExtinction);\n scatter += transmittance * (1.0 - dT) * lit;\n transmittance *= dT;\n }\n }\n t += stepLen;\n }\n#else\n // single-shell mode (default): symmetric sampling over the COMPLETE shell\n // interval. The distribution is derived before terrain-depth clamping, so the\n // sampling phase stays stable and the shell never develops depth-edge seams.\n // Occupancy gates expensive density at every shaped sample. Do not reject a\n // complete ray from a few probes or skip an extra interval: on long oblique\n // rays either shortcut can jump over a thin occupied cell and punch a hard\n // hole into the cloud layer.\n for (int i = 0; i < CLOUD_STEPS + uLoopGuard; i++) {\n float sampleIndex = float(i);\n if (sampleIndex < float(effSteps) && transmittance > 0.01) {\n float ta = sampleIndex / float(effSteps);\n float tb = (sampleIndex + 1.0) / float(effSteps);\n float intervalStart = shellStart + seg * ta;\n float stepLength = min(seg * (tb - ta), max(tEnd - intervalStart, 0.0));\n float t = intervalStart + stepLength * 0.5;\n if (t < tEnd && stepLength > 0.0) {\n vec3 P = ro + rd * t;\n float occ = uUseOccupancy > 0.5 ? occAt(P) : 1.0;\n if (occ >= 0.5) {\n vec3 offset = rd * (stepLength * 0.288675);\n vec2 sampleData = cloudSample(P - offset);\n float dens = 0.5 * (sampleData.x + cloudDensity(P + offset));\n if (dens > 0.001) {\n float light = uCloudSelfShadow > 0.5 ? cl_lightTransmittance(P) : 1.0;\n vec3 lit = cl_resolveLighting(P, rd, light, sampleData.y);\n float dT = exp(-dens * stepLength * uCloudExtinction);\n scatter += transmittance * (1.0 - dT) * lit;\n transmittance *= dT;\n }\n }\n }\n }\n }\n#endif\n\n float alpha = 1.0 - transmittance;\n if (alpha < 0.004) discard;\n\n vec3 col = scatter / max(alpha, 1e-4); // un-premultiply for normal blending\n col = pow(clamp(col, 0.0, 1.0), vec3(1.0 / 2.2));\n gl_FragColor = vec4(col, alpha);\n}\n`;\n\n/**\n * Create the volumetric cloud material.\n * @param {number} steps primary raymarch step count (compile-time)\n * @param {number} lightSteps secondary (sun) march step count (compile-time)\n * @param {number} octaves base noise FBM octave count (compile-time)\n * @param {number} detailOctaves detail noise FBM octave count (compile-time)\n * @param {boolean} useErosion whether to use cellular erosion (compile-time)\n * @param {number} lightMode 0 = secondary march, 1 = cheap 2-tap analytic shadow\n * @param {boolean} chunk true = sector-clipped chunk variant (CLOUD_CHUNK)\n */\nexport function createCloudMaterial(steps = 24, lightSteps = 6, octaves = 5, detailOctaves = 4, useErosion = true, lightMode = 0, chunk = false) {\n const uniforms = {\n uCloudInner: { value: 16240 },\n uCloudOuter: { value: 16860 },\n uCloudCoverage: { value: 0.5 },\n uCloudSoftness: { value: 0.16 },\n uCloudScale: { value: 1.0 },\n uCloudDetailScale: { value: 3.0 },\n uCloudDetailStrength: { value: 0.35 },\n uCloudErosionScale: { value: 6.0 },\n uCloudErosionStrength: { value: 0.30 },\n uCloudExtinction: { value: 0.013 },\n uCloudLightAbsorption: { value: 3.0 },\n uCloudShadowStrength: { value: 0.6 },\n uCloudScattering: { value: 1.0 },\n uCloudColor: { value: new THREE.Color(1, 1, 1) },\n uCloudShadowColor: { value: new THREE.Color(0.42, 0.47, 0.60) },\n uCloudDirectLight: { value: new THREE.Color(1.0, 0.94, 0.82) },\n uCloudAmbientTop: { value: new THREE.Color(0.18, 0.23, 0.31) },\n uCloudAmbientBottom: { value: new THREE.Color(0.13, 0.16, 0.22) },\n uCloudGroundBounce: { value: new THREE.Color(0.05, 0.04, 0.03) },\n uCloudAtmosphereInfluence: { value: 1.0 },\n uCloudSunResponse: { value: 1.0 },\n uCloudAmbientResponse: { value: 1.0 },\n uCloudSilverLining: { value: 0.25 },\n uCloudWind: { value: new THREE.Vector3() },\n uCloudNoiseOffset: { value: new THREE.Vector3() },\n uCloudVariationOffset: { value: new THREE.Vector3() },\n uCloudNoiseType: { value: 0 },\n uCloudDomainOrigin: { value: new THREE.Vector3() },\n uCloudRotation: { value: 0.0 },\n uCloudTime: { value: 0.0 },\n uCloudSelfShadow: { value: 1.0 },\n uCloudSunDir: { value: new THREE.Vector3(0.4, 0.7, 0.5).normalize() },\n uCloudStepScale: { value: 1.0 },\n uCloudEvolve: { value: 0.03 },\n tSceneDepth: { value: null },\n uDepthResolution: { value: new THREE.Vector2(1, 1) },\n uProjectionMatrixInverse: { value: new THREE.Matrix4() },\n uViewMatrixInverse: { value: new THREE.Matrix4() },\n uDepthBias: { value: 2.0 },\n uUseDepth: { value: 0.0 },\n uCloudOccupancy: { value: null },\n uUseOccupancy: { value: 0.0 },\n };\n if (chunk) {\n // 4 inward sector planes through the planet origin (set per chunk)\n uniforms.uCellNormals = { value: [\n new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0),\n new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, -1, 0),\n ] };\n }\n return new THREE.ShaderMaterial({\n uniforms,\n defines: {\n CLOUD_STEPS: Math.max(8, Math.round(steps)),\n CLOUD_LIGHT_STEPS: Math.max(1, Math.round(lightSteps)),\n CLOUD_OCTAVES: Math.max(1, Math.round(octaves)),\n CLOUD_DETAIL_OCTAVES: Math.max(0, Math.round(detailOctaves)),\n CLOUD_USE_EROSION: useErosion ? 1 : 0,\n CLOUD_LIGHT_MODE: lightMode ? 1 : 0,\n CLOUD_CHUNK: chunk ? 1 : 0,\n },\n vertexShader: VERTEX,\n fragmentShader: FRAGMENT,\n transparent: true,\n depthWrite: false,\n depthTest: false, // far-side occlusion handled analytically + depth clamp\n side: THREE.BackSide, // full-disc coverage from inside and outside\n });\n}\n","import * as THREE from 'three';\nimport { createCloudMaterial } from './CloudVolumeShader.js';\nimport { resolveCloudQuality, cloudNoiseOffset, resolveCloudNoiseType } from './CloudSettings.js';\nimport { renderTerrainCloudShadow } from './CloudShadowPass.js';\nimport { buildOccupancyOctahedral } from './cloudFieldCPU.js';\nimport { CloudLowResPass } from './CloudLowResPass.js';\nimport { applyCloudLightingState } from './CloudLightingState.js';\nimport { CloudOccupancyPass } from './CloudOccupancyPass.js';\n\n// Resolution of the directional occupancy grid (octahedral). Low-res + dilated\n// is enough: it only needs to say \"this column has some cloud\" so the shader can\n// skip the expensive density over empty sky.\nconst OCC_SIZE = 48;\n\n// The cloud altitude/thickness defaults (and the slider ranges) were tuned for\n// the default planet radius. They're world-unit offsets, so on a much smaller\n// planet they'd dominate and the cloud shell would balloon far above the\n// surface (looking like a second, larger planet). Scale them by the radius\n// ratio so the shell stays proportional at any planet size.\nconst REFERENCE_PLANET_RADIUS = 16000;\n\n// ============================================================================\n// PlanetCloudLayer: planet-side manager for the volumetric cloud shell. Owns\n// one sphere mesh (sized to the OUTER cloud radius) + the cloud material, and\n// keeps everything in sync with the planet radius, the cloud params, the sun\n// direction and the animation clock.\n//\n// The mesh only defines the render area; the visible volume comes from the\n// material's raymarch. The layer is fully self-contained — creating/destroying\n// it never touches the planet world, water shell, LOD or export logic.\n//\n// Quality (raymarch step count) is a compile-time #define, so changing it\n// rebuilds the material. The caller can pass an async compile hook so the swap\n// happens in the background with no frame hang (mirrors the terrain octave\n// recompile path in Engine).\n// ============================================================================\n\nexport class PlanetCloudLayer {\n /**\n * @param {THREE.Scene} scene\n * @param {object} opts\n * @param {number} opts.planetRadius\n * @param {(mats: THREE.Material[]) => Promise<void>} [opts.compile] background warmup hook\n */\n constructor(scene, opts = {}) {\n this.scene = scene;\n this.planetRadius = opts.planetRadius || 16000;\n this._compile = opts.compile || null;\n\n this._steps = 24;\n this._lightSteps = 6;\n this._octaves = 5;\n this._detailOctaves = 4;\n this._useErosion = true;\n this._lightMode = 0;\n this._stepLOD = false;\n this._adaptiveScaleMultiplier = 1;\n this._adaptiveStepScale = 1;\n this._baseRenderScale = 1;\n this._lowRes = false; // half/quarter-res cloud render + bilateral upscale\n this._lowResPass = new CloudLowResPass();\n this._enabled = false;\n this._inRange = true;\n this._maxDistance = Infinity;\n this._rotation = 0;\n this._wind = new THREE.Vector3();\n this._lastParams = null;\n this._compileToken = 0;\n this._pendingCompile = null;\n\n // scene-depth prepass (terrain occlusion of the clouds, like the studio slab)\n this._depthTarget = null;\n this._depthTexture = null;\n this._depthSize = new THREE.Vector2();\n this._prevClearColor = new THREE.Color();\n\n // directional occupancy grid (empty-space-skip acceleration; rebuilt on a\n // throttle since wind/rotation drift the field slowly)\n this._occData = new Uint8Array(OCC_SIZE * OCC_SIZE);\n this._occScratch = new Uint8Array(OCC_SIZE * OCC_SIZE);\n this._occupancyRatio = 0;\n this._occupancyUseful = true;\n this._occTex = new THREE.DataTexture(this._occData, OCC_SIZE, OCC_SIZE, THREE.RedFormat, THREE.UnsignedByteType);\n this._occTex.minFilter = THREE.LinearFilter;\n this._occTex.magFilter = THREE.LinearFilter;\n this._occTex.generateMipmaps = false;\n this._occTex.needsUpdate = true;\n this._occBuiltAt = 0;\n this._occupancyPass = null;\n\n this._renderer = opts.renderer || null;\n this.material = this._createMaterial();\n if (opts.renderer && this._usesOccupancy) {\n this._occupancyPass = new CloudOccupancyPass(\n opts.renderer,\n this.material.uniforms,\n { size: OCC_SIZE, planet: true },\n );\n }\n this._applyOccupancyUniforms();\n this.mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 64, 48), this.material);\n this.mesh.frustumCulled = false;\n this.mesh.renderOrder = 20; // after terrain (default) + water (10)\n this.mesh.visible = false;\n this.scene.add(this.mesh);\n }\n\n // Subclass hooks (the realistic renderer swaps the material and has no\n // occupancy grid).\n get _usesOccupancy() { return true; }\n\n _createMaterial() {\n return createCloudMaterial(this._steps, this._lightSteps, this._octaves, this._detailOctaves, this._useErosion, this._lightMode);\n }\n\n /** True when clouds are enabled, in range, and not in the 'off' fallback. */\n get active() {\n return this._enabled && this._inRange;\n }\n\n /**\n * Push the full cloud param set into the layer. Cheap and idempotent — call\n * it whenever a cloud param changes or the planet radius changes.\n * @param {object} params engine params (with cloud* keys)\n * @param {number} planetRadius\n * @param {object} [perf] centralized performance settings\n */\n applyParams(params, planetRadius, perf) {\n this.planetRadius = planetRadius || this.planetRadius;\n this._lastParams = params;\n\n const config = perf ? { ...params, ...perf } : params;\n const q = resolveCloudQuality(config);\n this._enabled = !!params.cloudsEnabled && !q.disabled;\n\n const maxDistMult = config.cloudMaxDistance ?? 6;\n this._maxDistance = maxDistMult * this.planetRadius;\n\n const u = this.material.uniforms;\n const r = this.planetRadius;\n // keep the shell proportional to planet size (see REFERENCE_PLANET_RADIUS)\n const radiusScale = r / REFERENCE_PLANET_RADIUS;\n const inner = r + (params.cloudAltitude ?? 240) * radiusScale;\n const outer = inner + Math.max(20, (params.cloudThickness ?? 620) * radiusScale);\n u.uCloudInner.value = inner;\n u.uCloudOuter.value = outer;\n\n // size the shell mesh to the outer radius (+ a hair so back faces never\n // clip the analytic outer sphere at grazing angles)\n this.mesh.scale.setScalar(outer * 1.001);\n\n // frequencies are user-relative; scale by radius so a given slider value\n // means the same world-size feature on any planet size.\n const fScale = 1.0 / r;\n u.uCloudScale.value = (params.cloudScale ?? 2.2) * fScale;\n u.uCloudDetailScale.value = (params.cloudDetailScale ?? 7.0) * fScale;\n u.uCloudErosionScale.value = (params.cloudErosionScale ?? 15.0) * fScale;\n u.uCloudVariationOffset.value.fromArray(cloudNoiseOffset(params.cloudNoiseSeed));\n u.uCloudNoiseType.value = resolveCloudNoiseType(params);\n this._occBuiltAt = 0;\n u.uCloudDetailStrength.value = params.cloudDetailStrength ?? 0.35;\n u.uCloudErosionStrength.value = params.cloudErosionStrength ?? 0.30;\n\n u.uCloudCoverage.value = params.cloudCoverage ?? 0.5;\n u.uCloudSoftness.value = Math.max(0.01, params.cloudSoftness ?? 0.16);\n\n // optical-depth gain folds in the density slider, normalized by thickness\n // so density behaves consistently across shell sizes.\n const thickness = outer - inner;\n u.uCloudExtinction.value = (params.cloudDensity ?? 1.0) * 8.0 / Math.max(thickness, 1);\n u.uCloudLightAbsorption.value = params.cloudLightAbsorption ?? 3.0;\n u.uCloudShadowStrength.value = params.cloudShadowStrength ?? 0.6;\n u.uCloudScattering.value = params.cloudScatteringStrength ?? 1.0;\n u.uCloudAtmosphereInfluence.value = params.cloudAtmosphereInfluence ?? 1.0;\n u.uCloudSunResponse.value = params.cloudSunResponse ?? 1.0;\n u.uCloudAmbientResponse.value = params.cloudAmbientResponse ?? 1.0;\n u.uCloudSilverLining.value = params.cloudSilverLining ?? 0.25;\n u.uCloudSelfShadow.value = q.selfShadow ? 1.0 : 0.0;\n this._stepLOD = q.stepLOD;\n if (!this._stepLOD) u.uCloudStepScale.value = 1.0;\n\n // low-res cloud render + depth-aware upscale (perf). scale 1.0 = off.\n this._baseRenderScale = config.cloudRenderScale ?? 1.0;\n this.setAdaptiveQuality(this._adaptiveScaleMultiplier, this._adaptiveStepScale);\n\n if (params.cloudColor) u.uCloudColor.value.setRGB(...params.cloudColor);\n if (params.cloudShadowColor) u.uCloudShadowColor.value.setRGB(...params.cloudShadowColor);\n\n // wind drift vector in the XZ plane (heading in degrees), scaled by speed.\n // NOISE-SPACE units/sec (not world units, no fScale): drift lives in baseP =\n // q*uCloudScale + drift, so this is radius-independent and the same order as\n // the evolution, making clouds actually traverse the sky rather than only\n // morph in place. (The planet also drifts via uCloudRotation.) The old\n // `0.6 * fScale` was ~100× weaker and read as static.\n const wa = (params.cloudWindDir ?? 45) * Math.PI / 180;\n const wspeed = (params.cloudWindSpeed ?? 1.0) * 0.045;\n this._wind.set(Math.cos(wa), 0, Math.sin(wa)).multiplyScalar(wspeed);\n u.uCloudWind.value.copy(this._wind);\n\n this._rotSpeed = (params.cloudRotationSpeed ?? 0.35) * 0.01;\n\n // evolution rate in noise-space units/sec (radius-independent — it scrolls\n // the noise domain, not world space). Drives the form/morph/dissipate motion.\n u.uCloudEvolve.value = (params.cloudEvolveSpeed ?? 1.0) * 0.03;\n\n // recompile if the step counts or noise settings changed (quality / fallback)\n // We check and rebuild at the end so _rebuildMaterial can copy the fully updated uniforms to the new material.\n if (q.steps !== this._steps ||\n q.lightSteps !== this._lightSteps ||\n q.octaves !== this._octaves ||\n q.detailOctaves !== this._detailOctaves ||\n q.useErosion !== this._useErosion ||\n q.lightMode !== this._lightMode) {\n this._rebuildMaterial(q.steps, q.lightSteps, q.octaves, q.detailOctaves, q.useErosion, q.lightMode);\n }\n }\n\n setLighting(lightingState) {\n applyCloudLightingState(this.material?.uniforms, lightingState);\n }\n\n setAdaptiveQuality(scaleMultiplier = 1, stepMultiplier = 1) {\n this._adaptiveScaleMultiplier = Math.max(0, Math.min(1, scaleMultiplier));\n this._adaptiveStepScale = Math.max(0.5, Math.min(1, stepMultiplier));\n const scale = Math.max(\n 0.25,\n Math.min(1, this._baseRenderScale * this._adaptiveScaleMultiplier),\n );\n this._lowRes = scale < 0.999 && this._enabled;\n this._lowResPass.scale = scale;\n this._lowResPass.setMeshLayer(this.mesh, this._lowRes);\n }\n\n get effectiveRenderScale() {\n return this._lowResPass?.scale ?? 1;\n }\n\n _compileMaterial(material) {\n const token = ++this._compileToken;\n if (!this._compile) return { token, promise: Promise.resolve({ ready: true }) };\n\n let promise;\n try {\n promise = Promise.resolve(this._compile([material]));\n } catch (e) {\n promise = Promise.reject(e);\n }\n\n const done = promise.then((result) => {\n if (result?.ready === false || result?.aborted === true) {\n throw new Error('Planet cloud shader did not become ready');\n }\n return result;\n });\n this._pendingCompile = { material, promise: done };\n\n const clearPending = () => {\n if (this._pendingCompile?.promise === done) this._pendingCompile = null;\n };\n done.then(clearPending, clearPending);\n\n return { token, promise: done };\n }\n\n _compileCurrentMaterial() {\n return this._compileMaterial(this.material).promise;\n }\n\n warmup() {\n // If a material rebuild is already compiling (e.g. perf settings applied a\n // non-default quality/light mode before warmup ran), defer to it. Starting\n // a fresh compile here would bump _compileToken and make the rebuild's\n // deferred swap bail, discarding the just-built material.\n if (this._pendingCompile) return this._pendingCompile.promise;\n return this._compileCurrentMaterial();\n }\n\n _disposeWhenSafe(material, pending) {\n if (!material) return;\n if (pending) pending.then(() => material.dispose(), () => material.dispose());\n else material.dispose();\n }\n\n /** Point the current material at the occupancy texture (after create/rebuild). */\n _applyOccupancyUniforms() {\n const u = this.material.uniforms;\n if (this._occupancyPass) this._occupancyPass.setUniforms(u);\n if (u.uCloudOccupancy) {\n u.uCloudOccupancy.value = this._occupancyPass?.texture || this._occTex;\n }\n }\n\n /** Rebuild the directional occupancy grid from the current field params. Cheap\n * (one FBM sample per texel of a 48² map) and throttled by the caller. */\n _rebuildOccupancy() {\n const u = this.material.uniforms;\n if (this._occupancyPass) {\n this._occupancyPass.render();\n this._occupancyRatio = null;\n this._occupancyUseful = true;\n u.uUseOccupancy.value = 1.0;\n return;\n }\n const inner = u.uCloudInner.value, outer = u.uCloudOuter.value;\n const w = u.uCloudWind.value;\n const occupancyRatio = buildOccupancyOctahedral(this._occData, OCC_SIZE, inner, outer, {\n scale: u.uCloudScale.value,\n noiseType: u.uCloudNoiseType.value,\n offsetX: u.uCloudVariationOffset.value.x,\n offsetY: u.uCloudVariationOffset.value.y,\n offsetZ: u.uCloudVariationOffset.value.z,\n windX: w.x, windY: w.y, windZ: w.z,\n time: u.uCloudTime.value,\n rotation: u.uCloudRotation.value,\n coverage: u.uCloudCoverage.value,\n softness: u.uCloudSoftness.value,\n octaves: this._octaves,\n evolve: u.uCloudEvolve.value,\n // conservative upper-bound margin for the detail noise the GPU adds\n boost: (u.uCloudDetailStrength.value || 0) * 0.5 + 0.03,\n }, 2, this._occScratch);\n this._occTex.needsUpdate = true;\n this._occupancyRatio = occupancyRatio;\n this._occupancyUseful = occupancyRatio > 0 && occupancyRatio < 0.78;\n u.uUseOccupancy.value = this._occupancyUseful ? 1.0 : 0.0;\n }\n\n /** Swap the cloud material for a new step count (compile-time #define). */\n _rebuildMaterial(steps, lightSteps, octaves, detailOctaves, useErosion, lightMode = this._lightMode) {\n this._steps = steps;\n this._lightSteps = lightSteps;\n this._octaves = octaves;\n this._detailOctaves = detailOctaves;\n this._useErosion = useErosion;\n this._lightMode = lightMode;\n const previous = this.material;\n const pendingPrevious = this._pendingCompile?.material === previous\n ? this._pendingCompile.promise\n : null;\n const next = createCloudMaterial(steps, lightSteps, octaves, detailOctaves, useErosion, lightMode);\n // carry over current uniform values\n const copyLiveUniforms = () => {\n const a = previous.uniforms, b = next.uniforms;\n for (const k in b) {\n if (!(k in a)) continue;\n const av = a[k].value, bv = b[k].value;\n if (av && av.copy && bv && bv.copy) bv.copy(av);\n else b[k].value = a[k].value;\n }\n };\n copyLiveUniforms();\n const { token, promise } = this._compileMaterial(next);\n promise.then(() => {\n if (token !== this._compileToken || this.material !== previous) {\n next.dispose();\n return;\n }\n // Shape/variation controls may change while the new quality program links.\n copyLiveUniforms();\n this.mesh.material = next;\n this.material = next;\n this._applyOccupancyUniforms();\n this._disposeWhenSafe(previous, pendingPrevious);\n }, () => next.dispose());\n }\n\n /** Per-frame: advance animation, refresh sun + camera-distance culling. */\n update(dt, cameraPos, sunDir) {\n if (!this._enabled) {\n if (this.mesh.visible) this.mesh.visible = false;\n return;\n }\n // distance-based optimization: hide the (expensive) shell when far away\n const dist = cameraPos.length(); // planet centered at origin\n this._inRange = dist <= this._maxDistance;\n this.mesh.visible = this._inRange;\n if (!this._inRange) return;\n\n const u = this.material.uniforms;\n // step-LOD: full quality near the surface, ramping down to 0.4 at the cull\n // distance so distant frames cost far fewer marched samples.\n let distanceStepScale = 1.0;\n if (this._stepLOD && Number.isFinite(this._maxDistance)) {\n const near = this.planetRadius;\n const far = this._maxDistance;\n const f = far > near ? (dist - near) / (far - near) : 0;\n distanceStepScale = Math.max(0.4, Math.min(1.0, 1.0 - f * 0.6));\n }\n u.uCloudStepScale.value = distanceStepScale * this._adaptiveStepScale;\n u.uCloudTime.value += dt;\n this._rotation += dt * (this._rotSpeed || 0);\n u.uCloudRotation.value = this._rotation;\n if (sunDir) u.uCloudSunDir.value.copy(sunDir);\n\n // refresh the empty-space-skip occupancy grid on a throttle (the field drifts\n // slowly with wind/rotation; the dilation margin absorbs the lag)\n const now = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const occupancyInterval = this._occupancyUseful ? 250 : 1000;\n if (now - this._occBuiltAt > occupancyInterval) {\n this._occBuiltAt = now;\n this._rebuildOccupancy();\n }\n }\n\n /** Bind depth produced by the real scene render (no duplicate scene pass). */\n useSceneDepth(depthTexture, camera, baseSize = null) {\n const u = this.material.uniforms;\n if (!this.active || !depthTexture) {\n u.uUseDepth.value = 0.0;\n return false;\n }\n const size = baseSize || depthTexture.image || {};\n const width = size.x ?? size.width ?? 1;\n const height = size.y ?? size.height ?? 1;\n u.tSceneDepth.value = depthTexture;\n u.uDepthResolution.value.set(width, height);\n u.uProjectionMatrixInverse.value.copy(camera.projectionMatrixInverse);\n u.uViewMatrixInverse.value.copy(camera.matrixWorld);\n u.uUseDepth.value = 1.0;\n return true;\n }\n\n /** Render the opaque scene depth (clouds hidden) so the cloud march can clamp\n * to the terrain — fixes clouds showing through the surface up close. Mirrors\n * CloudSlabLayer.renderDepthPrepass. Call once per frame before the main render. */\n renderDepthPrepass(renderer, camera, baseSize = null) {\n if (!this.active) {\n this.material.uniforms.uUseDepth.value = 0.0;\n return false;\n }\n this._ensureDepthTarget(renderer, baseSize);\n\n const wasVisible = this.mesh.visible;\n const prevTarget = renderer.getRenderTarget();\n const prevClearAlpha = renderer.getClearAlpha();\n renderer.getClearColor(this._prevClearColor);\n\n try {\n this.mesh.visible = false;\n renderer.setRenderTarget(this._depthTarget);\n renderer.setClearColor(0x000000, 1);\n renderer.clear(true, true, true);\n renderer.render(this.scene, camera);\n } finally {\n this.mesh.visible = wasVisible;\n renderer.setRenderTarget(prevTarget);\n renderer.setClearColor(this._prevClearColor, prevClearAlpha);\n }\n\n return this.useSceneDepth(this._depthTexture, camera, this._depthTarget);\n }\n\n /** True while low-res cloud mode is active (mesh drawn offscreen + composited). */\n get usesLowRes() {\n return this._lowRes && this.active && this._inRange;\n }\n\n /** March the clouds into the low-res target (after renderDepthPrepass, before\n * the main scene render). */\n renderLowRes(renderer, camera, baseSize = null) {\n if (!this.usesLowRes) return false;\n this._lowResPass.renderCloud(renderer, this.scene, camera, this.mesh, baseSize);\n return true;\n }\n\n /** Composite the low-res clouds over the current target (after the main render). */\n compositeLowRes(renderer, sceneDepthTexture = this._depthTexture) {\n if (!this.usesLowRes) return;\n this._lowResPass.composite(renderer, sceneDepthTexture);\n }\n\n _ensureDepthTarget(renderer, baseSize = null) {\n const size = baseSize || renderer.getDrawingBufferSize(this._depthSize);\n const w = Math.max(1, Math.round(size.x));\n const h = Math.max(1, Math.round(size.y));\n if (this._depthTarget && this._depthTarget.width === w && this._depthTarget.height === h) return;\n\n if (this._depthTarget) this._depthTarget.dispose();\n this._depthTexture = new THREE.DepthTexture(w, h);\n this._depthTexture.type = THREE.UnsignedIntType;\n this._depthTexture.format = THREE.DepthFormat;\n this._depthTarget = new THREE.WebGLRenderTarget(w, h, {\n depthTexture: this._depthTexture,\n depthBuffer: true,\n stencilBuffer: false,\n });\n this._depthTarget.texture.minFilter = THREE.NearestFilter;\n this._depthTarget.texture.magFilter = THREE.NearestFilter;\n this._depthTarget.texture.generateMipmaps = false;\n }\n\n renderTerrainShadow(sun, tiles) {\n return renderTerrainCloudShadow(this, sun, true, tiles);\n }\n\n dispose() {\n this._shadowPass?.dispose();\n if (this._depthTarget) {\n this._depthTarget.dispose();\n this._depthTarget = null;\n this._depthTexture = null;\n }\n if (this._occTex) { this._occTex.dispose(); this._occTex = null; }\n if (this._occupancyPass) {\n this._occupancyPass.dispose();\n this._occupancyPass = null;\n }\n if (this._lowResPass) { this._lowResPass.dispose(); this._lowResPass = null; }\n this.scene.remove(this.mesh);\n this.mesh.geometry.dispose();\n this.material.dispose();\n this.mesh = null;\n this.material = null;\n }\n}\n","import * as THREE from 'three';\nimport {\n NOISE_VOLUME_FRAGMENT,\n WEATHER_CUBE_FRAGMENT,\n WEATHER_FLAT_FRAGMENT,\n} from './realisticCloudGLSL.js';\n\n// ============================================================================\n// GPU inputs of the realistic cloud mode (port of the Procedural Planets\n// bakes):\n// noise volumes 64^3 tileable Perlin-Worley (RG8) + Worley fbm (R8),\n// baked once per renderer and shared by every layer\n// weather field r = cloud field, g = cloud type. It evolves through\n// keyframes WEATHER_STEP apart: the shader crossfades A -> B\n// while the keyframe after B is baked into the third target.\n// Cubemap (planet, one face per frame) or a 2D window over\n// world XZ (flat, re-centred as the wind drifts it).\n// ============================================================================\n\nconst NOISE_SIZE = 64;\nconst WEATHER_STEP = 0.004;\nexport const WEATHER_SIZE = 512;\n\nconst WEATHER_TARGET = {\n type: THREE.UnsignedByteType,\n format: THREE.RGFormat,\n minFilter: THREE.LinearFilter,\n magFilter: THREE.LinearFilter,\n wrapS: THREE.ClampToEdgeWrapping,\n wrapT: THREE.ClampToEdgeWrapping,\n depthBuffer: false,\n stencilBuffer: false,\n generateMipmaps: false,\n};\n\nconst FULLSCREEN_VERTEX = /* glsl */ `\nvoid main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nfunction screenMaterial(fragmentShader, uniforms) {\n return new THREE.ShaderMaterial({\n vertexShader: FULLSCREEN_VERTEX,\n fragmentShader,\n uniforms,\n depthTest: false,\n depthWrite: false,\n blending: THREE.NoBlending,\n });\n}\n\n// One fullscreen-triangle scene per renderer for every bake.\nclass Blitter {\n constructor() {\n this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);\n this.quad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2));\n this.quad.frustumCulled = false;\n this.scene = new THREE.Scene();\n this.scene.add(this.quad);\n }\n\n blit(renderer, material, target, layer = 0) {\n this.quad.material = material;\n renderer.setRenderTarget(target, layer);\n renderer.render(this.scene, this.camera);\n }\n\n dispose() {\n this.quad.geometry.dispose();\n }\n}\n\n// Saves / restores the renderer state a bake touches.\nfunction withBakeState(renderer, fn) {\n const prevTarget = renderer.getRenderTarget();\n const prevFace = renderer.getActiveCubeFace?.() ?? 0;\n const prevMip = renderer.getActiveMipmapLevel?.() ?? 0;\n const prevAutoClear = renderer.autoClear;\n const prevXr = renderer.xr?.enabled;\n try {\n renderer.autoClear = false;\n if (renderer.xr) renderer.xr.enabled = false;\n fn();\n } finally {\n renderer.setRenderTarget(prevTarget, prevFace, prevMip);\n renderer.autoClear = prevAutoClear;\n if (renderer.xr) renderer.xr.enabled = prevXr;\n }\n}\n\nconst _shared = new WeakMap();\nconst _owners = new WeakMap();\n\nexport function retainRealisticNoiseVolumes(renderer) {\n if (!renderer) return () => {};\n _owners.set(renderer, (_owners.get(renderer) || 0) + 1);\n let released = false;\n return () => {\n if (released) return; released = true;\n const count = (_owners.get(renderer) || 1) - 1;\n if (count > 0) { _owners.set(renderer, count); return; }\n _owners.delete(renderer);\n const entry = _shared.get(renderer);\n if (entry) { entry.noiseRT.dispose(); entry.erosionRT.dispose(); entry.blitter.dispose(); _shared.delete(renderer); }\n };\n}\n\n/**\n * Shared noise volumes for a renderer (baked on first use). Returns\n * { noise, erosion } 3D textures.\n */\nexport function getRealisticNoiseVolumes(renderer) {\n let entry = _shared.get(renderer);\n if (!entry) {\n const volume = (format) => {\n const rt = new THREE.WebGL3DRenderTarget(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, { depthBuffer: false });\n const t = rt.texture;\n t.format = format;\n t.type = THREE.UnsignedByteType;\n t.minFilter = THREE.LinearFilter;\n t.magFilter = THREE.LinearFilter;\n t.wrapS = t.wrapT = t.wrapR = THREE.RepeatWrapping;\n t.generateMipmaps = false;\n return rt;\n };\n entry = {\n noiseRT: volume(THREE.RGFormat),\n erosionRT: volume(THREE.RedFormat),\n baked: false,\n blitter: new Blitter(),\n };\n _shared.set(renderer, entry);\n }\n if (!entry.baked) {\n const mat = screenMaterial(NOISE_VOLUME_FRAGMENT, {\n uLayer: { value: 0 },\n uSize: { value: NOISE_SIZE },\n });\n withBakeState(renderer, () => {\n for (const rt of [entry.noiseRT, entry.erosionRT]) {\n for (let layer = 0; layer < NOISE_SIZE; layer++) {\n mat.uniforms.uLayer.value = layer;\n entry.blitter.blit(renderer, mat, rt, layer);\n }\n }\n });\n mat.dispose();\n entry.baked = true;\n }\n return { noise: entry.noiseRT.texture, erosion: entry.erosionRT.texture, blitter: entry.blitter };\n}\n\nexport function seedOffset(seed = 0) {\n // three decorrelated offsets in [-50, 50) from the integer seed\n let s = (Number(seed) >>> 0) || 1;\n const next = () => {\n s = (s + 0x6D2B79F5) >>> 0;\n let t = s;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n return new THREE.Vector3(next() * 100 - 50, next() * 100 - 50, next() * 100 - 50);\n}\n\n// ---------------------------------------------------------------------------\n// Keyframe clock shared by both weather fields: the displayed weather time\n// follows wt but waits at keyframe B until the next one is baked, then catches\n// up (never a jump).\n// ---------------------------------------------------------------------------\nclass WeatherKeyframes {\n constructor(count) {\n this.count = count;\n this.dirty = true;\n this._a = 0; this._b = 0; this._c = 1;\n this._tA = 0; this._tB = 0; this._tC = 0;\n this._shown = 0;\n this._prev = 0;\n }\n\n start(wt) {\n this._b = this._a;\n this._tA = this._tB = wt;\n this._shown = this._prev = wt;\n this.dirty = false;\n this.queue();\n }\n\n queue() {\n this._c = [0, 1, 2].find((i) => i !== this._a && i !== this._b);\n this._tC = this._tB + WEATHER_STEP;\n this.pending = true;\n }\n\n advance(wt) {\n const dw = Math.max(0, wt - this._prev);\n this._prev = wt;\n const behind = wt - this._shown > dw;\n this._shown = Math.min(this._shown + dw * (behind ? 1.5 : 1), wt, this._tB);\n if (this._shown >= this._tB && !this.pending) {\n this._a = this._b; this._tA = this._tB;\n this._b = this._c; this._tB = this._tC;\n this.queue();\n }\n const span = this._tB - this._tA;\n return span > 0 ? THREE.MathUtils.clamp((this._shown - this._tA) / span, 0, 1) : 0;\n }\n\n get late() {\n return this._prev - this._tB > WEATHER_STEP * 0.5;\n }\n}\n\n/** Planet weather: three RG8 cubemaps, one face of the next keyframe per frame. */\nexport class CubeWeatherField {\n constructor(size = WEATHER_SIZE) {\n this.size = size;\n this.targets = [0, 1, 2].map(() => new THREE.WebGLCubeRenderTarget(size, WEATHER_TARGET));\n this.keys = new WeatherKeyframes(3);\n this._face = 0;\n this._initFace = 0;\n this.material = screenMaterial(WEATHER_CUBE_FRAGMENT, {\n uSeedOffset: { value: new THREE.Vector3() },\n uWeatherTime: { value: 0 },\n uFaceSize: { value: size },\n uFace: { value: 0 },\n uCloudScale: { value: 3.2 },\n uLoopGuard: { value: 0 },\n });\n this.blend = 0;\n }\n\n /** Re-bake from scratch when the seed or system scale changes. */\n configure(scale, seedVec) {\n const u = this.material.uniforms;\n if (u.uCloudScale.value === scale && u.uSeedOffset.value.equals(seedVec)) return;\n u.uCloudScale.value = scale;\n u.uSeedOffset.value.copy(seedVec);\n this.keys.dirty = true;\n this._initFace = 0;\n }\n\n _bakeFace(renderer, blitter, idx, time, face) {\n const u = this.material.uniforms;\n u.uWeatherTime.value = time;\n u.uFace.value = face;\n blitter.blit(renderer, this.material, this.targets[idx], face);\n }\n\n update(renderer, blitter, wt) {\n const k = this.keys;\n withBakeState(renderer, () => {\n if (k.dirty) {\n for (; this._initFace < 6; this._initFace++) this._bakeFace(renderer, blitter, k._a, wt, this._initFace);\n this._initFace = 0;\n k.start(wt);\n this._face = 0;\n }\n if (k.pending) {\n do {\n this._bakeFace(renderer, blitter, k._c, k._tC, this._face);\n } while (++this._face < 6 && k.late);\n if (this._face >= 6) { this._face = 0; k.pending = false; }\n }\n });\n this.blend = k.advance(wt);\n }\n\n get current() { return this.targets[this.keys._a].texture; }\n get next() { return this.targets[this.keys._b].texture; }\n\n dispose() {\n for (const rt of this.targets) rt.dispose();\n this.material.dispose();\n }\n}\n\n/**\n * Flat weather: three RG8 2D maps over a field-space window. The window is\n * re-centred (all keyframes re-baked) when the drifted view leaves its core.\n */\nexport class FlatWeatherField {\n constructor(size = WEATHER_SIZE) {\n this.size = size;\n this.targets = [0, 1, 2].map(() => new THREE.WebGLRenderTarget(size, size, WEATHER_TARGET));\n this.keys = new WeatherKeyframes(3);\n this.center = new THREE.Vector2(Infinity, Infinity);\n this.half = 1;\n this.material = screenMaterial(WEATHER_FLAT_FRAGMENT, {\n uSeedOffset: { value: new THREE.Vector3() },\n uWeatherTime: { value: 0 },\n uFaceSize: { value: size },\n uWindowCenter: { value: new THREE.Vector2() },\n uWindowHalf: { value: 1 },\n uCloudScale: { value: 1e-3 },\n uLoopGuard: { value: 0 },\n });\n this.blend = 0;\n }\n\n configure(scale, seedVec) {\n const u = this.material.uniforms;\n if (u.uCloudScale.value === scale && u.uSeedOffset.value.equals(seedVec)) return;\n u.uCloudScale.value = scale;\n u.uSeedOffset.value.copy(seedVec);\n this.keys.dirty = true;\n }\n\n _bake(renderer, blitter, idx, time) {\n const u = this.material.uniforms;\n u.uWeatherTime.value = time;\n u.uWindowCenter.value.copy(this.center);\n u.uWindowHalf.value = this.half;\n blitter.blit(renderer, this.material, this.targets[idx]);\n }\n\n /**\n * @param {THREE.Vector2} want field-space point the window must cover\n * @param {number} half window half width (world units)\n */\n update(renderer, blitter, wt, want, half) {\n const k = this.keys;\n const moved = Math.abs(want.x - this.center.x) > this.half * 0.18\n || Math.abs(want.y - this.center.y) > this.half * 0.18\n || Math.abs(half - this.half) > this.half * 0.05;\n withBakeState(renderer, () => {\n if (moved) {\n this.center.copy(want);\n this.half = half;\n if (!k.dirty) {\n // same weather times, new window: re-bake what is shown\n this._bake(renderer, blitter, k._a, k._tA);\n if (k._b !== k._a) this._bake(renderer, blitter, k._b, k._tB);\n k.pending = true;\n }\n }\n if (k.dirty) {\n this._bake(renderer, blitter, k._a, wt);\n k.start(wt);\n }\n if (k.pending) {\n this._bake(renderer, blitter, k._c, k._tC);\n k.pending = false;\n }\n });\n this.blend = k.advance(wt);\n }\n\n get current() { return this.targets[this.keys._a].texture; }\n get next() { return this.targets[this.keys._b].texture; }\n\n dispose() {\n for (const rt of this.targets) rt.dispose();\n this.material.dispose();\n }\n}\n","import * as THREE from 'three';\nimport { CloudSlabLayer } from '../CloudSlabLayer.js';\nimport { PlanetCloudLayer } from '../PlanetCloudLayer.js';\nimport { resolveCloudQuality, CLOUD_DEFAULT_PARAMS, cloudNoiseOffset, resolveCloudNoiseType } from '../CloudSettings.js';\nimport { REALISTIC_CLOUD_VERTEX, REALISTIC_CLOUD_FRAGMENT, REALISTIC_MAX_STEPS } from './realisticCloudGLSL.js';\nimport {\n getRealisticNoiseVolumes,\n retainRealisticNoiseVolumes,\n seedOffset,\n WEATHER_SIZE,\n CubeWeatherField,\n FlatWeatherField,\n} from './RealisticCloudResources.js';\n\n// ============================================================================\n// Realistic cloud layers: the Procedural Planets cloud renderer on the\n// existing layer plumbing. They subclass the legacy layers, so the bounding\n// mesh, scene-depth occlusion, low-res bilateral upscale, background shader\n// warmup and adaptive quality are shared; only the material, the per-frame\n// bakes (noise volumes + weather keyframes) and the uniform mapping differ.\n// ============================================================================\n\nconst SUN_E = 6.0; // sun irradiance at intensity 1 (Procedural Planets HDR units)\nconst SKY_GAIN = 1.2; // engine ambient colours -> sky irradiance\nconst REFERENCE_PLANET_RADIUS = 16000;\n\nconst _v2 = new THREE.Vector2();\n\nfunction param(params, key) {\n return params[key] ?? CLOUD_DEFAULT_PARAMS[key];\n}\n\nfunction applyFormationFrequencies(u, params, billow, cellSpan) {\n // System Scale is a frequency, like legacy Cloud Scale: increasing it must\n // shrink individual clouds as well as the weather systems. Keep the default\n // appearance, and let Billow Size control their size within each system.\n const systemFrequency = Math.max(0.1, param(params, 'cloudSystemScale'))\n / CLOUD_DEFAULT_PARAMS.cloudSystemScale;\n const billowSize = Math.max(0.1, param(params, 'cloudBillowSize'));\n u.uCloudShapeFreq.value = systemFrequency / (billow * 1.6 * billowSize);\n u.uCloudDetailFreq.value = u.uCloudShapeFreq.value * 4.1;\n u.uCloudCellFreq.value = 0.33 * systemFrequency / (cellSpan * billowSize);\n}\n\nexport function createRealisticCloudMaterial({ planet = false } = {}) {\n const uniforms = {\n uLoopGuard: { value: 0 },\n uCloudNoise: { value: null },\n uCloudErosion: { value: null },\n uWeatherMap: { value: null },\n uWeatherMapNext: { value: null },\n uWeatherBlend: { value: 0 },\n uCloudShapeFreq: { value: 1e-3 },\n uCloudDetailFreq: { value: 4e-3 },\n uCloudCellFreq: { value: 3e-4 },\n uCloudWind: { value: new THREE.Vector3() },\n uCloudVariationOffset: { value: new THREE.Vector3() },\n uCloudNoiseType: { value: 0 },\n uCloudCoverage: { value: 0.5 },\n uCloudSoftness: { value: 0.18 },\n uCloudDensity: { value: 0.8 },\n uCloudDetail: { value: 0.7 },\n uCloudTowering: { value: 0.55 },\n uCloudShear: { value: 0 },\n uCloudBottom: { value: 240 },\n uCloudTop: { value: 860 },\n uCloudSilver: { value: 1 },\n uCloudColor: { value: new THREE.Vector3(1, 1, 1) },\n uCloudSkyTint: { value: new THREE.Vector3(0.78, 0.84, 0.95) },\n uCloudSteps: { value: 64 },\n uExposure: { value: 1 },\n uSunDir: { value: new THREE.Vector3(0.4, 0.7, 0.5).normalize() },\n uSunLight: { value: new THREE.Vector3(SUN_E, SUN_E * 0.94, SUN_E * 0.82) },\n uSkyTop: { value: new THREE.Vector3(0.22, 0.28, 0.37) },\n uSkyBottom: { value: new THREE.Vector3(0.16, 0.19, 0.26) },\n tSceneDepth: { value: null },\n uDepthResolution: { value: new THREE.Vector2(1, 1) },\n uProjectionMatrixInverse: { value: new THREE.Matrix4() },\n uViewMatrixInverse: { value: new THREE.Matrix4() },\n uDepthBias: { value: 2.0 },\n uUseDepth: { value: 0 },\n };\n if (planet) {\n uniforms.uCloudRotCS = { value: new THREE.Vector2(1, 0) };\n uniforms.uGroundRadius = { value: REFERENCE_PLANET_RADIUS };\n } else {\n uniforms.uFieldShift = { value: new THREE.Vector2() };\n uniforms.uWeatherCenter = { value: new THREE.Vector2() };\n uniforms.uWeatherInvSpan = { value: 1e-3 };\n uniforms.uWeatherSize = { value: WEATHER_SIZE };\n uniforms.uShearDir = { value: new THREE.Vector2(1, 0) };\n uniforms.uCloudCenter = { value: new THREE.Vector2() };\n uniforms.uCloudRadius = { value: 1500 };\n uniforms.uCloudFar = { value: 9000 };\n }\n const material = new THREE.ShaderMaterial({\n uniforms,\n defines: planet ? { CLOUD_PLANET: 1 } : {},\n vertexShader: REALISTIC_CLOUD_VERTEX,\n fragmentShader: REALISTIC_CLOUD_FRAGMENT,\n transparent: true,\n depthWrite: false,\n depthTest: false, // occlusion comes from tSceneDepth per pixel\n side: THREE.BackSide, // the bounding mesh's far faces cover the volume\n });\n material.name = planet ? 'clouds.realistic.planet' : 'clouds.realistic.flat';\n return material;\n}\n\n/** Resolved engine lighting -> the realistic material's HDR sun / sky inputs. */\nfunction applyRealisticLighting(u, state) {\n if (!u || !state) return;\n const d = state.sunDirection;\n if (d) u.uSunDir.value.set(d[0], d[1], d[2]).normalize();\n const sun = state.directLightColor;\n if (sun) u.uSunLight.value.set(sun[0] * SUN_E, sun[1] * SUN_E, sun[2] * SUN_E);\n const top = state.ambientTopColor;\n const bottom = state.ambientBottomColor;\n if (top) u.uSkyTop.value.set(top[0] * SKY_GAIN, top[1] * SKY_GAIN, top[2] * SKY_GAIN);\n if (bottom) u.uSkyBottom.value.set(bottom[0] * SKY_GAIN, bottom[1] * SKY_GAIN, bottom[2] * SKY_GAIN);\n}\n\n/** Uniforms shared by both geometries (shape, look, quality). */\nfunction applySharedParams(u, params, config, q) {\n u.uCloudVariationOffset.value.fromArray(cloudNoiseOffset(params.cloudNoiseSeed));\n u.uCloudNoiseType.value = resolveCloudNoiseType(params);\n u.uCloudCoverage.value = param(params, 'cloudCoverage');\n u.uCloudSoftness.value = Math.max(0.01, param(params, 'cloudSoftness'));\n u.uCloudDensity.value = param(params, 'cloudDensity');\n u.uCloudDetail.value = param(params, 'cloudErosion');\n u.uCloudTowering.value = param(params, 'cloudTowering');\n u.uCloudSilver.value = param(params, 'cloudForwardScatter');\n u.uCloudColor.value.fromArray(param(params, 'cloudColor'));\n u.uCloudSkyTint.value.fromArray(param(params, 'cloudSkyTint'));\n u.uExposure.value = param(params, 'cloudExposure');\n let steps = config.cloudRealisticSteps ?? 64;\n if (config.cloudFallback === 'lite') steps = Math.min(steps, 32);\n return Math.max(12, Math.min(REALISTIC_MAX_STEPS, steps)) * (q.disabled ? 0 : 1);\n}\n\n// ---------------------------------------------------------------------------\n// Flat (studio board): slab between two world-Y planes over a disc\n// ---------------------------------------------------------------------------\nexport class RealisticCloudSlabLayer extends CloudSlabLayer {\n constructor(scene, opts = {}) {\n super(scene, opts);\n this.renderMode = 'realistic';\n this._releaseNoiseVolumes = retainRealisticNoiseVolumes(opts.renderer);\n this._lowResPass.smooth = true;\n this._weather = new FlatWeatherField();\n this._fieldShift = new THREE.Vector2();\n this._windDir = new THREE.Vector2(1, 0);\n this._windSpeed = 0;\n this._noiseWind = new THREE.Vector3();\n this._noiseWindRate = new THREE.Vector3();\n this._weatherTime = 0;\n this._weatherRate = 0;\n this._weatherScale = 1e-3;\n this._seed = new THREE.Vector3();\n this._windowHalf = 1;\n this._baseSteps = 64;\n }\n\n // The camera pipeline keys its target on this. Asking for scene depth from\n // the moment the layer is enabled (not only once its program is linked)\n // keeps the target stable while a mode transition compiles the program.\n get wantsSceneDepth() {\n return this._enabled && this._inScene && this._inRange;\n }\n\n get _usesOccupancy() { return false; }\n _createMaterial() { return createRealisticCloudMaterial({ planet: false }); }\n _applyOccupancyUniforms() {}\n _rebuildOccupancy() {}\n getTerrainShadowState() { return this._shadowPass?.state ?? null; }\n\n applyParams(params, maxHeight, boardSize, perf, layout = {}) {\n this._boardSize = boardSize || this._boardSize;\n const extent = layout.extent || this._boardSize;\n const cx = layout.center?.x ?? 0;\n const cz = layout.center?.z ?? 0;\n this._coverSize = extent;\n this._center = { x: cx, z: cz };\n\n const config = perf ? { ...params, ...perf } : params;\n const q = resolveCloudQuality(config);\n this._enabled = !!params.cloudsEnabled && !q.disabled;\n this._maxDistance = (config.cloudMaxDistance ?? 6) * extent;\n\n const u = this.material.uniforms;\n const bottom = param(params, 'cloudAltitude');\n const thickness = Math.max(20, param(params, 'cloudThickness'));\n const top = bottom + thickness;\n u.uCloudBottom.value = bottom;\n u.uCloudTop.value = top;\n\n const radius = Math.max(1, layout.radius ?? extent * 0.62);\n u.uCloudRadius.value = radius;\n u.uCloudFar.value = extent * 4.0;\n u.uCloudCenter.value.set(cx, cz);\n const horiz = radius * 2.1;\n this.mesh.scale.set(horiz, Math.max(1, thickness * 1.04), horiz);\n this.mesh.position.set(cx, (bottom + top) * 0.5, cz);\n\n // Billows grow with the square root of the layer thickness (a thicker\n // layer stacks more of them into taller towers); the reference length is\n // tied to the board so a slider value means the same look at any size.\n const board = Math.max(this._boardSize, 1);\n const billow = Math.sqrt(thickness * board * 0.3);\n // Tower cells twice as wide as on a planet: the slab is mostly seen from\n // the side, where narrow cells of different heights read as streaks.\n applyFormationFrequencies(u, params, billow, thickness * 3.2);\n // shear: how far the layer top is carried downstream (world units)\n u.uCloudShear.value = param(params, 'cloudShear') * thickness * 2.2;\n this._baseSteps = applySharedParams(u, params, config, q);\n\n // Bound weather detail to the visible board instead of sampling one\n // nearly constant weather value across an entire Tile or Mini.\n const systemScale = param(params, 'cloudSystemScale');\n const weatherFrequency = Math.max(1, systemScale / CLOUD_DEFAULT_PARAMS.cloudSystemScale);\n // A bounded board must sample several weather cells. The former /34\n // baseline could put its entire disc in one clear cell for a variation seed.\n const minimumWeatherFrequency = 2.0 * systemScale / CLOUD_DEFAULT_PARAMS.cloudSystemScale;\n this._weatherScale = Math.max(systemScale * weatherFrequency * weatherFrequency / 34.0,\n minimumWeatherFrequency) / board;\n this._seed.copy(seedOffset(params.seed ?? 0)).add(u.uCloudVariationOffset.value);\n this._windowHalf = radius * 1.3 + u.uCloudShear.value;\n\n const wa = param(params, 'cloudWindDir') * Math.PI / 180;\n const windSpeed = param(params, 'cloudWindSpeed');\n this._windDir.set(Math.cos(wa), Math.sin(wa));\n u.uShearDir.value.copy(this._windDir);\n this._windSpeed = windSpeed * board * 0.02;\n this._noiseWindRate.set(1, 0.3, -0.6).multiplyScalar(windSpeed * 0.004);\n this._weatherRate = param(params, 'cloudEvolveSpeed') * 0.0021;\n\n this._baseRenderScale = config.cloudRenderScale ?? 1.0;\n this.setAdaptiveQuality(this._adaptiveScaleMultiplier, this._adaptiveStepScale);\n\n if (this._enabled && !this._ready && !this._warming && this._compile) {\n this._compileCurrentMaterial();\n }\n }\n\n setLighting(lightingState) {\n applyRealisticLighting(this.material?.uniforms, lightingState);\n }\n\n update(dt, cameraPos, sunDir) {\n if (!this._enabled || !this._inScene || !this._ready || !this._renderer) {\n if (this.mesh.visible) this.mesh.visible = false;\n return;\n }\n const c = this._center || { x: 0, z: 0 };\n const dist = Math.hypot(cameraPos.x - c.x, cameraPos.y, cameraPos.z - c.z);\n this._inRange = dist <= this._maxDistance;\n this.mesh.visible = this._inRange;\n if (!this._inRange) return;\n\n const u = this.material.uniforms;\n const vols = getRealisticNoiseVolumes(this._renderer);\n u.uCloudNoise.value = vols.noise;\n u.uCloudErosion.value = vols.erosion;\n\n this._fieldShift.addScaledVector(this._windDir, dt * this._windSpeed);\n u.uFieldShift.value.copy(this._fieldShift);\n this._noiseWind.addScaledVector(this._noiseWindRate, dt);\n u.uCloudWind.value.copy(this._noiseWind);\n this._weatherTime += dt * this._weatherRate;\n\n // the window covers the disc in field space (it drifts with the wind)\n _v2.set(c.x - this._fieldShift.x, c.z - this._fieldShift.y);\n this._weather.configure(this._weatherScale, this._seed);\n this._weather.update(this._renderer, vols.blitter, this._weatherTime, _v2, this._windowHalf);\n u.uWeatherMap.value = this._weather.current;\n u.uWeatherMapNext.value = this._weather.next;\n u.uWeatherBlend.value = this._weather.blend;\n u.uWeatherCenter.value.copy(this._weather.center);\n u.uWeatherInvSpan.value = 1 / (2 * this._weather.half);\n\n u.uCloudSteps.value = this._baseSteps * this._adaptiveStepScale;\n if (sunDir) u.uSunDir.value.copy(sunDir).normalize();\n }\n\n dispose() {\n this._releaseNoiseVolumes?.();\n this._weather?.dispose();\n this._weather = null;\n super.dispose();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Infinite world: the bounded slab follows the camera on chunk boundaries. The\n// weather lives in field space, so re-centring never changes the clouds.\n// ---------------------------------------------------------------------------\nexport class RealisticInfiniteCloudLayer extends RealisticCloudSlabLayer {\n constructor(scene, opts = {}) {\n super(scene, opts);\n this.mesh.name = 'infinite-cloud-layer';\n this._chunkSize = Math.max(1, opts.chunkSize || 256);\n this._viewRadius = Math.max(1, opts.viewRadius || 8);\n this._logicalCenter = new THREE.Vector2();\n }\n\n applyParams(params, maxHeight, boardSize, perf, layout = {}) {\n this._chunkSize = Math.max(1, layout.chunkSize || this._chunkSize);\n this._viewRadius = Math.max(1, layout.viewRadius || this._viewRadius);\n const cloudRadius = this._chunkSize * (this._viewRadius + 1) * 1.15;\n super.applyParams(params, maxHeight, boardSize, perf, {\n extent: cloudRadius / 0.62,\n center: { x: this._logicalCenter.x, z: this._logicalCenter.y },\n });\n this._maxDistance = Infinity;\n this.material.uniforms.uCloudFar.value = cloudRadius * 2.5;\n }\n\n _recenter(cameraPos) {\n const x = Math.floor(cameraPos.x / this._chunkSize) * this._chunkSize;\n const z = Math.floor(cameraPos.z / this._chunkSize) * this._chunkSize;\n if (x === this._logicalCenter.x && z === this._logicalCenter.y) return;\n this._logicalCenter.set(x, z);\n this._center = { x, z };\n this.material.uniforms.uCloudCenter.value.set(x, z);\n this.mesh.position.x = x;\n this.mesh.position.z = z;\n }\n\n update(dt, cameraPos, sunDir) {\n this._recenter(cameraPos);\n super.update(dt, cameraPos, sunDir);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Planet: spherical shell, weather cubemap that drifts around the pole axis\n// ---------------------------------------------------------------------------\nexport class RealisticPlanetCloudLayer extends PlanetCloudLayer {\n constructor(scene, opts = {}) {\n super(scene, opts);\n this.renderMode = 'realistic';\n this._releaseNoiseVolumes = retainRealisticNoiseVolumes(opts.renderer);\n this._lowResPass.smooth = true;\n this._weather = new CubeWeatherField();\n this._noiseWind = new THREE.Vector3();\n this._noiseWindRate = new THREE.Vector3();\n this._weatherTime = 0;\n this._weatherRate = 0;\n this._systemScale = 3.2;\n this._seed = new THREE.Vector3();\n this._baseSteps = 64;\n }\n\n get _usesOccupancy() { return false; }\n _createMaterial() { return createRealisticCloudMaterial({ planet: true }); }\n _applyOccupancyUniforms() {}\n _rebuildOccupancy() {}\n\n applyParams(params, planetRadius, perf) {\n this.planetRadius = planetRadius || this.planetRadius;\n this._lastParams = params;\n const config = perf ? { ...params, ...perf } : params;\n const q = resolveCloudQuality(config);\n this._enabled = !!params.cloudsEnabled && !q.disabled;\n const R = this.planetRadius;\n this._maxDistance = (config.cloudMaxDistance ?? 6) * R;\n\n const u = this.material.uniforms;\n const radiusScale = R / REFERENCE_PLANET_RADIUS;\n const inner = R + param(params, 'cloudAltitude') * radiusScale;\n const outer = inner + Math.max(20, param(params, 'cloudThickness') * radiusScale);\n const thick = outer - inner;\n u.uCloudBottom.value = inner;\n u.uCloudTop.value = outer;\n u.uGroundRadius.value = R;\n this.mesh.scale.setScalar(outer * 1.001);\n\n // noise frequencies in world units, tied to the shell thickness exactly\n // as in Procedural Planets (billows grow with sqrt of the thickness)\n const billow = Math.sqrt(thick * R * 0.009);\n applyFormationFrequencies(u, params, billow, thick * 1.6);\n // shear in direction units: how far the shell top is carried downstream\n u.uCloudShear.value = param(params, 'cloudShear') * (thick / R) * 2.2;\n this._baseSteps = applySharedParams(u, params, config, q);\n\n this._systemScale = param(params, 'cloudSystemScale');\n this._seed.copy(seedOffset(params.seed ?? 0)).add(u.uCloudVariationOffset.value);\n this._rotSpeed = param(params, 'cloudRotationSpeed') * 0.01;\n const windSpeed = param(params, 'cloudWindSpeed');\n this._noiseWindRate.set(1, 0.3, -0.6).multiplyScalar(windSpeed * 0.004);\n this._weatherRate = param(params, 'cloudEvolveSpeed') * 0.0021;\n\n this._baseRenderScale = config.cloudRenderScale ?? 1.0;\n this.setAdaptiveQuality(this._adaptiveScaleMultiplier, this._adaptiveStepScale);\n }\n\n setLighting(lightingState) {\n applyRealisticLighting(this.material?.uniforms, lightingState);\n }\n\n update(dt, cameraPos, sunDir) {\n if (!this._enabled || !this._renderer) {\n if (this.mesh.visible) this.mesh.visible = false;\n return;\n }\n this._inRange = cameraPos.length() <= this._maxDistance;\n this.mesh.visible = this._inRange;\n if (!this._inRange) return;\n\n const u = this.material.uniforms;\n const vols = getRealisticNoiseVolumes(this._renderer);\n u.uCloudNoise.value = vols.noise;\n u.uCloudErosion.value = vols.erosion;\n\n this._rotation = (this._rotation + dt * (this._rotSpeed || 0)) % (Math.PI * 2);\n u.uCloudRotCS.value.set(Math.cos(this._rotation), Math.sin(this._rotation));\n this._noiseWind.addScaledVector(this._noiseWindRate, dt);\n u.uCloudWind.value.copy(this._noiseWind);\n this._weatherTime += dt * this._weatherRate;\n\n this._weather.configure(this._systemScale, this._seed);\n this._weather.update(this._renderer, vols.blitter, this._weatherTime);\n u.uWeatherMap.value = this._weather.current;\n u.uWeatherMapNext.value = this._weather.next;\n u.uWeatherBlend.value = this._weather.blend;\n\n u.uCloudSteps.value = this._baseSteps * this._adaptiveStepScale;\n if (sunDir) u.uSunDir.value.copy(sunDir).normalize();\n }\n\n dispose() {\n this._releaseNoiseVolumes?.();\n this._weather?.dispose();\n this._weather = null;\n super.dispose();\n }\n}\n","import { effectQuality, CLOUD_QUALITY_DEFAULTS } from './EffectQuality.js';\nimport { resolveEffectHost } from './EffectHost.js';\nimport * as THREE from 'three';\nimport { validateParameters } from '../resources/ParameterValidation.js';\nimport { CloudSlabLayer } from '../../engine/sky/CloudSlabLayer.js';\nimport { InfiniteCloudLayer } from '../../engine/sky/InfiniteCloudLayer.js';\nimport { PlanetCloudLayer } from '../../engine/sky/PlanetCloudLayer.js';\nimport {\n RealisticCloudSlabLayer,\n RealisticInfiniteCloudLayer,\n RealisticPlanetCloudLayer,\n} from '../../engine/sky/realistic/RealisticCloudLayers.js';\nimport { CLOUD_DEFAULT_PARAMS } from '../../engine/sky/CloudSettings.js';\nimport { resolveCloudLightingState } from '../../engine/sky/CloudLightingState.js';\nimport { compileMaterial } from '../resources/CompileMaterial.js';\nimport { withRendererState } from '../resources/RendererState.js';\nimport { RevisionScope } from '../resources/RevisionScope.js';\n\nconst classes = {\n legacy: { finite: CloudSlabLayer, infinite: InfiniteCloudLayer, planet: PlanetCloudLayer },\n realistic: {\n finite: RealisticCloudSlabLayer,\n infinite: RealisticInfiniteCloudLayer,\n planet: RealisticPlanetCloudLayer,\n },\n};\n\nexport class TerrainClouds {\n constructor({ terrain, renderer, world, mode = 'legacy', parameters = {}, quality = {} } = {}) {\n validateParameters(parameters, CLOUD_DEFAULT_PARAMS);\n const resolvedQuality=effectQuality(quality,CLOUD_QUALITY_DEFAULTS);\n const host = resolveEffectHost({terrain,renderer,world});\n terrain=host.terrain;\n this.terrain=terrain;\n this._ownsHost=host.ownsHost;\n this.object=new THREE.Group();this.object.name='clouds';terrain.object.add(this.object);\n this.mode = mode;\n this.parameters = { ...CLOUD_DEFAULT_PARAMS, ...parameters, cloudsEnabled: parameters.cloudsEnabled ?? true };\n this.quality = resolvedQuality;\n this.layer = null;\n this.group = null;\n this.scope = new RevisionScope();\n this._detach = terrain.addLayer(this);\n }\n _apply(layer, parameters, quality = this.quality) {\n const t = this.terrain,\n c = t.configuration;\n if (t.mode === 'planet') layer.applyParams(parameters, c.layout.radius, quality);\n else\n layer.applyParams(\n parameters,\n c.heightScale * 1.35,\n c.layout.chunkCount * c.layout.chunkSize,\n quality,\n { chunkSize: c.layout.chunkSize, viewRadius: c.layout.viewRadius, ...t._miniCloudLayout },\n );\n layer.setLighting(resolveCloudLightingState({ sunDirection: t._uniforms.uSunDir.value }));\n }\n configure(patch = {}, options = {}) {\n const mode = patch.mode ?? this.mode;\n const quality=effectQuality(patch.quality,this.quality);\n if (!classes[mode]) throw new TypeError('Invalid cloud mode');\n const parameters = { ...this.parameters, ...patch.parameters };\n validateParameters(patch.parameters ?? {}, CLOUD_DEFAULT_PARAMS);\n return this.scope.run(async (check) => {\n const t = this.terrain,\n group = new THREE.Group();\n group.visible = false;\n this.object.add(group);\n let layer;\n let published = false;\n try {\n layer = new classes[mode][t.mode](group, {\n renderer: t._renderer,\n planetRadius: t.configuration.layout.radius,\n chunkSize: t.configuration.layout.chunkSize,\n viewRadius: t.configuration.layout.viewRadius,\n compile: async (mats) => {\n for (const mat of mats)\n await compileMaterial(\n t._renderer,\n mat,\n t._viewCamera ?? new THREE.PerspectiveCamera(),\n { geometry: layer.mesh.geometry.clone() },\n );\n },\n });\n this._apply(layer, parameters, quality);\n // applyParams starts the exact selected specialization's warm-up.\n if (layer._pendingCompile) await layer._pendingCompile.promise;\n else await layer.warmup?.();\n await Promise.resolve();\n check();\n if (layer._targetConfig && !layer._configMatches(layer._targetConfig)) {\n const q = layer._targetConfig;\n layer._rebuildMaterial(\n q.steps,\n q.lightSteps,\n q.octaves,\n q.detailOctaves,\n q.useErosion,\n q.lightMode,\n );\n if (layer._pendingCompile) await layer._pendingCompile.promise;\n await Promise.resolve();\n }\n if (t.mode !== 'planet' && parameters.cloudsEnabled !== false && quality.cloudFallback !== 'off' && !layer._ready)\n throw new Error('Cloud shader preparation failed');\n check();\n t._assertAlive();\n this.layer?.dispose();\n this.group?.removeFromParent();\n this.layer = layer;\n this.group = group;\n this.mode = mode;\n this.parameters = parameters;\n this.quality = quality;\n group.visible = true;\n published = true;\n } finally {\n if (!published) {\n layer?.dispose();\n group.removeFromParent();\n }\n }\n }, options);\n }\n prepare(camera, options = {}) {\n if(this._ownsHost)this.terrain.frame(0,camera);\n return this.configure({}, options);\n }\n onTerrainChanged() {\n if (this.layer) this._apply(this.layer, this.parameters);\n }\n update(dt, { camera }) {\n if(this._ownsHost)camera=this.terrain.frame(dt,camera);\n if (!this.layer) return;\n withRendererState(this.terrain._renderer, () =>\n this.layer.update(dt, camera.position, this.terrain._uniforms.uSunDir.value),\n );\n }\n beforeRender() {\n if (!this.layer) return;\n const t = this.terrain,\n u = t._uniforms;\n const shadow = this.parameters.cloudShadowsEnabled\n ? withRendererState(t._renderer, () =>\n this.layer.renderTerrainShadow?.(u.uSunDir.value, null),\n )\n : null;\n u.uTerrainCloudShadowEnabled.value = shadow ? 1 : 0;\n u.uTerrainCloudShadowStrength.value = Math.min(\n 0.85,\n Math.max(0, this.parameters.cloudShadowOpacity ?? 0.45),\n );\n u.uTerrainCloudShadowTex.value = shadow?.texture ?? null;\n if (shadow) {\n u.uTerrainCloudShadowCenter.value.copy(shadow.center);\n u.uTerrainCloudShadowExtent.value = shadow.extent;\n u.uTerrainCloudShadowAltitude.value = shadow.altitude;\n u.uTerrainCloudShadowPlanet.value = shadow.planet ? 1 : 0;\n }\n }\n serialize() {\n return {\n type: 'clouds',\n ...(this._ownsHost ? {world:{...this.terrain.world}} : {}),\n mode: this.mode,\n parameters: structuredClone(this.parameters),\n quality: { ...this.quality },\n };\n }\n getDiagnostics() {\n return {\n mode: this.mode,\n active: !!this.layer?.active,\n lowResolution: !!this.layer?.usesLowRes,\n ready: !!this.layer && (this.terrain.mode === 'planet' || !!this.layer._ready),\n };\n }\n dispose() {\n if (this.scope.disposed) return;\n this.scope.dispose();\n this._detach();\n this.layer?.dispose();\n this.group?.removeFromParent();\n this.terrain._uniforms.uTerrainCloudShadowEnabled.value = 0;\n this.layer = null;\n this.group = null;\n this.object.removeFromParent();\n if(this._ownsHost)this.terrain.dispose();\n }\n}\n\nexport async function createClouds(options) {\n const layer = new TerrainClouds(options);\n try {\n await layer.configure({}, { signal: options.signal });\n return layer;\n } catch (e) {\n layer.dispose();\n throw e;\n }\n}\n"],"names":["VERTEX","FRAGMENT","mix","scale","OCC_SIZE","REFERENCE_PLANET_RADIUS"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
|
-
import { C as COMMON_UNIFORMS_GLSL, N as NOISE_GLSL, B as BIOME_GLSL, b as buildHeightGLSL } from "./biomeGLSL-
|
|
2
|
+
import { C as COMMON_UNIFORMS_GLSL, N as NOISE_GLSL, B as BIOME_GLSL, b as buildHeightGLSL } from "./biomeGLSL-DWGDDBqT.js";
|
|
3
3
|
import { g as generateStackGLSL, d as defaultLegacyStack } from "./noiseStackCodegen-C4R9Y3L8.js";
|
|
4
4
|
import { c as compileMaterial } from "./CompileMaterial-DZiWxNZC.js";
|
|
5
5
|
import { w as withRendererState } from "./RendererState-BwgUc9ze.js";
|
|
@@ -483,4 +483,4 @@ export {
|
|
|
483
483
|
TerrainHeightCache as T,
|
|
484
484
|
createHeightCache as c
|
|
485
485
|
};
|
|
486
|
-
//# sourceMappingURL=TerrainHeightCache-
|
|
486
|
+
//# sourceMappingURL=TerrainHeightCache-DIZxi9jz.js.map
|