declare const _default: "\n\n#include \"gsplatHelpersVS\"\n#include \"gsplatOutputVS\"\n\nattribute vertex_position: vec3f;\n\nuniform viewport_size: vec4f;\n\n// -inverse(matrix_projection)[row 2]; lets the VS reconstruct linear view\n// depth from clipPos via dot(clipToViewZ, clip). Set per-camera by the\n// renderer (see GSplatHybridRenderer).\nuniform clipToViewZ: vec4f;\n\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\n    uniform alphaClip: f32;\n#else\n    uniform alphaClipForward: f32;\n#endif\n\n// Globally sorted indices into projCache (output of the radix sort).\nvar<storage, read> sortedIndices: array<u32>;\n\n// Pre-projected splat cache (8 u32 slots per splat).\nvar<storage, read> projCache: array<u32>;\n\n// Visible splat count written by compute-gsplat-projector-write-indirect-args.js.\nvar<storage, read> numSplatsStorage: array<u32>;\n\nvarying gaussianUV: half2;\nvarying gaussianColor: half4;\n\n#ifndef DITHER_NONE\n    varying id: f32;\n#endif\n\n#ifdef PREPASS_PASS\n    varying vLinearDepth: f32;\n#endif\n\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\n    varying @interpolate(flat) vPickId: u32;\n#endif\n\n#ifdef GSPLAT_OVERDRAW\n    uniform colorRampIntensity: f32;\n    var colorRamp: texture_2d<f32>;\n    var colorRampSampler: sampler;\n#endif\n\nconst discardVec: vec4f = vec4f(0.0, 0.0, 2.0, 1.0);\n\n@vertex\nfn vertexMain(input: VertexInput) -> VertexOutput {\n    var output: VertexOutput;\n\n    // Same instance/quad linearisation as gsplatSourceVS:\n    // order = instanceIdx * GSPLAT_INSTANCE_SIZE + perInstanceQuadIdx.\n    let order = pcInstanceIndex * {GSPLAT_INSTANCE_SIZE}u + u32(vertex_position.z);\n\n    let numSplats = numSplatsStorage[0];\n    if (order >= numSplats) {\n        output.position = discardVec;\n        return output;\n    }\n\n    let cacheIdx = sortedIndices[order];\n    let base = cacheIdx * {CACHE_STRIDE}u;\n\n    let proj = vec4f(\n        bitcast<f32>(projCache[base + 0u]),\n        bitcast<f32>(projCache[base + 1u]),\n        bitcast<f32>(projCache[base + 2u]),\n        bitcast<f32>(projCache[base + 3u])\n    );\n    let v1 = unpack2x16float(projCache[base + 4u]);\n    let v2 = unpack2x16float(projCache[base + 5u]);\n\n    // Color / opacity / pickId: slot 6 is either packed (rg) or a raw u32 pcId.\n    let ba = unpack2x16float(projCache[base + 7u]);\n    let alpha = half(ba.y);\n\n    #if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\n        let pickId = projCache[base + 6u];\n    #endif\n\n    #ifdef PICK_PASS\n        // In the pick path slot 6 is repurposed as the picking ID; alpha is the only\n        // colour we care about in the FS gate. Slot 7's r channel is unused.\n        var clr: half4 = half4(half(0.0), half(0.0), half(0.0), alpha);\n    #else\n        let rg = unpack2x16float(projCache[base + 6u]);\n        var clr: half4 = half4(half(rg.x), half(rg.y), half(ba.x), alpha);\n    #endif\n\n    // clipCorner: shrink the quad to exclude near-zero alpha regions (matches gsplatCommonVS per-pass threshold).\n    let cornerUV = vec2f(vertex_position.xy);\n    #if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\n        let alphaClipValue = half(uniform.alphaClip);\n    #else\n        let alphaClipValue = half(uniform.alphaClipForward);\n    #endif\n    let clip = min(half(1.0), sqrt(max(half(0.0), log(alpha / alphaClipValue))) * half(0.5));\n    let cornerClipped = cornerUV * f32(clip);\n\n    // Convert pixel-space offset into clip-space. proj.w is the real clipPos.w,\n    // so c == clip.w / viewport matches gsplatCorner.js line 97 for both\n    // perspective (w == -view.z) and orthographic (w == 1) projections.\n    let c = vec2f(proj.w) * uniform.viewport_size.zw;\n    let pixelOffset = cornerClipped.x * v1 + cornerClipped.y * v2;\n    let clipOffset = pixelOffset * c;\n\n    output.position = proj + vec4f(clipOffset, 0.0, 0.0);\n    output.gaussianUV = half2(cornerClipped);\n\n    // Reconstruct linear view depth from clip via the per-camera clipToViewZ\n    // uniform = -inverse(matrix_projection)[row 2]. For perspective this\n    // collapses to clip.w; for ortho it produces the correct -view.z. Used by\n    // fog/overdraw/prepass below.\n    let viewDepth = dot(uniform.clipToViewZ, proj);\n\n    #ifdef GSPLAT_OVERDRAW\n        // Overdraw mode renders a flat colour ramp; depth-shade input not needed.\n        let t: f32 = clamp(viewDepth / 20.0, 0.0, 1.0);\n        let rampColor: vec3f = textureSampleLevel(colorRamp, colorRampSampler, vec2f(t, 0.5), 0.0).rgb;\n        let outAlpha = alpha * half(1.0 / 32.0) * half(uniform.colorRampIntensity);\n        output.gaussianColor = half4(half3(rampColor), outAlpha);\n    #else\n        output.gaussianColor = half4(\n            half3(prepareOutputFromGamma(max(vec3f(clr.xyz), vec3f(0.0)), viewDepth)),\n            alpha\n        );\n    #endif\n\n    #ifndef DITHER_NONE\n        // Best-effort id from the cache index \u2014 used only for blue-noise dither.\n        output.id = f32(cacheIdx);\n    #endif\n\n    #ifdef PREPASS_PASS\n        output.vLinearDepth = viewDepth;\n    #endif\n\n    #if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\n        output.vPickId = pickId;\n    #endif\n\n    return output;\n}\n";
export default _default;
