examples/mini_splat.wgsl
Repository source snapshot · Plain text · GitHub
1// Teaching compute rasterizer: one invocation owns one pixel, no triangle pass.2// Inputs must already be sorted back-to-front. Complexity is O(pixels*splats).3struct Splat {4 mean_sigma: vec4<f32>, // camera-space xyz (+Z forward), world-space sigma5 rgb_alpha: vec4<f32>,6};7@group(0) @binding(0) var<storage, read> splats: array<Splat>;8@group(0) @binding(1) var output: texture_storage_2d<rgba8unorm, write>;910@compute @workgroup_size(8, 8)11fn main(@builtin(global_invocation_id) id: vec3<u32>) {12 let size = textureDimensions(output);13 if any(id.xy >= size) { return; }14 let pixel = vec2<f32>(id.xy) + 0.5;15 let focal = 0.8 * f32(size.x);16 var color = vec3<f32>(0.0);17 for (var i = 0u; i < arrayLength(&splats); i++) {18 let s = splats[i];19 let p = s.mean_sigma.xyz;20 if p.z <= 0.05 { continue; }21 let center = focal * p.xy / p.z + vec2<f32>(size) * 0.5;22 // Isotropic world covariance projected through the perspective Jacobian.23 let jx = vec3<f32>(focal/p.z, 0.0, -focal*p.x/(p.z*p.z));24 let jy = vec3<f32>(0.0, focal/p.z, -focal*p.y/(p.z*p.z));25 let variance = s.mean_sigma.w * s.mean_sigma.w;26 let a = variance * dot(jx, jx) + 0.3;27 let b = variance * dot(jx, jy);28 let c = variance * dot(jy, jy) + 0.3;29 let d = pixel - center;30 let power = -0.5 * (c*d.x*d.x - 2.0*b*d.x*d.y + a*d.y*d.y) / (a*c-b*b);31 let alpha = min(0.99, s.rgb_alpha.a * exp(power));32 if alpha < 1.0/255.0 { continue; }33 color = s.rgb_alpha.rgb * alpha + color * (1.0-alpha);34 }35 textureStore(output, vec2<i32>(id.xy), vec4<f32>(color, 1.0));36}37