mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
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
This commit is contained in:
parent
2715cc8bf6
commit
6d45c243f8
29 changed files with 567 additions and 71 deletions
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
75
client/shaders/update_exposure/opengl_fragment.glsl
Normal file
75
client/shaders/update_exposure/opengl_fragment.glsl
Normal file
|
@ -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.);
|
||||
}
|
11
client/shaders/update_exposure/opengl_vertex.glsl
Normal file
11
client/shaders/update_exposure/opengl_vertex.glsl
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue