diff options
Diffstat (limited to 'client/shaders/update_exposure/opengl_fragment.glsl')
-rw-r--r-- | client/shaders/update_exposure/opengl_fragment.glsl | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/client/shaders/update_exposure/opengl_fragment.glsl b/client/shaders/update_exposure/opengl_fragment.glsl new file mode 100644 index 000000000..dfed8f0d8 --- /dev/null +++ b/client/shaders/update_exposure/opengl_fragment.glsl @@ -0,0 +1,75 @@ +#define exposure texture0 +#define screen texture1 + +struct ExposureParams { + float luminanceMin; + float luminanceMax; + float exposureCorrection; + float luminanceKey; + float speedDarkBright; + float speedBrightDark; + float centerWeightPower; + float compensationFactor; +}; + +uniform sampler2D exposure; +uniform sampler2D screen; + +#ifdef ENABLE_BLOOM +uniform float bloomStrength; +#else +const float bloomStrength = 1.0; +#endif +uniform ExposureParams exposureParams; +uniform float animationTimerDelta; + + +const vec3 luminanceFactors = vec3(0.213, 0.715, 0.072); + +float getLuminance(vec3 color) +{ + return dot(color, luminanceFactors); +} + +void main(void) +{ + float previousExposure = texture2D(exposure, vec2(0.5, 0.5)).r; + + vec3 averageColor = vec3(0.); + float n = 0.; + + // Scan the screen with center-weighting and sample average color + for (float _x = 0.1; _x < 0.9; _x += 0.17) { + float x = pow(_x, exposureParams.centerWeightPower); + for (float _y = 0.1; _y < 0.9; _y += 0.17) { + float y = pow(_y, exposureParams.centerWeightPower); + averageColor += texture2D(screen, vec2(0.5 + 0.5 * x, 0.5 + 0.5 * y)).rgb; + averageColor += texture2D(screen, vec2(0.5 + 0.5 * x, 0.5 - 0.5 * y)).rgb; + averageColor += texture2D(screen, vec2(0.5 - 0.5 * x, 0.5 + 0.5 * y)).rgb; + averageColor += texture2D(screen, vec2(0.5 - 0.5 * x, 0.5 - 0.5 * y)).rgb; + n += 4.; + } + } + + float luminance = getLuminance(averageColor); + luminance /= n; + + luminance /= pow(2., previousExposure) * bloomStrength * exposureParams.compensationFactor; // compensate for the configurable factors + + luminance = clamp(luminance, exposureParams.luminanceMin, exposureParams.luminanceMax); + + // From https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/course-notes-moving-frostbite-to-pbr-v2.pdf + // 1. EV100 = log2(luminance * S / K) where S = 100, K = 0.125 = log2(luminance) + 3 + // 2. Lmax = 1.2 * 2 ^ (EV100 - EC) + // => Lmax = 1.2 * 2^3 * luminance / 2^EC = 9.6 * luminance / 2^EC + // 3. exposure = 1 / Lmax + // => exposure = 2^EC / (9.6 * luminance) + float wantedExposure = exposureParams.exposureCorrection - log(luminance)/0.693147180559945 - 3.263034405833794; + + if (wantedExposure < previousExposure) + wantedExposure = mix(wantedExposure, previousExposure, exp(-animationTimerDelta * exposureParams.speedDarkBright)); // dark -> bright + else + wantedExposure = mix(wantedExposure, previousExposure, exp(-animationTimerDelta * exposureParams.speedBrightDark)); // bright -> dark + + gl_FragColor = vec4(vec3(wantedExposure), 1.); +} |