example(RTVolume): GPU-written device-buffer procedural AABBs (#37)

A compute shader (aabbs.comp.{glsl,wgsl}) writes the procedural box into a
device buffer that BuildProcedural consumes by device address/handle with no
host copy; the WebGPU path also refits from it each frame so the box breathes.
Verified rendering on both Vulkan (native) and WebGPU (browser).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-16 14:12:12 +00:00
commit 0d1312ac09
4 changed files with 173 additions and 13 deletions

View file

@ -0,0 +1,29 @@
// Issue #37: GPU producer (WebGPU) for the procedural AABB build input.
// Writes the per-box bounding boxes straight into a device storage buffer
// that Mesh::BuildProcedural / RefitProcedural then consume by handle, with
// no host copy. Emits a single unit box [-r,r]^3 (the bounding volume the
// intersection shader turns into a sphere); `time` lets it breathe so the
// per-frame refit has something to track. A real particle system would write
// one box per particle from simulation state.
//
// PlainComputeShader layout (no rayQuery user groups start at 1):
// @group(0) @binding(0) uniform Params
// @group(1) @binding(0) storage read_write boxes : array<f32> (6 f32/box)
struct Params { count: u32, time: f32, _0: u32, _1: u32 };
@group(0) @binding(0) var<uniform> pc : Params;
@group(1) @binding(0) var<storage, read_write> boxes : array<f32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
let i = gid.x;
if (i >= pc.count) { return; }
let r = 1.0 + 0.15 * sin(pc.time);
let b = i * 6u;
boxes[b + 0u] = -r;
boxes[b + 1u] = -r;
boxes[b + 2u] = -r;
boxes[b + 3u] = r;
boxes[b + 4u] = r;
boxes[b + 5u] = r;
}