All checks were successful
Build (Arch Linux) / build (push) Successful in 3m10s
74 lines
1.9 KiB
Plaintext
74 lines
1.9 KiB
Plaintext
#version 460 core
|
|
|
|
const uint LOCAL_SIZE = 128u;
|
|
|
|
layout(local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
|
|
|
|
struct point_light {
|
|
vec4 position;
|
|
vec4 colour;
|
|
float intensity;
|
|
float radius;
|
|
};
|
|
|
|
const uint MAX_NUM_LIGHTS = 100u;
|
|
|
|
struct cluster {
|
|
vec4 min_point;
|
|
vec4 max_point;
|
|
uint count;
|
|
uint light_indices[MAX_NUM_LIGHTS];
|
|
};
|
|
|
|
layout(std430, binding = 1) restrict buffer cluster_buf {
|
|
cluster clusters[];
|
|
};
|
|
|
|
layout(std430, binding = 2) restrict buffer lights_buf {
|
|
point_light point_lights[];
|
|
};
|
|
|
|
uniform mat4 view_mat;
|
|
|
|
bool test_sphere_aabb(uint i, cluster c);
|
|
|
|
// each invocation of main() is a thread processing a cluster
|
|
void main() {
|
|
uint n_lights = point_lights.length();
|
|
uint cluster_idx = gl_WorkGroupID.x * LOCAL_SIZE + gl_LocalInvocationID.x;
|
|
cluster c = clusters[cluster_idx];
|
|
|
|
// we need to reset count because culling runs every frame.
|
|
// otherwise it would accumulate.
|
|
c.count = 0;
|
|
|
|
for (uint i = 0; i < n_lights; ++i) {
|
|
if (test_sphere_aabb(i, c) && c.count < 100) {
|
|
c.light_indices[c.count] = i;
|
|
c.count++;
|
|
}
|
|
}
|
|
|
|
clusters[cluster_idx] = c;
|
|
}
|
|
|
|
bool sphere_aabb_intersection(vec3 center, float radius, vec3 aabb_min, vec3 aabb_max) {
|
|
// closest point on the AABB to the sphere center
|
|
vec3 closest_point = clamp(center, aabb_min, aabb_max);
|
|
|
|
// squared distance between the sphere center and closest point
|
|
float distance_squared = dot(closest_point - center, closest_point - center);
|
|
return distance_squared <= radius * radius;
|
|
}
|
|
|
|
// this just unpacks data for sphere_aabb_intersection
|
|
bool test_sphere_aabb(uint i, cluster c) {
|
|
vec3 center = vec3(view_mat * point_lights[i].position);
|
|
float radius = point_lights[i].radius;
|
|
|
|
vec3 aabb_min = c.min_point.xyz;
|
|
vec3 aabb_max = c.max_point.xyz;
|
|
|
|
return sphere_aabb_intersection(center, radius, aabb_min, aabb_max);
|
|
}
|