aboutsummaryrefslogtreecommitdiff
path: root/client/shaders/update_exposure/opengl_fragment.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'client/shaders/update_exposure/opengl_fragment.glsl')
-rw-r--r--client/shaders/update_exposure/opengl_fragment.glsl75
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.);
+}