[nzsl_version("1.0")] module Compute.Particles; [layout(std140)] struct Particle { color: vec3[f32], position: vec2[f32], targetPosition: vec2[f32], velocity: vec2[f32] } [layout(std140)] struct ParticleData { particle_count: u32, particles: dyn_array[Particle] } [layout(std140)] struct SceneData { deltaTime: f32, mousePos: vec2[f32], effectRadius: f32 } external { [binding(0)] data: storage[ParticleData], [binding(1)] sceneData: uniform[SceneData] } struct Input { [builtin(global_invocation_indices)] indices: vec3[u32] } [entry(compute)] [workgroup(64, 1, 1)] fn main(input: Input) { let index = input.indices.x; if (index >= data.particle_count) return; // Gets pushed by the cursor let attract_pos = sceneData.mousePos; let dist = length(attract_pos - data.particles[index].position); data.particles[index].velocity -= 10000.0 * sceneData.effectRadius / min(dist, sceneData.effectRadius) * sceneData.deltaTime * (attract_pos - data.particles[index].position) / (dist * dist * dist * dist); // But want to return to their original position let dist = length(data.particles[index].targetPosition - data.particles[index].position); let shouldUseDir = dist < 1.0; data.particles[index].velocity += 100.0 * sceneData.deltaTime * select(shouldUseDir, normalize(data.particles[index].targetPosition - data.particles[index].position), vec2[f32](0.0, 0.0)); // Lose speed with time let damping = pow(0.5, sceneData.deltaTime); data.particles[index].velocity *= damping; // Move particle data.particles[index].position += data.particles[index].velocity * sceneData.deltaTime; }