/** * Procedural sky background — a single fullscreen triangle drawn at the far * plane (reverse-Z: z = 0) before any geometry. Analytic zenith/horizon/ * ground gradient plus a sun disc + glow, driven by the same sun direction * the geometry lighting uses. * * Tonemapping note: the geometry shader applies ACES + gamma at the end of * its fragment stage (not in a post pass), so the sky must apply the same * curve here or it would read as a different "film stock" than the model. */ export declare const skyShaderSource = "\n struct SkyUniforms {\n camRight: vec3,\n tanHalfFovX: f32,\n camUp: vec3,\n tanHalfFovY: f32,\n camForward: vec3,\n exposure: f32,\n sunDirection: vec3,\n sunIntensity: f32,\n zenithColor: vec3,\n _pad0: f32,\n horizonColor: vec3,\n _pad1: f32,\n groundColor: vec3,\n _pad2: f32,\n }\n @binding(0) @group(0) var sky: SkyUniforms;\n\n struct VertexOutput {\n @builtin(position) position: vec4,\n @location(0) ndc: vec2,\n }\n\n @vertex\n fn vs_main(@builtin(vertex_index) vi: u32) -> VertexOutput {\n // Fullscreen triangle: (-1,-1), (3,-1), (-1,3).\n let x = f32((vi << 1u) & 2u) * 2.0 - 1.0;\n let y = f32(vi & 2u) * 2.0 - 1.0;\n var out: VertexOutput;\n // z = 0 is the far plane under reverse-Z, so any geometry drawn\n // later wins the depth test without the sky writing depth.\n out.position = vec4(x, y, 0.0, 1.0);\n out.ndc = vec2(x, y);\n return out;\n }\n\n // Same ACES filmic curve as the geometry fragment shader.\n fn acesTonemap(c: vec3) -> vec3 {\n let a = 2.51;\n let b = 0.03;\n let cc = 2.43;\n let d = 0.59;\n let e = 0.14;\n return clamp((c * (a * c + b)) / (c * (cc * c + d) + e), vec3(0.0), vec3(1.0));\n }\n\n struct FragmentOutput {\n @location(0) color: vec4,\n // Matches the pass's object-id attachment clear value so the sky\n // never registers as a pickable entity.\n @location(1) objectIdEncoded: vec4,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragmentOutput {\n // Per-pixel view ray from the camera basis. Used for orthographic\n // cameras too \u2014 parallel rays would collapse the sky to a single\n // colour, so a perspective-style fan reads better in both modes.\n let dir = normalize(\n sky.camForward\n + input.ndc.x * sky.tanHalfFovX * sky.camRight\n + input.ndc.y * sky.tanHalfFovY * sky.camUp\n );\n let elevation = dir.y;\n\n // Horizon \u2192 zenith gradient with a slow falloff near the horizon.\n let zenithMix = pow(clamp(elevation, 0.0, 1.0), 0.45);\n var color = mix(sky.horizonColor, sky.zenithColor, zenithMix);\n\n // Below the horizon: fade quickly into the ground colour.\n let groundMix = smoothstep(0.0, -0.1, elevation);\n color = mix(color, sky.groundColor, groundMix);\n\n // Sun disc + glow. The disc is slightly oversized vs the real\n // ~0.53\u00B0 sun so it stays visible at typical canvas resolutions.\n let cosSun = dot(dir, sky.sunDirection);\n let disc = smoothstep(0.99985, 0.99995, cosSun);\n let glow = pow(max(cosSun, 0.0), 350.0) * 0.5\n + pow(max(cosSun, 0.0), 24.0) * 0.12;\n // Hide the disc once the sun sets, and never draw it on the ground.\n let sunVisible = smoothstep(-0.06, 0.02, sky.sunDirection.y) * (1.0 - groundMix);\n let sunTint = vec3(1.0, 0.92, 0.78);\n color += (disc * 6.0 + glow) * max(sky.sunIntensity, 0.0) * sunVisible * sunTint;\n\n // Match the geometry pipeline: exposure \u2192 ACES \u2192 gamma.\n color *= sky.exposure;\n color = acesTonemap(color);\n color = pow(color, vec3(1.0 / 2.2));\n\n var out: FragmentOutput;\n out.color = vec4(color, 1.0);\n out.objectIdEncoded = vec4(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n "; //# sourceMappingURL=sky.wgsl.d.ts.map