LumixEngine/data/pipelines/avg_luminance.shd
2020-10-28 21:33:02 +01:00

81 lines
No EOL
2.1 KiB
Text

include "pipelines/common.glsl"
compute_shader [[
#if defined PASS2 || defined PASS0
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
#else
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#endif
layout (binding = 0) uniform sampler2D u_image;
layout (binding = 1, std430) coherent buffer OutData {
uint b_histogram[256];
float b_accum;
};
layout(binding = 4, std140) uniform Data {
vec2 u_size;
float u_accomodation_speed;
};
shared uint histogram[256];
uint luminanceToBin(float lum, float min, float inv_range) {
if (lum < 1e-3) {
return 0;
}
float logLum = clamp((log2(lum) - min) * inv_range, 0.0, 1.0);
return uint(logLum * 254.0 + 1.0);
}
float binToLuminance(float bin, float min, float range) {
if (bin <= 1e-5) return 0;
float t = saturate((bin - 1) / 254.0);
return exp2(t * range + min);
}
void main() {
const float range = 12.0;
const float min = -6;
#ifdef PASS0
b_histogram[gl_LocalInvocationID.x] = 0;
#elif !defined PASS2
uint idx = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 16;
histogram[idx] = 0;
groupMemoryBarrier();
barrier();
if (all(lessThan(gl_GlobalInvocationID.xy, uvec2(u_size + 0.5)))) {
float luminance = luminance(texture(u_image, ivec2(gl_GlobalInvocationID.xy) / u_size).rgb);
uint bin = luminanceToBin(luminance, min, 1 / range);
atomicAdd(histogram[bin], 1);
}
groupMemoryBarrier();
barrier();
atomicAdd(b_histogram[idx], histogram[idx]);
#else
uint idx = gl_LocalInvocationID.x;
histogram[idx] = b_histogram[idx] * idx;
groupMemoryBarrier();
barrier();
for (uint offset = 256 >> 1; offset > 0; offset >>= 1) {
if (idx < offset) {
histogram[idx] += histogram[idx + offset];
}
groupMemoryBarrier();
barrier();
}
if (idx == 0) {
float avg_bin = histogram[0] / float(u_size.x * u_size.y);
float avg_lum = binToLuminance(avg_bin, min, range);
b_accum += (avg_lum - b_accum) * (1 - exp(-Global.frame_time_delta * u_accomodation_speed));
}
#endif
}
]]