aboutsummaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorx2048 <codeforsmile@gmail.com>2023-01-06 22:33:25 +0100
committerGitHub <noreply@github.com>2023-01-06 22:33:25 +0100
commit6d45c243f85942b20dab58753e735ec89a68f710 (patch)
treebfe6207d73d1b111af82ea9e5794bdaac4ce26e3 /client
parent2715cc8bf68a2cc8cd583cd5b0bb732ee13a1b49 (diff)
downloadminetest-6d45c243f85942b20dab58753e735ec89a68f710.tar.xz
Add dynamic exposure correction (#12959)
* Add uniform for frame delta time * Adjust exposure in logarithmic (EV) space * Add network support and LUA API * Add testing mod
Diffstat (limited to 'client')
-rw-r--r--client/shaders/extract_bloom/opengl_fragment.glsl13
-rw-r--r--client/shaders/extract_bloom/opengl_vertex.glsl8
-rw-r--r--client/shaders/second_stage/opengl_fragment.glsl11
-rw-r--r--client/shaders/second_stage/opengl_vertex.glsl13
-rw-r--r--client/shaders/update_exposure/opengl_fragment.glsl75
-rw-r--r--client/shaders/update_exposure/opengl_vertex.glsl11
6 files changed, 123 insertions, 8 deletions
diff --git a/client/shaders/extract_bloom/opengl_fragment.glsl b/client/shaders/extract_bloom/opengl_fragment.glsl
index af320f9ab..45f5e9c6f 100644
--- a/client/shaders/extract_bloom/opengl_fragment.glsl
+++ b/client/shaders/extract_bloom/opengl_fragment.glsl
@@ -1,8 +1,12 @@
#define rendered texture0
+struct ExposureParams {
+ float compensationFactor;
+};
+
uniform sampler2D rendered;
-uniform mediump float exposureFactor;
uniform mediump float bloomStrength;
+uniform ExposureParams exposureParams;
#ifdef GL_ES
varying mediump vec2 varTexCoord;
@@ -10,6 +14,7 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord;
#endif
+varying float exposure;
void main(void)
{
@@ -18,10 +23,6 @@ void main(void)
// translate to linear colorspace (approximate)
color = pow(color, vec3(2.2));
- // Scale colors by luminance to amplify bright colors
- // in SDR textures.
- float luminance = dot(color, vec3(0.213, 0.515, 0.072));
- luminance *= luminance;
- color *= luminance * exposureFactor * bloomStrength;
+ color *= pow(2., exposure) * exposureParams.compensationFactor * bloomStrength;
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
}
diff --git a/client/shaders/extract_bloom/opengl_vertex.glsl b/client/shaders/extract_bloom/opengl_vertex.glsl
index 12692c296..479ae1079 100644
--- a/client/shaders/extract_bloom/opengl_vertex.glsl
+++ b/client/shaders/extract_bloom/opengl_vertex.glsl
@@ -1,11 +1,19 @@
+#define exposureMap texture1
+
+uniform sampler2D exposureMap;
+
#ifdef GL_ES
varying mediump vec2 varTexCoord;
#else
centroid varying vec2 varTexCoord;
#endif
+varying float exposure;
+
void main(void)
{
+ exposure = texture2D(exposureMap, vec2(0.5)).r;
+
varTexCoord.st = inTexCoord0.st;
gl_Position = inVertexPosition;
}
diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl
index 09b49ef0e..2ff58aa42 100644
--- a/client/shaders/second_stage/opengl_fragment.glsl
+++ b/client/shaders/second_stage/opengl_fragment.glsl
@@ -1,9 +1,14 @@
#define rendered texture0
#define bloom texture1
+struct ExposureParams {
+ float compensationFactor;
+};
+
uniform sampler2D rendered;
uniform sampler2D bloom;
-uniform mediump float exposureFactor;
+
+uniform ExposureParams exposureParams;
uniform lowp float bloomIntensity;
uniform lowp float saturation;
@@ -13,6 +18,8 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord;
#endif
+varying float exposure;
+
#ifdef ENABLE_BLOOM
vec4 applyBloom(vec4 color, vec2 uv)
@@ -80,7 +87,7 @@ void main(void)
if (uv.x > 0.5 || uv.y > 0.5)
#endif
{
- color.rgb *= exposureFactor;
+ color.rgb *= exposure * exposureParams.compensationFactor;
}
diff --git a/client/shaders/second_stage/opengl_vertex.glsl b/client/shaders/second_stage/opengl_vertex.glsl
index 12692c296..7c121f6d1 100644
--- a/client/shaders/second_stage/opengl_vertex.glsl
+++ b/client/shaders/second_stage/opengl_vertex.glsl
@@ -1,11 +1,24 @@
+#define exposureMap texture2
+
+uniform sampler2D exposureMap;
+
#ifdef GL_ES
varying mediump vec2 varTexCoord;
#else
centroid varying vec2 varTexCoord;
#endif
+varying float exposure;
+
void main(void)
{
+#ifdef ENABLE_AUTO_EXPOSURE
+ exposure = texture2D(exposureMap, vec2(0.5)).r;
+ exposure = pow(2., exposure);
+#else
+ exposure = 1.0;
+#endif
+
varTexCoord.st = inTexCoord0.st;
gl_Position = inVertexPosition;
}
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.);
+}
diff --git a/client/shaders/update_exposure/opengl_vertex.glsl b/client/shaders/update_exposure/opengl_vertex.glsl
new file mode 100644
index 000000000..12692c296
--- /dev/null
+++ b/client/shaders/update_exposure/opengl_vertex.glsl
@@ -0,0 +1,11 @@
+#ifdef GL_ES
+varying mediump vec2 varTexCoord;
+#else
+centroid varying vec2 varTexCoord;
+#endif
+
+void main(void)
+{
+ varTexCoord.st = inTexCoord0.st;
+ gl_Position = inVertexPosition;
+}