Skip to content

Commit

Permalink
Added karis average to bloom
Browse files Browse the repository at this point in the history
  • Loading branch information
patricklbell committed Sep 13, 2022
1 parent 3f90ae6 commit 8d6f3ed
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 20 deletions.
88 changes: 70 additions & 18 deletions data/shaders/downsample.gl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ out vec3 out_color;

uniform sampler2D image;
uniform vec2 resolution;
#define KARIS 1
#if KARIS
uniform int is_mip0;

vec3 pow_vec3(vec3 v, float p)
{
return vec3(pow(v.x, p), pow(v.y, p), pow(v.z, p));
}

const float invGamma = 1.0 / 2.2;
vec3 to_srgb(vec3 v) { return pow_vec3(v, invGamma); }

float RGBToLuminance(vec3 col)
{
return dot(col, vec3(0.2126f, 0.7152f, 0.0722f));
}

float karis_average(vec3 col)
{
// Formula is 1 / (1 + luma)
float luma = RGBToLuminance(to_srgb(col)) * 0.25f;
return 1.0f / (1.0f + luma);
}
#endif

void main()
{
Expand Down Expand Up @@ -59,23 +83,51 @@ void main()
vec3 l = texture(image, vec2(texcoord.x - x, texcoord.y - y)).rgb;
vec3 m = texture(image, vec2(texcoord.x + x, texcoord.y - y)).rgb;

// Apply weighted distribution:
// 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1
// a,b,d,e * 0.125
// b,c,e,f * 0.125
// d,e,g,h * 0.125
// e,f,h,i * 0.125
// j,k,l,m * 0.5
// This shows 5 square areas that are being sampled. But some of them overlap,
// so to have an energy preserving downsample we need to make some adjustments.
// The weights are the distributed, so that the sum of j,k,l,m (e.g.)
// contribute 0.5 to the final color output. The code below is written
// to effectively yield this sum. We get:
// 0.125*5 + 0.03125*4 + 0.0625*4 = 1
out_color = e*0.125;
out_color += (a+c+g+i)*0.03125;
out_color += (b+d+f+h)*0.0625;
out_color += (j+k+l+m)*0.125;
out_color = max(out_color, 0.0001f);
#if KARIS
// Check if we need to perform Karis average on each block of 4 samples
vec3 groups[5];
switch (is_mip0)
{
case 1:
// We are writing to mip 0, so we need to apply Karis average to each block
// of 4 samples to prevent fireflies (very bright subpixels, leads to pulsating
// artifacts).
groups[0] = (a+b+d+e) * (0.125f/4.0f);
groups[1] = (b+c+e+f) * (0.125f/4.0f);
groups[2] = (d+e+g+h) * (0.125f/4.0f);
groups[3] = (e+f+h+i) * (0.125f/4.0f);
groups[4] = (j+k+l+m) * (0.5f/4.0f);
groups[0] *= karis_average(groups[0]);
groups[1] *= karis_average(groups[1]);
groups[2] *= karis_average(groups[2]);
groups[3] *= karis_average(groups[3]);
groups[4] *= karis_average(groups[4]);
out_color = groups[0]+groups[1]+groups[2]+groups[3]+groups[4];
break;
default:
#endif
// Apply weighted distribution:
// 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1
// a,b,d,e * 0.125
// b,c,e,f * 0.125
// d,e,g,h * 0.125
// e,f,h,i * 0.125
// j,k,l,m * 0.5
// This shows 5 square areas that are being sampled. But some of them overlap,
// so to have an energy preserving downsample we need to make some adjustments.
// The weights are the distributed, so that the sum of j,k,l,m (e.g.)
// contribute 0.5 to the final color output. The code below is written
// to effectively yield this sum. We get:
// 0.125*5 + 0.03125*4 + 0.0625*4 = 1
out_color = e*0.125;
out_color += (a+c+g+i)*0.03125;
out_color += (b+d+f+h)*0.0625;
out_color += (j+k+l+m)*0.125;
out_color = max(out_color, 0.0001f);
#if KARIS
break;
}
#endif

}
#endif
2 changes: 1 addition & 1 deletion include/shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ namespace shader {

extern GLuint downsample_program;
extern struct DownsampleUniforms {
GLuint resolution;
GLuint resolution, is_mip0;
} downsample_uniforms;

extern GLuint upsample_program;
Expand Down
7 changes: 6 additions & 1 deletion src/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,10 +748,15 @@ void blurBloomFbo(){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, graphics::hdr_buffer);

for(const auto &mip : graphics::bloom_mip_infos) {
for(int i = 0; i < graphics::bloom_mip_infos.size(); ++i) {
const auto &mip = graphics::bloom_mip_infos[i];

glViewport(0, 0, mip.size.x, mip.size.y);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mip.texture, 0);

int is_mip0 = i == graphics::bloom_mip_infos.size() - 1;
glUniform1i(shader::downsample_uniforms.is_mip0, is_mip0);

drawQuad();

// Set next iterations properties
Expand Down
1 change: 1 addition & 0 deletions src/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ void loadDownsampleShader(std::string path){

// Grab uniforms to modify during rendering
downsample_uniforms.resolution = glGetUniformLocation(downsample_program, "resolution");
downsample_uniforms.is_mip0 = glGetUniformLocation(downsample_program, "is_mip0");

glUseProgram(downsample_program);
// Set fixed locations for textures in GL_TEXTUREi
Expand Down

0 comments on commit 8d6f3ed

Please sign in to comment.