mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Improve bloom effect (#12916)
* Remove the built-in exposure factor of 2.5 * Add physics-based bloom (https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom) * Add luminance scaling for bloom layer to simulate HDR * Add setting to control bloom strength
This commit is contained in:
parent
fb3085a2c5
commit
9b24041394
15 changed files with 195 additions and 59 deletions
37
client/shaders/bloom_downsample/opengl_fragment.glsl
Normal file
37
client/shaders/bloom_downsample/opengl_fragment.glsl
Normal file
|
@ -0,0 +1,37 @@
|
|||
// based on Phys.Bloom OpenGL tutorial https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
|
||||
// and ACM Siggraph talk in 2014 by Jorge Jimenez for Call of Duty: Advanced Warfare.
|
||||
#define rendered texture0
|
||||
|
||||
uniform sampler2D rendered;
|
||||
uniform vec2 texelSize0;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 tx = 2.0 * texelSize0;
|
||||
vec3 a = texture2D(rendered, varTexCoord.st + vec2(-1., -1.) * tx).rgb;
|
||||
vec3 b = texture2D(rendered, varTexCoord.st + vec2(0., -1.) * tx).rgb;
|
||||
vec3 c = texture2D(rendered, varTexCoord.st + vec2(1., -1.) * tx).rgb;
|
||||
vec3 d = texture2D(rendered, varTexCoord.st + vec2(-1., 0.) * tx).rgb;
|
||||
vec3 e = texture2D(rendered, varTexCoord.st + vec2(0., 0.) * tx).rgb;
|
||||
vec3 f = texture2D(rendered, varTexCoord.st + vec2(1., 0.) * tx).rgb;
|
||||
vec3 g = texture2D(rendered, varTexCoord.st + vec2(-1., 1.) * tx).rgb;
|
||||
vec3 h = texture2D(rendered, varTexCoord.st + vec2(0., 1.) * tx).rgb;
|
||||
vec3 i = texture2D(rendered, varTexCoord.st + vec2(1., 1.) * tx).rgb;
|
||||
vec3 j = texture2D(rendered, varTexCoord.st + vec2(-0.5, -0.5) * tx).rgb;
|
||||
vec3 k = texture2D(rendered, varTexCoord.st + vec2(0.5, -0.5) * tx).rgb;
|
||||
vec3 l = texture2D(rendered, varTexCoord.st + vec2(-0.5, 0.5) * tx).rgb;
|
||||
vec3 m = texture2D(rendered, varTexCoord.st + vec2(-0.5, 0.5) * tx).rgb;
|
||||
|
||||
vec3 color =
|
||||
(a + c + g + i) * 0.03125 +
|
||||
(b + d + f + h) * 0.0625 +
|
||||
(e + j + k + l + m) * 0.125;
|
||||
|
||||
gl_FragColor = max(vec4(color, 1.0), 1e-4);
|
||||
}
|
11
client/shaders/bloom_downsample/opengl_vertex.glsl
Normal file
11
client/shaders/bloom_downsample/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;
|
||||
}
|
35
client/shaders/bloom_upsample/opengl_fragment.glsl
Normal file
35
client/shaders/bloom_upsample/opengl_fragment.glsl
Normal file
|
@ -0,0 +1,35 @@
|
|||
#define current texture0
|
||||
#define previous texture1
|
||||
|
||||
uniform sampler2D current;
|
||||
uniform sampler2D previous;
|
||||
uniform vec2 texelSize0;
|
||||
uniform mediump float bloomRadius;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 offset = bloomRadius * texelSize0;
|
||||
|
||||
vec3 a = texture2D(previous, varTexCoord.st + vec2(-1., -1.) * offset).rgb;
|
||||
vec3 b = texture2D(previous, varTexCoord.st + vec2(0., -1.) * offset).rgb;
|
||||
vec3 c = texture2D(previous, varTexCoord.st + vec2(1., -1.) * offset).rgb;
|
||||
vec3 d = texture2D(previous, varTexCoord.st + vec2(-1., 0.) * offset).rgb;
|
||||
vec3 e = texture2D(previous, varTexCoord.st + vec2(0., 0.) * offset).rgb;
|
||||
vec3 f = texture2D(previous, varTexCoord.st + vec2(1., 0.) * offset).rgb;
|
||||
vec3 g = texture2D(previous, varTexCoord.st + vec2(-1., 1.) * offset).rgb;
|
||||
vec3 h = texture2D(previous, varTexCoord.st + vec2(0., 1.) * offset).rgb;
|
||||
vec3 i = texture2D(previous, varTexCoord.st + vec2(1., 1.) * offset).rgb;
|
||||
|
||||
vec3 base = texture2D(current, varTexCoord.st).rgb;
|
||||
|
||||
gl_FragColor = max(vec4(base +
|
||||
(a + c + g + i) * 0.0625 +
|
||||
(b + d + f + h) * 0.125 +
|
||||
e * 0.25, 1.), 1e-4);
|
||||
}
|
11
client/shaders/bloom_upsample/opengl_vertex.glsl
Normal file
11
client/shaders/bloom_upsample/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;
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
uniform sampler2D rendered;
|
||||
uniform vec2 texelSize0;
|
||||
uniform mediump float bloomRadius;
|
||||
uniform mat3 bloomBlurWeights;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
@ -10,6 +11,13 @@ varying mediump vec2 varTexCoord;
|
|||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
// smoothstep - squared
|
||||
float smstsq(float f)
|
||||
{
|
||||
f = f * f * (3 - 2 * f);
|
||||
return f;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// kernel distance and linear size
|
||||
|
@ -19,8 +27,8 @@ void main(void)
|
|||
vec4 color = vec4(0.);
|
||||
mediump float sum = 0.;
|
||||
for (mediump float i = 0.; i < n; i++) {
|
||||
mediump float weight = pow(1. - (abs(i / bloomRadius - 1.)), 1.3);
|
||||
color += texture2D(rendered, uv).rgba * weight;
|
||||
mediump float weight = smstsq(1. - (abs(i / bloomRadius - 1.)));
|
||||
color.rgb += texture2D(rendered, uv).rgb * weight;
|
||||
sum += weight;
|
||||
uv += vec2(texelSize0.x, 0.);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
uniform sampler2D rendered;
|
||||
uniform vec2 texelSize0;
|
||||
uniform mediump float bloomRadius;
|
||||
uniform mat3 bloomBlurWeights;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
@ -10,6 +11,13 @@ varying mediump vec2 varTexCoord;
|
|||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
// smoothstep - squared
|
||||
float smstsq(float f)
|
||||
{
|
||||
f = f * f * (3 - 2 * f);
|
||||
return f;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// kernel distance and linear size
|
||||
|
@ -19,8 +27,8 @@ void main(void)
|
|||
vec4 color = vec4(0.);
|
||||
mediump float sum = 0.;
|
||||
for (mediump float i = 0.; i < n; i++) {
|
||||
mediump float weight = pow(1. - (abs(i / bloomRadius - 1.)), 1.3);
|
||||
color += texture2D(rendered, uv).rgba * weight;
|
||||
mediump float weight = smstsq(1. - (abs(i / bloomRadius - 1.)));
|
||||
color.rgb += texture2D(rendered, uv).rgb * weight;
|
||||
sum += weight;
|
||||
uv += vec2(0., texelSize0.y);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
uniform sampler2D rendered;
|
||||
uniform mediump float exposureFactor;
|
||||
uniform float bloomLuminanceThreshold;
|
||||
uniform mediump float bloomStrength;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
@ -14,8 +14,14 @@ centroid varying vec2 varTexCoord;
|
|||
void main(void)
|
||||
{
|
||||
vec2 uv = varTexCoord.st;
|
||||
vec4 color = texture2D(rendered, uv).rgba;
|
||||
vec3 color = texture2D(rendered, uv).rgb;
|
||||
// translate to linear colorspace (approximate)
|
||||
color.rgb = pow(color.rgb, vec3(2.2)) * exposureFactor;
|
||||
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
||||
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;
|
||||
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
|
||||
}
|
||||
|
|
|
@ -16,15 +16,14 @@ centroid varying vec2 varTexCoord;
|
|||
|
||||
vec4 applyBloom(vec4 color, vec2 uv)
|
||||
{
|
||||
float bias = bloomIntensity;
|
||||
vec4 bloom = texture2D(bloom, uv);
|
||||
vec3 light = texture2D(bloom, uv).rgb;
|
||||
#ifdef ENABLE_BLOOM_DEBUG
|
||||
if (uv.x > 0.5 && uv.y < 0.5)
|
||||
return vec4(bloom.rgb, color.a);
|
||||
return vec4(light, color.a);
|
||||
if (uv.x < 0.5)
|
||||
return color;
|
||||
return light;
|
||||
#endif
|
||||
color.rgb = mix(color.rgb, bloom.rgb, bias);
|
||||
color.rgb = mix(color.rgb, light, bloomIntensity);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
@ -86,8 +85,6 @@ void main(void)
|
|||
{
|
||||
#if ENABLE_TONE_MAPPING
|
||||
color = applyToneMapping(color);
|
||||
#else
|
||||
color.rgb /= 2.5; // default exposure factor, see also RenderingEngine::DEFAULT_EXPOSURE_FACTOR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue