17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 07:29:20 +02:00
Files
maszyna/shaders/cluster_build.comp

58 lines
2.2 KiB
Plaintext

// bounding boxes of the light clusters in view space, see gl/cluster_grid.h
// one invocation per cluster, run when the projection or the depth range of the pass changes
#include <common>
layout(local_size_x = CLUSTER_BUILD_GROUP_SIZE) in;
// clip space w at the lower boundary of slice k: the inverse of the slice formula used when shading
float slice_depth(uint k)
{
return exp((float(k) - cluster_slice_bias) / cluster_slice_scale);
}
void main()
{
uint index = gl_GlobalInvocationID.x;
if (index >= uint(CLUSTER_COUNT))
return;
uvec3 cell = uvec3(
index % uint(CLUSTER_GRID_X),
(index / uint(CLUSTER_GRID_X)) % uint(CLUSTER_GRID_Y),
index / uint(CLUSTER_GRID_X * CLUSTER_GRID_Y));
// clip x, y and w are affine functions of the view space position, while clip z is constant (reverse z with
// the far plane at infinity), which makes the projection matrix singular. the position is recovered from
// those three alone, so off-axis and rotated screens of custom viewports and vr eyes work too
mat3 linear = mat3(
vec3(cluster_projection[0][0], cluster_projection[0][1], cluster_projection[0][3]),
vec3(cluster_projection[1][0], cluster_projection[1][1], cluster_projection[1][3]),
vec3(cluster_projection[2][0], cluster_projection[2][1], cluster_projection[2][3]));
vec3 translation = vec3(cluster_projection[3][0], cluster_projection[3][1], cluster_projection[3][3]);
mat3 unproject = inverse(linear);
// the tile in clip space xy, the slice in clip space w
vec2 tiles = vec2(CLUSTER_GRID_X, CLUSTER_GRID_Y);
vec2 ndc_min = vec2(cell.xy) / tiles * 2.0 - 1.0;
vec2 ndc_max = vec2(cell.xy + 1U) / tiles * 2.0 - 1.0;
float w_near = slice_depth(cell.z);
float w_far = slice_depth(cell.z + 1U);
vec3 lower = vec3(3.402823e38);
vec3 upper = vec3(-3.402823e38);
for (int corner = 0; corner < 8; ++corner)
{
vec2 ndc = vec2(
(corner & 1) != 0 ? ndc_max.x : ndc_min.x,
(corner & 2) != 0 ? ndc_max.y : ndc_min.y);
float w = (corner & 4) != 0 ? w_far : w_near;
vec3 position = unproject * (vec3(ndc * w, w) - translation);
lower = min(lower, position);
upper = max(upper, position);
}
cluster_aabbs[index].lower = vec4(lower, 0.0);
cluster_aabbs[index].upper = vec4(upper, 0.0);
}