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


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

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


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

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

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

fn getHash(gridCoordinate: vec3<i32>, cellCount: u32) -> u32 {

let maxIndex = i32(cellCount) - 1;

	let x = max(0, min(gridCoordinate.x, maxIndex));
	let y = max(0, min(gridCoordinate.y, maxIndex));
	let z = max(0, min(gridCoordinate.z, maxIndex));

	return u32(x + y * i32(cellCount) + z * i32(cellCount) * i32(cellCount));
}

@compute @workgroup_size(256)
fn computeMain(@builtin(global_invocation_id) globalInvocationId: vec3<u32>) {

	let particleIndex = globalInvocationId.x;

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

	var currentPosition 	= positions[particleIndex];

let cellSize = (gridMax - gridMin) / f32(cellCount);  // 2.0 / 16 = 0.125

let relativePos = currentPosition - gridMin;          // currentPosition + 1

let gridCoord = vec3<i32>(floor(relativePos / cellSize));  // relativePos divided by cellSize, then floored

let hash = getHash(gridCoord, cellCount);

	gridHashes[ particleIndex ] 	= hash;

	indices[ particleIndex ] 		= particleIndex;

}
