// MinecraftPT — Exposure_CS // Computes the average scene luminance and smooths the exposure over time. // Writes the result into a 1x1 R16F image (exposureTex) read by the final pass. #include "/Lib/Settings.glsl" #include "/Lib/Utilities.glsl" const ivec3 workGroups = ivec3(8, 8, 1); layout (local_size_x = 16, local_size_y = 16) in; layout (r16f) uniform writeonly image2D img_exposureTex; uniform sampler2D colortex12; shared float luminanceSum[256]; void main(){ ivec2 texel = ivec2(gl_GlobalInvocationID.xy); // Downsample luminance from the HDR scene float lum = 0.0; vec2 base = vec2(texel * 4); for (int i = 0; i < 4; i++){ for (int j = 0; j < 4; j++){ vec3 color = texelFetch(colortex12, ivec2(base + vec2(i, j)), 0).rgb; lum += luminance(color); }} lum /= 16.0; // Shared reduction uint local = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 16u; luminanceSum[local] = lum; barrier(); if (local == 0u){ float avg = 0.0; for (uint i = 0u; i < 256u; i++){ avg += luminanceSum[i]; } avg /= 256.0; // Target exposure (inverse of average luminance) float targetExposure = 1.0 / max(avg, 0.001); // Read previous exposure for temporal smoothing (single thread) float prevExposure = imageLoad(img_exposureTex, ivec2(0, 0)).r; if (prevExposure <= 0.0) prevExposure = 1.0; float adapted = mix(prevExposure, targetExposure, SMOOTH_EXPOSURE); adapted = clamp(adapted, 0.01, 100.0); imageStore(img_exposureTex, ivec2(0, 0), vec4(adapted)); } }