summaryrefslogtreecommitdiff
path: root/advanced_lighting/7.bloom
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-06-15 16:11:31 +0500
committerpryazha <pryadeiniv@mail.ru>2025-06-15 16:11:31 +0500
commit9d944f26d359e4bc1ffd8e44350b0df9f0935b18 (patch)
tree9759a83a76ab741a587b99f00c2463eafd05d813 /advanced_lighting/7.bloom
parentd65ddd07a43d5ffdcf2ddf90d6f86626cf9b92d8 (diff)
something
Diffstat (limited to 'advanced_lighting/7.bloom')
-rw-r--r--advanced_lighting/7.bloom/bloom.c287
-rwxr-xr-xadvanced_lighting/7.bloom/build5
-rw-r--r--advanced_lighting/7.bloom/shaders/bloom.frag45
-rw-r--r--advanced_lighting/7.bloom/shaders/bloom.vert24
-rw-r--r--advanced_lighting/7.bloom/shaders/blur.frag29
-rw-r--r--advanced_lighting/7.bloom/shaders/blur.vert14
-rw-r--r--advanced_lighting/7.bloom/shaders/final.frag25
-rw-r--r--advanced_lighting/7.bloom/shaders/final.vert14
-rw-r--r--advanced_lighting/7.bloom/shaders/light.frag22
-rw-r--r--advanced_lighting/7.bloom/shaders/test_blur.frag28
-rw-r--r--advanced_lighting/7.bloom/shaders/test_blur.vert14
11 files changed, 507 insertions, 0 deletions
diff --git a/advanced_lighting/7.bloom/bloom.c b/advanced_lighting/7.bloom/bloom.c
new file mode 100644
index 0000000..70adcfe
--- /dev/null
+++ b/advanced_lighting/7.bloom/bloom.c
@@ -0,0 +1,287 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+
+#include "pwyazh.h"
+#include "pwyazh_GL.h"
+
+#include "common.h"
+
+#define LIGHT_COUNT 3
+
+int main(void)
+{
+ S32 width = 1600;
+ S32 height = 900;
+
+ /* NOTE(pryazha): GLFW init */
+ glfwSetErrorCallback(error_callback);
+ if (glfwInit() == GLFW_FALSE)
+ return 1;
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
+ GLFWwindow *window = glfwCreateWindow(width, height, "Bloom", 0, 0);
+ if (!window)
+ return 1;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwMakeContextCurrent(window);
+ if (glewInit() != GLEW_OK)
+ return 1;
+
+ glEnable(GL_DEPTH_TEST);
+
+ /* NOTE(pryazha): Program init */
+ State state = {0};
+ state.arena = arena_alloc(Kilobytes(256));
+ state.input.first_mouse = 1;
+ state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f };
+
+ V3F light_positions[LIGHT_COUNT];
+ F32 da = 2.0f*pi_F32/LIGHT_COUNT;
+ F32 a = 0.0f;
+ F32 r = 2.0f;
+ for (S32 i = 0; i < LIGHT_COUNT; i++, a += da)
+ light_positions[i] = v3f(f32_sin(a)*r, 0.0f, f32_cos(a)*r);
+
+ V3F light_colors[LIGHT_COUNT] = {
+ {5.0f, 5.0f, 5.0f},
+ {10.0f, 0.0f, 0.0f},
+ {0.0f, 5.0f, 0.0f},
+ };
+
+ S32 bloom = 0;
+ F32 exposure = 1.0f;
+
+ /* NOTE(pryazha): Textures */
+ U32 woood_texture = load_texture_gamma("../../data/textures/wood.png", 1);
+
+ /* NOTE(pryazha): Meshes */
+ Mesh *quad = mesh_gen_quad(state.arena);
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+
+ /* NOTE(pryazha): Shaders */
+ U32 shader = load_shader("shaders/bloom.vert", "shaders/bloom.frag");
+ U32 shader_light = load_shader("shaders/bloom.vert", "shaders/light.frag");
+ U32 shader_blur = load_shader("shaders/blur.vert", "shaders/blur.frag");
+ U32 shader_test_blur = load_shader("shaders/test_blur.vert", "shaders/test_blur.frag");
+ U32 shader_final = load_shader("shaders/final.vert", "shaders/final.frag");
+
+ glUseProgram(shader_final);
+ shader_set_1i(shader_final, "scene", 0);
+ shader_set_1i(shader_final, "blur", 1);
+
+ /* NOTE(pryazha): Framebuffers */
+ U32 hdrfbo;
+ glGenFramebuffers(1, &hdrfbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
+
+ U32 colorbuffers[2];
+ glGenTextures(2, colorbuffers);
+ for (S32 i = 0; i < 2; ++i) {
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, colorbuffers[i], 0);
+ }
+
+ U32 hdrrbo;
+ glGenRenderbuffers(1, &hdrrbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, hdrrbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdrrbo);
+
+ U32 attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
+ glDrawBuffers(2, attachments);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: framebuffer not complete\n");
+
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ U32 pingpong_fbo[2];
+ U32 pingpong_colorbuffers[2];
+ glGenFramebuffers(2, pingpong_fbo);
+ glGenTextures(2, pingpong_colorbuffers);
+ for (S32 i = 0; i < 2; i++) {
+ glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[i]);
+ glBindTexture(GL_TEXTURE_2D, pingpong_colorbuffers[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpong_colorbuffers[i], 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: framebuffer not complete\n");
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ U32 blur_fbo;
+ glGenFramebuffers(1, &blur_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
+ U32 blur_colorbuffer;
+ glGenTextures(1, &blur_colorbuffer);
+ glBindTexture(GL_TEXTURE_2D, blur_colorbuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blur_colorbuffer, 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: blur framebuffer not complete\n");
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ S32 myblur = 0;
+
+ F64 last_time = glfwGetTime();
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
+ glfwGetFramebufferSize(window, &width, &height);
+ process_glfw_keyboard(window, &state.input);
+ process_glfw_mouse_pos(window, &state.input);
+
+ if (key_first_press(state.input.exit))
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+
+ F32 speed = 2.0f;
+ V3F dv = get_dv_camera_first_person(&state.input, &state.camera, speed, state.dt);
+ state.camera_dp = v3f_add(state.camera_dp, dv);
+ state.camera_dp = v3f_scalef(state.camera_dp, 0.8f);
+ state.camera.pos = v3f_add(state.camera.pos, state.camera_dp);
+
+ F32 sensitivity = 0.1f;
+ state.input.mouse_offset = v2f_scalef(state.input.mouse_offset, sensitivity);
+ state.camera.yaw += state.input.mouse_offset.x;
+ state.camera.pitch += state.input.mouse_offset.y;
+ if (state.camera.pitch > 89.0f)
+ state.camera.pitch = 89.0f;
+ if (state.camera.pitch < -89.0f)
+ state.camera.pitch = -89.0f;
+
+ /* NOTE(pryazha): Update */
+ if (key_is_pressed(state.input.action_down))
+ exposure -= 0.01f;
+ if (key_is_pressed(state.input.action_up))
+ exposure += 0.01f;
+
+ if (key_first_press(state.input.jump))
+ bloom = !bloom;
+
+ if (key_first_press(state.input.action_left))
+ myblur = !myblur;
+
+ for (S32 i = 0; i < LIGHT_COUNT; i++)
+ light_positions[i].y = f32_sin(glfwGetTime()+i);
+
+ /* NOTE(pryazha): Render */
+ glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Render to HDR framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ F32 ar = (F32)width/(F32)height;
+ MAT4 projection = camera_persp(state.camera, ar);
+ MAT4 view = get_view_matrix(&state.camera);
+
+ glUseProgram(shader);
+ shader_set_mat4fv(shader, "projection", projection);
+ shader_set_mat4fv(shader, "view", view);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ char light_string[1024];
+ snprintf(light_string, 1024, "lights[%d].position", i);
+ shader_set_3fv(shader, light_string, light_positions[i]);
+ snprintf(light_string, 1024, "lights[%d].color", i);
+ shader_set_3fv(shader, light_string, light_colors[i]);
+ }
+ shader_set_3fv(shader, "view_pos", state.camera.pos);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, woood_texture);
+
+ MAT4 model = mat4_make_scale(v3f(10.0f, 0.25f, 10.0f));
+ model = mat4_translate(model, v3f(0.0f, -2.0f, 0.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_rotate_angles(model, v3f(30.0f, 45.0f, 0.0f));
+ model = mat4_translate(model, v3f(-0.5f, -1.0f, -2.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_rotate_angles(model, v3f(-30.0f, 45.0f, 90.0f));
+ model = mat4_translate(model, v3f(0.75f, -1.5f, 1.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glUseProgram(0);
+
+ glUseProgram(shader_light);
+ shader_set_mat4fv(shader_light, "projection", projection);
+ shader_set_mat4fv(shader_light, "view", view);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ model = mat4_make_scale(v3f(0.2f, 0.2f, 0.2f));
+ model = mat4_translate(model, light_positions[i]);
+ shader_set_mat4fv(shader_light, "model", model);
+ shader_set_3fv(shader_light, "light_color", light_colors[i]);
+ mesh_draw(cube);
+ }
+ glUseProgram(0);
+
+ S32 horizontal = 1, first = 1, amount = 10;
+ glUseProgram(shader_blur);
+ for (S32 i = 0; i < amount; i++) {
+ glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[horizontal]);
+ shader_set_1i(shader_blur, "horizontal", horizontal);
+ glBindTexture(GL_TEXTURE_2D, first ? colorbuffers[1] : pingpong_colorbuffers[!horizontal]);
+ mesh_draw(quad);
+ horizontal = !horizontal;
+ if (first)
+ first = 0;
+ }
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
+ glUseProgram(shader_test_blur);
+ glActiveTexture(0);
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[1]);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader_final);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[0]);
+ glActiveTexture(GL_TEXTURE1);
+ if (myblur) {
+ glBindTexture(GL_TEXTURE_2D, blur_colorbuffer);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, pingpong_colorbuffers[!horizontal]);
+ }
+ shader_set_1i(shader_final, "bloom", bloom);
+ shader_set_1f(shader_final, "exposure", exposure);
+ mesh_draw(quad);
+
+ glfwSwapBuffers(window);
+
+ F64 time = glfwGetTime();
+ state.dt = time - last_time;
+ last_time = time;
+
+ input_update_last_state(&state.input);
+ }
+
+ return 0;
+}
diff --git a/advanced_lighting/7.bloom/build b/advanced_lighting/7.bloom/build
new file mode 100755
index 0000000..99df29a
--- /dev/null
+++ b/advanced_lighting/7.bloom/build
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='bloom'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/advanced_lighting/7.bloom/shaders/bloom.frag b/advanced_lighting/7.bloom/shaders/bloom.frag
new file mode 100644
index 0000000..88decf8
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/bloom.frag
@@ -0,0 +1,45 @@
+#version 330 core
+
+in VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+layout(location = 0) out vec4 frag_color;
+layout(location = 1) out vec4 bright_color;
+
+struct light_t {
+ vec3 position;
+ vec3 color;
+};
+
+uniform light_t lights[3];
+uniform sampler2D diffuse_texture;
+uniform vec3 view_pos;
+
+const int light_count = 3;
+
+void main(void)
+{
+ vec3 color = texture(diffuse_texture, vs_out.tex_coords).rgb;
+ vec3 ambient = 0.01 * color;
+ vec3 lighting = vec3(0.0);
+ vec3 view_dir = normalize(view_pos - vs_out.position);
+ for (int i = 0; i < light_count; i++) {
+ vec3 light_dir = normalize(lights[i].position - vs_out.position);
+ float diff = max(dot(light_dir, vs_out.normal), 0.0);
+ vec3 result = lights[i].color * diff * color;
+ float distance = length(vs_out.position - lights[i].position);
+ result *= 1.0 / (distance * distance);
+ lighting += result;
+ }
+ vec3 result = ambient + lighting;
+ float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
+ if (brightness > 1.0) {
+ bright_color = vec4(result, 1.0);
+ } else {
+ bright_color = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/bloom.vert b/advanced_lighting/7.bloom/shaders/bloom.vert
new file mode 100644
index 0000000..0c9dc02
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/bloom.vert
@@ -0,0 +1,24 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec3 normal;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 model;
+
+void main()
+{
+ vs_out.position = vec3(model * vec4(position, 1.0));
+ mat3 normal_matrix = transpose(inverse(mat3(model)));
+ vs_out.normal = normalize(normal_matrix * normal);
+ vs_out.tex_coords = tex_coords;
+ gl_Position = projection * view * model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/blur.frag b/advanced_lighting/7.bloom/shaders/blur.frag
new file mode 100644
index 0000000..67b7e43
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/blur.frag
@@ -0,0 +1,29 @@
+#version 330 core
+
+in VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+out vec4 frag_color;
+
+uniform sampler2D image;
+uniform bool horizontal;
+uniform float weights[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162);
+
+void main(void)
+{
+ vec2 tex_offset = 1.0 / textureSize(image, 0);
+ vec3 result = texture(image, vs_out.tex_coords).rgb * weights[0];
+ if (horizontal) {
+ for (int i = 1; i < 5; i++) {
+ result += texture(image, vs_out.tex_coords + vec2(tex_offset.x * i, 0.0)).rgb * weights[i];
+ result += texture(image, vs_out.tex_coords - vec2(tex_offset.x * i, 0.0)).rgb * weights[i];
+ }
+ } else {
+ for (int i = 1; i < 5; i++) {
+ result += texture(image, vs_out.tex_coords + vec2(0.0, tex_offset.y * i)).rgb * weights[i];
+ result += texture(image, vs_out.tex_coords - vec2(0.0, tex_offset.y * i)).rgb * weights[i];
+ }
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/blur.vert b/advanced_lighting/7.bloom/shaders/blur.vert
new file mode 100644
index 0000000..e4ced24
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/blur.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+void main(void)
+{
+ vs_out.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/final.frag b/advanced_lighting/7.bloom/shaders/final.frag
new file mode 100644
index 0000000..fe9f5d7
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/final.frag
@@ -0,0 +1,25 @@
+#version 330 core
+
+in VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+out vec4 frag_color;
+
+uniform sampler2D scene;
+uniform sampler2D blur;
+uniform bool bloom;
+uniform float exposure;
+
+void main()
+{
+ const float gamma = 2.2;
+ vec3 scene_color = texture(scene, vs_out.tex_coords).rgb;
+ vec3 blur_color = texture(blur, vs_out.tex_coords).rgb;
+ if (bloom) {
+ scene_color += blur_color;
+ }
+ vec3 result = vec3(1.0) - exp(-scene_color * exposure);
+ result = pow(result, vec3(1.0 / gamma));
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/final.vert b/advanced_lighting/7.bloom/shaders/final.vert
new file mode 100644
index 0000000..f6a4e38
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/final.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+void main()
+{
+ vs_out.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/light.frag b/advanced_lighting/7.bloom/shaders/light.frag
new file mode 100644
index 0000000..72a2874
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/light.frag
@@ -0,0 +1,22 @@
+#version 330 core
+
+in VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+layout(location = 0) out vec4 frag_color;
+layout(location = 1) out vec4 bright_color;
+
+uniform vec3 light_color;
+
+void main()
+{
+ frag_color = vec4(light_color, 1.0);
+ float brightness = dot(vec3(frag_color), vec3(0.2126, 0.7152, 0.0722));
+ if (brightness > 1.0)
+ bright_color = vec4(vec3(frag_color), 1.0);
+ else
+ bright_color = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/test_blur.frag b/advanced_lighting/7.bloom/shaders/test_blur.frag
new file mode 100644
index 0000000..8d7ee9a
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/test_blur.frag
@@ -0,0 +1,28 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+uniform float weights[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162);
+
+void main()
+{
+ vec2 texture_offset = 1.0 / textureSize(colorbuffer, 0);
+ vec3 result = texture(colorbuffer, vert.tex_coords).rgb * weights[0];
+ for (int x = 1; x < weights.length(); x++) {
+ vec2 offset = vec2(texture_offset.x * x, 0.0f);
+ result += texture(colorbuffer, vert.tex_coords + offset).rgb * weights[x];
+ result += texture(colorbuffer, vert.tex_coords - offset).rgb * weights[x];
+ }
+ for (int y = 1; y < weights.length(); y++) {
+ vec2 offset = vec2(0.0f, texture_offset.y * y);
+ result += texture(colorbuffer, vert.tex_coords + offset).rgb * weights[y];
+ result += texture(colorbuffer, vert.tex_coords - offset).rgb * weights[y];
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/test_blur.vert b/advanced_lighting/7.bloom/shaders/test_blur.vert
new file mode 100644
index 0000000..eed3be3
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/test_blur.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}