#type compute #version 460 core layout(local_size_x = 1, local_size_y = 1) in; layout(binding = 0, std430) buffer Histogram { uint bins[64]; }; layout(binding = 1, std430) buffer Exposure { float exposure; }; uniform float u_SpeedUp; uniform float u_SpeedDown; uniform float u_Key; uniform float u_LowPercent; uniform float u_HighPercent; uniform float u_MinExposure; uniform float u_MaxExposure; uniform float u_DeltaTime; uniform float u_LogMin; uniform float u_LogMax; void main() { float currentExposure = exposure; uint total = 0; uint prefix[64]; for (int i = 0; i < 64; i++) { total += bins[i]; prefix[i] = total; } float lowCount = u_LowPercent * 0.01 * total; float highCount = u_HighPercent * 0.01 * total; int lowBin = 0, highBin = 63; for (int i = 0; i < 64; i++) { if (prefix[i] < lowCount) lowBin = i + 1; if (prefix[i] < highCount) highBin = i + 1; } lowBin = clamp(lowBin, 0, 63); highBin = clamp(highBin, 0, 63); float sumLum = 0.0; uint count = 0; for (int i = lowBin; i <= highBin; i++) { float t = (float(i) + 0.5) / 64.0; float logLum = u_LogMin + t * (u_LogMax - u_LogMin); float lum = exp2(logLum); sumLum += lum * float(bins[i]); count += bins[i]; } float avgLum = count > 0 ? sumLum / count : 0.18; float targetExposure = u_Key / max(avgLum, 0.0001); targetExposure = clamp(targetExposure, u_MinExposure, u_MaxExposure); float speed = (targetExposure > currentExposure) ? u_SpeedUp : u_SpeedDown; float adaptFactor = 1.0 - exp(-speed * u_DeltaTime); float newExposure = mix(currentExposure, targetExposure, adaptFactor); newExposure = clamp(newExposure, u_MinExposure, u_MaxExposure); exposure = newExposure; }