Skip to content

Instantly share code, notes, and snippets.

@kaadmy
Created February 26, 2022 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaadmy/58a2bb4b42cbc5c55cda8c7bcf8446a3 to your computer and use it in GitHub Desktop.
Save kaadmy/58a2bb4b42cbc5c55cda8c7bcf8446a3 to your computer and use it in GitHub Desktop.
#define BLOOM_LEVELS 6
int bloom_size[BLOOM_LEVELS][2];
GLuint bloom_fbo[BLOOM_LEVELS][2];
GLuint bloom_tex[2];
void bloomInit(void) {
for(int j = 0; j < 2; j++) {
glBindTexture(GL_TEXTURE_2D, bloom_tex[j]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
for(int i = 0; i < BLOOM_LEVELS; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, bloom_fbo[i][j]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bloom_tex[j], i);
}
}
}
void bloomResize(int width, int height) {
// Initial size is half resolution.
bloom_size[0][0] = w / 2;
bloom_size[0][1] = h / 2;
// Calculate mip sizes.
for(int i = 1; i < BLOOM_LEVELS; i++) {
bloom_size[i][0] = MAX(bloom_size[i - 1][0] / 2, 1);
bloom_size[i][1] = MAX(bloom_size[i - 1][1] / 2, 1);
}
// Resize texture storage.
for(int j = 0; j < 2; j++) {
glBindTexture(GL_TEXTURE_2D, bloom_tex[j]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R11F_G11F_B10F, bloom_size[0][0], bloom_size[0][1], 0, GL_RGB, GL_FLOAT, NULL);
// Ideally, this should be accomplished by `glTexStorage2D`,
// but that would require GL 4.2 or `GL_EXT_texture_storage`.
glGenerateMipmap(GL_TEXTURE_2D);
}
}
void bloomDraw(void) {
// ====================
//
// Extract color with threshold from main scene color attachment.
glUseProgram(program_bloom_extract);
glViewport(0, 0, bloom_size[0][0], bloom_size[0][1]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bloom_fbo[0][1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, main_color_attachment);
drawFullscreenQuad();
// ====================
//
// Ping pong separable blur.
glUseProgram(program_bloom_blur);
for(int i = 0; i < BLOOM_LEVELS; i++) {
glViewport(0, 0, bloom_size[i][0], bloom_size[i][1]);
// ====================
//
// X axis horizontal blur.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bloom_fbo[i][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, bloom_tex[1]);
// XY = pixel UV step, Z = mip level of source texture.
glUniform3f("u_step", 1.0 / bloom_size[i][0], 0.0, (float) MAX(i - 1, 0));
drawFullscreenQuad();
// ====================
//
// Y axis vertical blur.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bloom_fbo[i][1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, bloom_tex[0]);
glUniform3f("u_step", 0.0, 1.0 / bloom_size[i][1], (float) i);
drawFullscreenQuad();
}
// ====================
//
// Composite bloom layers together.
glUseProgram(program_bloom_composite);
glViewport(0, 0, bloom_size[0][0], bloom_size[0][1]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bloom_fbo[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, bloom_tex[1]);
drawFullscreenQuad();
}
in vec2 v_uv;
out vec4 rt0;
uniform sampler2D us_tex0;
uniform vec3 u_step;
void main() {
vec2 a = u_step.xy * 1.3846;
vec2 b = u_step.xy * 3.2307;
rt0 = textureLod(us_tex0, v_uv, u_step.z) * 0.2270;
rt0 += textureLod(us_tex0, v_uv - a, u_step.z) * 0.3162;
rt0 += textureLod(us_tex0, v_uv + a, u_step.z) * 0.3162;
rt0 += textureLod(us_tex0, v_uv - b, u_step.z) * 0.0702;
rt0 += textureLod(us_tex0, v_uv + b, u_step.z) * 0.0702;
};
in vec2 v_uv;
out vec4 rt0;
uniform sampler2D us_tex0;
void main() {
rt0 = sampleBicubic(us_tex0, v_uv, 1.0) * 1.0;
rt0 += sampleBicubic(us_tex0, v_uv, 2.0) * 0.95;
rt0 += sampleBicubic(us_tex0, v_uv, 3.0) * 0.9;
rt0 += sampleBicubic(us_tex0, v_uv, 4.0) * 0.7;
rt0 += sampleBicubic(us_tex0, v_uv, 5.0) * 0.4;
rt0 *= 0.3;
};
in vec2 v_uv;
out vec4 rt0;
uniform sampler2D us_tex0;
void main() {
rt0 = textureLod(us_tex0, v_uv, 0.0);
rt0.rgb *= smoothstep(3.0, 4.0, dot(rt0.rgb, vec3(0.2126, 0.7152, 0.0722)));
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment