@group(0) @binding(0)
var<storage, read_write> positions: array<vec3<f32>>;

@group(0) @binding(1)
var<storage, read_write> velocities: array<vec3<f32>>;

@group(0) @binding(2)
var<storage, read_write> distances: array<f32>;

@group(0) @binding(3)
var<storage, read_write> indices: array<u32>;

@group(0) @binding(4)
var<uniform> deltaTimeSeconds: f32;

@group(0) @binding(5)
var<uniform> cameraPosition: vec3<f32>;

@group(0) @binding(6)
var<uniform> updateDistancesAndIndices: u32;  

@group(0) @binding(7)
var<uniform> cellCount: u32;

@group(0) @binding(8)
var<uniform> gravity: f32;

@compute @workgroup_size(64)
fn computeMain(@builtin(global_invocation_id) globalInvocationId: vec3<u32>) {
	let particleIndex = globalInvocationId.x;

	if (particleIndex >= arrayLength(&positions)) {
		return;
	}

	let gravityAcceleration = vec3<f32>(0.0, gravity, 0.0);

	var currentPosition 	= positions[particleIndex];
	var currentVelocity 	= velocities[particleIndex];

	let deltaTimeClamped 	= min(deltaTimeSeconds, 0.01);

	currentVelocity += gravityAcceleration * deltaTimeClamped;

	currentPosition += currentVelocity * deltaTimeClamped;

	let friction = 0.98;

	currentVelocity *= friction;


	positions[particleIndex] 	= currentPosition;
	
	velocities[particleIndex] 	= currentVelocity;

	if ( updateDistancesAndIndices == 1u ) {

		let diff 					= currentPosition - cameraPosition;

		let dist 					= length(diff);

		distances[ particleIndex ] 	= dist;

		indices[ particleIndex ] 	= particleIndex;

		positions[ particleIndex ] 	= currentPosition;

	}
}
