struct Particle { pos: vec3, _pad0: f32, // matches _pad0 in C vel: vec3, _pad1: f32, // matches _pad1 in C }; @group(0) @binding(0) var particles: array; @group(0) @binding(1) var viewProjectionMatrix: mat4x4; @group(0) @binding(2) var cameraRight: vec3; @group(0) @binding(3) var cameraUp: vec3; struct VertexOutput { @builtin(position) Position: vec4, @location(0) fragColor: vec4, }; const quadVertexOffsets = array, 6>( vec2(-1, -1), vec2( 1, -1), vec2(-1, 1), vec2( 1, -1), vec2( 1, 1), vec2(-1, 1) ); @vertex fn vs_main( @builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32 ) -> VertexOutput { let particle = particles[instanceIndex]; let offset = quadVertexOffsets[vertexIndex]; let worldPosition = particle.pos * 150.0 + offset.x * cameraRight + offset.y * cameraUp; var output: VertexOutput; output.Position = viewProjectionMatrix * vec4(worldPosition , 1.0); output.fragColor = vec4(1.0, 1.0, 1.0, 1.0); // white color return output; } @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4 { return input.fragColor; }