#version 450
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
const uint HASH_SIZE = 65521;
const uint MAX_PER_CELL = 128;
struct InstanceData {
mat4 model;
vec4 color;
vec4 mat_props;
vec4 velocity;
vec4 angular_velocity;
vec4 physic_props;
};
layout(set = 0, binding = 0) readonly buffer ReadBuf { InstanceData data[]; } read_buf;
layout(set = 0, binding = 2) buffer GridCounts { uint data[]; } grid_counts;
layout(set = 0, binding = 3) buffer GridObjects { uint data[]; } grid_objects;
layout(set = 0, binding = 4) readonly buffer BigIndices { uint data[]; } big_indices;
layout(push_constant) uniform PushConstants {
float dt;
uint total_objects;
uint offset;
uint count;
uint num_big_objects;
vec4 global_gravity; // w = CELL_SIZE
} pc;
uint hashCell(ivec3 c) {
uvec3 u = uvec3(c);
return (u.x * 2654435761u ^ u.y * 2246822519u ^ u.z * 3266489917u) % HASH_SIZE;
}
vec3 extractScale(mat4 m) {
return vec3(length(m[0].xyz), length(m[1].xyz), length(m[2].xyz));
}
void main() {
uint i = gl_GlobalInvocationID.x;
if (i >= pc.total_objects) return;
InstanceData me = read_buf.data[i];
// Using x * 0.5 as radius
float radius = extractScale(me.model).x * 0.5;
// Ignore big objects (handled by BigIndices array)
if (radius > 2.5) return;
vec3 pos = me.model[3].xyz;
float cell_size = pc.global_gravity.w;
ivec3 cell = ivec3(floor(pos / cell_size));
uint h = hashCell(cell);
// Atomically increment the count for this hash cell
uint idx = atomicAdd(grid_counts.data[h], 1);
if (idx < MAX_PER_CELL) {
grid_objects.data[h * MAX_PER_CELL + idx] = i;
}
}