17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 03:59:19 +02:00
Files
maszyna/shaders/exposure_histogram.comp

50 lines
1.5 KiB
Plaintext

// luminance histogram of the image for the automatic exposure: every second pixel in both directions, binned by the log2
// of its luminance. bin 0 takes the black pixels, which the average leaves out. exposure_average.comp reads and clears it
#include <common>
layout(local_size_x = EXPOSURE_HISTOGRAM_GROUP_SIZE, local_size_y = EXPOSURE_HISTOGRAM_GROUP_SIZE) in;
layout(binding = 0) uniform sampler2D hdr_image;
layout(std430, binding = EXPOSURE_SSBO_BINDING) buffer exposure_ssbo
{
uint histogram[EXPOSURE_HISTOGRAM_BINS];
float adapted_luminance;
float exposure;
float average_luminance;
uint valid;
};
// x: log2 of the lowest luminance binned, y: number of bins per unit of log2 luminance
layout(location = 0) uniform vec2 log_range;
shared uint shared_histogram[EXPOSURE_HISTOGRAM_BINS];
void main()
{
uint index = gl_LocalInvocationIndex;
shared_histogram[index] = 0U;
barrier();
ivec2 pixel = ivec2(gl_GlobalInvocationID.xy) * 2;
ivec2 size = textureSize(hdr_image, 0);
if (pixel.x < size.x && pixel.y < size.y)
{
vec3 color = texelFetch(hdr_image, pixel, 0).rgb;
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
uint bin = 0U;
// also false for a NaN
if (luminance > 1e-6)
{
float position = clamp((log2(luminance) - log_range.x) * log_range.y, 0.0, float(EXPOSURE_HISTOGRAM_BINS - 2U));
bin = 1U + uint(position);
}
atomicAdd(shared_histogram[bin], 1U);
}
barrier();
if (shared_histogram[index] != 0U)
atomicAdd(histogram[index], shared_histogram[index]);
}