mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-31 11:09:06 +01:00
feat(vulkan): vulkan 1.4 core with the user interface and the launcher, shaders split into ogl46/vk14 with SPIR-V binaries loaded first
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
// exposure from the luminance histogram (exposure_histogram.comp): the average log2 luminance of the pixels between the
|
||||
// low and high percentile (the darkest and brightest parts of the image do not move the exposure), adapted over time to,
|
||||
// faster towards the brighter. the exposure brings the adapted luminance to the key, within the limits. one work group,
|
||||
// one invocation per bin; the histogram is cleared for the next frame
|
||||
|
||||
#include <common>
|
||||
|
||||
layout(local_size_x = EXPOSURE_HISTOGRAM_BINS) in;
|
||||
|
||||
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: log2 luminance per bin
|
||||
layout(location = 0) uniform vec2 log_range;
|
||||
// x: time since the last frame (s), y: rate of adaptation to a darker image, z: to a brighter one (1/s), w: key
|
||||
layout(location = 1) uniform vec4 adaptation;
|
||||
// lowest and highest exposure (multipliers)
|
||||
layout(location = 2) uniform vec2 exposure_range;
|
||||
|
||||
const float LOW_PERCENTILE = 0.4;
|
||||
const float HIGH_PERCENTILE = 0.95;
|
||||
|
||||
shared float shared_counts[EXPOSURE_HISTOGRAM_BINS];
|
||||
|
||||
void main()
|
||||
{
|
||||
uint index = gl_LocalInvocationIndex;
|
||||
shared_counts[index] = float(histogram[index]);
|
||||
histogram[index] = 0U;
|
||||
barrier();
|
||||
|
||||
if (index != 0U)
|
||||
return;
|
||||
|
||||
float total = 0.0;
|
||||
for (uint bin = 1U; bin < EXPOSURE_HISTOGRAM_BINS; ++bin)
|
||||
total += shared_counts[bin];
|
||||
// an all black image (or none) leaves the exposure as it was
|
||||
if (total < 1.0)
|
||||
return;
|
||||
|
||||
float low = total * LOW_PERCENTILE;
|
||||
float high = total * HIGH_PERCENTILE;
|
||||
float counted = 0.0;
|
||||
float logsum = 0.0;
|
||||
float weight = 0.0;
|
||||
for (uint bin = 1U; bin < EXPOSURE_HISTOGRAM_BINS; ++bin)
|
||||
{
|
||||
float count = shared_counts[bin];
|
||||
// the part of the bin between the percentiles
|
||||
float inside = max(min(counted + count, high) - max(counted, low), 0.0);
|
||||
counted += count;
|
||||
float binluminance = log_range.x + (float(bin - 1U) + 0.5) * log_range.y;
|
||||
logsum += inside * binluminance;
|
||||
weight += inside;
|
||||
}
|
||||
float averagelog = (weight > 0.0) ? logsum / weight : log_range.x;
|
||||
average_luminance = exp2(averagelog);
|
||||
|
||||
if (valid == 0U || !(adapted_luminance > 0.0))
|
||||
{
|
||||
adapted_luminance = average_luminance;
|
||||
valid = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
float adaptedlog = log2(adapted_luminance);
|
||||
float rate = (averagelog < adaptedlog) ? adaptation.y : adaptation.z;
|
||||
adaptedlog = mix(adaptedlog, averagelog, 1.0 - exp(-adaptation.x * rate));
|
||||
adapted_luminance = exp2(adaptedlog);
|
||||
}
|
||||
exposure = clamp(adaptation.w / adapted_luminance, exposure_range.x, exposure_range.y);
|
||||
}
|
||||
Reference in New Issue
Block a user