export const vertex: "\nfn splatsVS(\n // per-instance inputs\n order: u32,\n quadPos: vec3,\n\n // scene matrices (pass cameraProjectionMatrix, cameraViewMatrix, modelWorldMatrix from JS)\n projectionMatrix: mat4x4,\n viewMatrix: mat4x4,\n modelMatrix: mat4x4,\n\n // resources\n positionColor3D: texture_3d,\n covariance3D: texture_3d,\n\n // scalar uniforms\n textureSize: u32,\n sizeMultiplier: f32,\n k: f32,\n beta_k: f32,\n minSplatPixelSize: f32,\n minOpacity: f32,\n culling: u32,\n antialiasingFactor: f32,\n cropRadius: f32,\n depthBias: f32,\n viewportPixelSize: vec2,\n zUpToYUpMatrix3x3: mat3x3\n) -> vec4 {\n // compute slice coords from linear address\n let texSize: u32 = textureSize;\n let slicePixels: u32 = texSize * texSize;\n let sliceIndex: u32 = order / slicePixels;\n let slicePixelIndex: u32 = order % slicePixels;\n let xVal: u32 = slicePixelIndex % texSize;\n let yVal: u32 = slicePixelIndex / texSize;\n let coord: vec3 = vec3(i32(xVal), i32(yVal), i32(sliceIndex));\n\n // load packed position (xyz as u32 bitcasts) and color (rgba8)\n let posCol: vec4 = textureLoad(positionColor3D, coord, 0);\n var splatPosModel: vec3 = vec3(bitcast(posCol.r), bitcast(posCol.g), bitcast(posCol.b));\n // WGSL builtin to unpack 4x8 UNORM from u32\n var color: vec4 = unpack4x8unorm(posCol.a);\n\n // cull by radius\n if (length(splatPosModel) > cropRadius) {\n // write varyings via injected 'varyings' object\n varyings.vUv = quadPos.xy;\n varyings.vStds = 0.0;\n varyings.vColor = vec4(0.0);\n varyings.vSplatDepth = 1.0;\n return vec4(0.0);\n }\n\n // fetch covariance rows packed as half2\n let cov: vec4 = textureLoad(covariance3D, coord, 0);\n let c0: vec2 = unpack2x16float(cov.r);\n let c1: vec2 = unpack2x16float(cov.g);\n let c2: vec2 = unpack2x16float(cov.b);\n var covariance: mat3x3 = mat3x3(\n vec3(c0.x, c0.y, c1.x),\n vec3(c0.y, c1.y, c2.x),\n vec3(c1.x, c2.x, c2.y)\n );\n\n // rotate covariance from z-up to y-up and by model rotation\n let modelRot: mat3x3 = mat3x3(\n modelMatrix[0].xyz,\n modelMatrix[1].xyz,\n modelMatrix[2].xyz\n );\n let modelRotT: mat3x3 = transpose(modelRot);\n covariance = transpose(zUpToYUpMatrix3x3) * covariance * zUpToYUpMatrix3x3;\n covariance = modelRotT * covariance * modelRot;\n covariance = covariance * (sizeMultiplier * sizeMultiplier);\n\n // threshold-based stds for opacity falloff\n let maxV: f32 = max(color.a, 0.0001);\n let thresh: f32 = min(minOpacity, maxV);\n if (thresh >= maxV) {\n varyings.vUv = quadPos.xy;\n varyings.vStds = 0.0;\n varyings.vColor = vec4(0.0);\n varyings.vSplatDepth = 1.0;\n return vec4(0.0);\n }\n let lnRatio: f32 = log(thresh / maxV);\n var stds: f32 = pow(-8.0 * lnRatio / beta_k, 1.0 / k);\n\n // world position\n let rotatedModel: vec3 = zUpToYUpMatrix3x3 * splatPosModel;\n let splatWorld: vec3 = (modelMatrix * vec4(rotatedModel, 1.0)).xyz;\n\n // depth without and with bias\n var splatView: vec4 = viewMatrix * vec4(splatWorld, 1.0);\n let splatProj: vec4 = projectionMatrix * splatView;\n splatView.z = splatView.z + depthBias;\n let splatProjBias: vec4 = projectionMatrix * splatView;\n let splatDepthWithBias: f32 = (splatProjBias.z / splatProjBias.w) * 0.5 + 0.5;\n\n // screen-space jacobian\n let posCam: vec3 = (viewMatrix * vec4(splatWorld, 1.0)).xyz;\n let invZ: f32 = 1.0 / posCam.z;\n let invZ2: f32 = invZ * invZ;\n let fx: f32 = projectionMatrix[0][0];\n let fy: f32 = projectionMatrix[1][1];\n let j0: vec3 = vec3(fx * invZ, 0.0, -fx * posCam.x * invZ2);\n let j1: vec3 = vec3(0.0, fy * invZ, -fy * posCam.y * invZ2);\n let viewRot: mat3x3 = mat3x3(\n viewMatrix[0].xyz,\n viewMatrix[1].xyz,\n viewMatrix[2].xyz\n );\n let viewRotT: mat3x3 = transpose(viewRot);\n let j0W: vec3 = viewRotT * j0 * 4.0;\n let j1W: vec3 = viewRotT * j1 * 4.0;\n let tmp0: vec3 = covariance * j0W;\n let tmp1: vec3 = covariance * j1W;\n var a: f32 = dot(j0W, tmp0);\n var b: f32 = dot(j0W, tmp1);\n var c: f32 = dot(j1W, tmp1);\n let sigmaNDC: f32 = (antialiasingFactor / viewportPixelSize.x) * 2.0;\n let k2: f32 = sigmaNDC * sigmaNDC;\n let detOrig: f32 = a * c - b * b;\n a = a + k2;\n c = c + k2;\n let detBlur: f32 = a * c - b * b;\n color.a = color.a * sqrt(clamp(detOrig / detBlur, 0.0, 1.0 - 1.0e-6));\n if (color.a < 0.01) {\n varyings.vUv = quadPos.xy;\n varyings.vStds = 0.0;\n varyings.vColor = vec4(0.0);\n varyings.vSplatDepth = 1.0;\n return vec4(0.0);\n }\n\n // ellipse axes and quad extrusion\n let halfTrace: f32 = 0.5 * (a + c);\n let rootTerm: f32 = sqrt(max(halfTrace * halfTrace - (a * c - b * b), 0.0));\n let lambda1: f32 = halfTrace + rootTerm;\n let lambda2: f32 = halfTrace - rootTerm;\n if (min(lambda2, lambda1) <= 0.0) {\n varyings.vUv = quadPos.xy;\n varyings.vStds = 0.0;\n varyings.vColor = vec4(0.0);\n varyings.vSplatDepth = 1.0;\n return vec4(0.0);\n }\n var eig1: vec2;\n if (abs(b) < 1e-7) {\n if (a >= c) {\n eig1 = vec2(1.0, 0.0);\n } else {\n eig1 = vec2(0.0, 1.0);\n }\n } else {\n eig1 = normalize(vec2(b, lambda1 - a));\n }\n var eig2: vec2 = vec2(-eig1.y, eig1.x);\n eig1 = eig1 * sqrt(lambda1) * 2.0;\n eig2 = eig2 * sqrt(lambda2) * 2.0;\n let alpha: f32 = dot(j0, j0);\n let betaV: f32 = dot(j0, j1);\n let gammaV: f32 = dot(j1, j1);\n let invDet: f32 = 1.0 / (alpha * gammaV - betaV * betaV);\n var deltaCam1: vec3 = (gammaV * eig1.x - betaV * eig1.y) * j0 + (-betaV * eig1.x + alpha * eig1.y) * j1;\n var deltaCam2: vec3 = (gammaV * eig2.x - betaV * eig2.y) * j0 + (-betaV * eig2.x + alpha * eig2.y) * j1;\n deltaCam1 = deltaCam1 * invDet * 0.5;\n deltaCam2 = deltaCam2 * invDet * 0.5;\n let axisW1: vec3 = viewRotT * deltaCam1;\n let axisW2: vec3 = viewRotT * deltaCam2;\n\n let outWorld: vec3 = splatWorld + (quadPos.x * axisW1 + quadPos.y * axisW2) * stds;\n let outPos: vec4 = projectionMatrix * viewMatrix * vec4(outWorld, 1.0);\n\n // write varyings\n varyings.vUv = quadPos.xy;\n varyings.vStds = stds;\n varyings.vColor = color;\n varyings.vSplatDepth = splatDepthWithBias;\n\n return outPos;\n}\n"; export const fragment: "\nfn splatsFS(\n vUv: vec2,\n vStds: f32,\n vColor: vec4,\n k: f32,\n beta_k: f32\n) -> vec4 {\n // cheap quad-circle discard\n if (dot(vUv, vUv) > 0.25) {\n return vec4(0.0);\n }\n let p: vec2 = vUv * vStds;\n let r2: f32 = dot(p, p);\n let rk: f32 = pow(r2, 0.5 * k);\n let alpha: f32 = vColor.a * exp(-beta_k * rk);\n let corrected: vec3 = pow(vColor.rgb, vec3(1.0 / 2.2));\n return vec4(corrected, alpha);\n}\n"; export const depth: "\nfn splatsDepth(vSplatDepth: f32) -> f32 {\n return vSplatDepth;\n}\n";