mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-31 13:29:07 +01:00
Build view-space light cluster grid in a compute pass
This commit is contained in:
57
shaders/cluster_build.comp
Normal file
57
shaders/cluster_build.comp
Normal file
@@ -0,0 +1,57 @@
|
||||
// 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);
|
||||
}
|
||||
38
shaders/cluster_heatmap.frag
Normal file
38
shaders/cluster_heatmap.frag
Normal file
@@ -0,0 +1,38 @@
|
||||
// debug view of the light clusters: tints every pixel of the scene with the colour of its depth slice,
|
||||
// and darkens every other screen tile to show the grid. drawn over the resolved image, see gl/cluster_grid.h
|
||||
|
||||
in vec2 f_coords;
|
||||
|
||||
#include <common>
|
||||
|
||||
#texture (depth_tex, 0, R)
|
||||
uniform sampler2D depth_tex;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
const float TINT = 0.55;
|
||||
|
||||
// blue (near) through green to red (far)
|
||||
vec3 ramp(float t)
|
||||
{
|
||||
return clamp(vec3(1.5) - abs(4.0 * t - vec3(3.0, 2.0, 1.0)), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// reverse z: 0 is the far plane at infinity, i.e. the sky, which has no cluster
|
||||
float depth = texelFetch(depth_tex, ivec2(f_coords * vec2(textureSize(depth_tex, 0))), 0).r;
|
||||
if (depth <= 0.0)
|
||||
discard;
|
||||
|
||||
// depth is znear / w
|
||||
float w = cluster_znear / depth;
|
||||
int slice = clamp(int(floor(log(w) * cluster_slice_scale + cluster_slice_bias)), 0, CLUSTER_GRID_Z - 1);
|
||||
ivec2 tile = clamp(ivec2(floor(f_coords * vec2(CLUSTER_GRID_X, CLUSTER_GRID_Y))), ivec2(0), ivec2(CLUSTER_GRID_X - 1, CLUSTER_GRID_Y - 1));
|
||||
|
||||
vec3 color = ramp(float(slice) / float(CLUSTER_GRID_Z - 1));
|
||||
if (((tile.x + tile.y) & 1) != 0)
|
||||
color *= 0.8;
|
||||
|
||||
out_color = vec4(color, TINT);
|
||||
}
|
||||
Reference in New Issue
Block a user