1
0
Fork 0
fgdata/Shaders/HDR/bloom_downsample.frag
Fernando García Liñán f53a170539 HDR: Better bloom effect
We also now pre-expose our lighting before writing to the HDR buffers.
This solves some precision issues and prevents the Sun from producing
infinite values.
2023-04-13 00:30:02 +02:00

89 lines
2.9 KiB
GLSL

/*
* Bloom - downsampling step
* "Next Generation Post Processing in Call of Duty Advanced Warfare"
* ACM Siggraph (2014)
* Based on the implementation by Alexander Christensen
* https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
*/
#version 330 core
layout(location = 0) out vec3 fragColor;
in vec2 texcoord;
uniform sampler2D tex;
uniform bool is_first_downsample;
// color.glsl
float linear_srgb_to_luminance(vec3 color);
vec3 eotf_sRGB(vec3 linear_srgb);
float karis_average(vec3 color)
{
return 1.0 / (1.0 + linear_srgb_to_luminance(color));
}
void main()
{
vec2 texel_size = 1.0 / vec2(textureSize(tex, 0));
float x = texel_size.x;
float y = texel_size.y;
// Take 13 samples around current texel
// a - b - c
// - j - k -
// d - e - f
// - l - m -
// g - h - i
// === ('e' is the current texel) ===
vec3 a = texture(tex, vec2(texcoord.x - 2*x, texcoord.y + 2*y)).rgb;
vec3 b = texture(tex, vec2(texcoord.x, texcoord.y + 2*y)).rgb;
vec3 c = texture(tex, vec2(texcoord.x + 2*x, texcoord.y + 2*y)).rgb;
vec3 d = texture(tex, vec2(texcoord.x - 2*x, texcoord.y)).rgb;
vec3 e = texture(tex, vec2(texcoord.x, texcoord.y)).rgb;
vec3 f = texture(tex, vec2(texcoord.x + 2*x, texcoord.y)).rgb;
vec3 g = texture(tex, vec2(texcoord.x - 2*x, texcoord.y - 2*y)).rgb;
vec3 h = texture(tex, vec2(texcoord.x, texcoord.y - 2*y)).rgb;
vec3 i = texture(tex, vec2(texcoord.x + 2*x, texcoord.y - 2*y)).rgb;
vec3 j = texture(tex, vec2(texcoord.x - x, texcoord.y + y)).rgb;
vec3 k = texture(tex, vec2(texcoord.x + x, texcoord.y + y)).rgb;
vec3 l = texture(tex, vec2(texcoord.x - x, texcoord.y - y)).rgb;
vec3 m = texture(tex, vec2(texcoord.x + x, texcoord.y - y)).rgb;
vec3 downsample;
if (is_first_downsample) {
// Apply Karis average to each block of 4 samples to prevent fireflies.
// Only done on the first downsampling step.
vec3 group0 = (a+b+d+e) * 0.25;
vec3 group1 = (b+c+e+f) * 0.25;
vec3 group2 = (d+e+g+h) * 0.25;
vec3 group3 = (e+f+h+i) * 0.25;
vec3 group4 = (j+k+l+m) * 0.25;
float kw0 = karis_average(group0);
float kw1 = karis_average(group1);
float kw2 = karis_average(group2);
float kw3 = karis_average(group3);
float kw4 = karis_average(group4);
float kw_sum = kw0 + kw1 + kw2 + kw3 + kw4;
downsample =
kw0 * group0 +
kw1 * group1 +
kw2 * group2 +
kw3 * group3 +
kw4 * group4;
downsample /= kw_sum;
} else {
// Apply weighted distribution:
// 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1
downsample = e*0.125;
downsample += (a+c+g+i)*0.03125;
downsample += (b+d+f+h)*0.0625;
downsample += (j+k+l+m)*0.125;
}
fragColor = downsample;
}