From 9fc6c6f5995832eacac512377932457ad1972be8 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Sat, 19 Apr 2025 00:47:30 -0500 Subject: [PATCH] New Bloom Algorithm --- imgui.ini | 6 +- remake/build.log | 1 + src/assets/scenes/lighting_test_2.cene | 18 ++-- src/assets/shaders/blur.frag | 20 ++++ src/assets/shaders/composite.frag | 14 +++ src/assets/shaders/fullscreen.vert | 10 ++ src/src/Renderer.cpp | 144 ++++++++++++++++++------- 7 files changed, 160 insertions(+), 53 deletions(-) create mode 100644 src/assets/shaders/composite.frag create mode 100644 src/assets/shaders/fullscreen.vert diff --git a/imgui.ini b/imgui.ini index 1272a06..e2c3616 100644 --- a/imgui.ini +++ b/imgui.ini @@ -92,9 +92,9 @@ DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split= DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,597 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,559 Split=X Selected=0x9B5D3198 DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1283,481 Split=Y Selected=0x9B5D3198 - DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1283,306 Selected=0x9B5D3198 - DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1283,251 Selected=0xEA83D666 + DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1283,306 HiddenTabBar=1 Selected=0x9B5D3198 + DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1283,251 HiddenTabBar=1 Selected=0xEA83D666 DockNode ID=0x00000006 Parent=0x00000008 SizeRef=248,481 Split=Y Selected=0x3FC1A724 - DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,315 Selected=0x3FC1A724 + DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,315 HiddenTabBar=1 Selected=0x3FC1A724 DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,242 HiddenTabBar=1 Selected=0xA873C17F diff --git a/remake/build.log b/remake/build.log index 60dc3d1..fca714e 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,2 +1,3 @@ +[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Renderer.cpp -o src\build\Renderer.o [LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\Entitys\Object.o src\build\utils\EngineConfig.o src\build\utils\ExceptionHandler.o src\build\utils\FileDialog.o src\build\utils\GameObjectsList.o src\build\utils\Logging.o src\build\utils\Profiler.o src\build\utils\Shader.o src\build\utils\UID.o src\build\utils\utils.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto [RUN] Executed app.exe successfully. diff --git a/src/assets/scenes/lighting_test_2.cene b/src/assets/scenes/lighting_test_2.cene index a16606d..52c1ea9 100644 --- a/src/assets/scenes/lighting_test_2.cene +++ b/src/assets/scenes/lighting_test_2.cene @@ -1,6 +1,6 @@ engine_version: 0.1.0 scene_name: lighting_test_2 -scene_hash: f2105b58a0e6aed672541892cfc067be2cec4800ba5b5d780d0c035e9dc141a9 +scene_hash: c084720adfdfb7fefd6c0c6c1654d18bc2245da4d222165c332b57dcc8d78c12 format_version: 1 objects: - name: Tiles @@ -115,7 +115,7 @@ objects: - name: Red uid: 6afde2dd47aa4557b6afb1a607c99dc8 id: 13 - position: [841.838257, 558.36377] + position: [1079.61902, 527.103088] rotation: 0 layer: 2 visable: true @@ -133,7 +133,7 @@ objects: - name: Green uid: 0f950d76d24b4dc18f54cab2c3aaaf9a id: 14 - position: [1518.33362, 1099.0614] + position: [1426.51587, 1320.61597] rotation: 0 layer: 2 visable: true @@ -151,7 +151,7 @@ objects: - name: Blue uid: 09f722f51c7c4b0f98de3a0a16d127c4 id: 15 - position: [711.828064, 1414.57483] + position: [565.865173, 1224.28101] rotation: 0 layer: 2 visable: true @@ -210,9 +210,9 @@ objects: primary: true children: [] color_correction: - brightness: 1 - saturation: 1 - gamma: 1 + brightness: 2 + saturation: 2 + gamma: 1.05999994 bloom: true - intensity: 1.20000005 - threshold: 0.200000003 \ No newline at end of file + intensity: 1.21000004 + threshold: 0.25 \ No newline at end of file diff --git a/src/assets/shaders/blur.frag b/src/assets/shaders/blur.frag index e69de29..8b936bc 100644 --- a/src/assets/shaders/blur.frag +++ b/src/assets/shaders/blur.frag @@ -0,0 +1,20 @@ +#version 330 core +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D uTex; +uniform vec2 uDirection; + +const float weights[5] = float[](0.204164, 0.304005, 0.093913, 0.010381, 0.000336); + +void main() { + vec3 result = texture(uTex, vUV).rgb * weights[0]; + + for (int i = 1; i < 5; ++i) { + vec2 offset = uDirection * float(i); + result += texture(uTex, vUV + offset).rgb * weights[i]; + result += texture(uTex, vUV - offset).rgb * weights[i]; + } + + FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/src/assets/shaders/composite.frag b/src/assets/shaders/composite.frag new file mode 100644 index 0000000..7c5a4ac --- /dev/null +++ b/src/assets/shaders/composite.frag @@ -0,0 +1,14 @@ + +#version 330 core +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D uScene; +uniform sampler2D uBloom; +uniform float uIntensity; + +void main() { + vec3 sceneColor = texture(uScene, vUV).rgb; + vec3 bloomColor = texture(uBloom, vUV).rgb * uIntensity; + FragColor = vec4(sceneColor + bloomColor, 1.0); +} \ No newline at end of file diff --git a/src/assets/shaders/fullscreen.vert b/src/assets/shaders/fullscreen.vert new file mode 100644 index 0000000..349f630 --- /dev/null +++ b/src/assets/shaders/fullscreen.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; + +out vec2 vUV; + +void main() { + vUV = aUV; + gl_Position = vec4(aPos.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/src/src/Renderer.cpp b/src/src/Renderer.cpp index 39868b4..0c869b8 100644 --- a/src/src/Renderer.cpp +++ b/src/src/Renderer.cpp @@ -17,7 +17,16 @@ static Shader spriteShader; static Shader unlitShader; -static Shader bloomShader; +static Shader tilemapShader; + +static Shader extractShader; +static Shader blurShader; +static Shader compositeShader; + +static GLuint extractFBO, extractTexture; +static GLuint blurFBO_H, blurTexture_H; +static GLuint blurFBO_V, blurTexture_V; +static GLuint bloomFBO, bloomTexture; GLuint Renderer::fbo = 0; GLuint Renderer::textureColorBuffer = 0; @@ -41,8 +50,6 @@ int Renderer::s_ClusterRows = 0; GLuint Renderer::bloomFBO = 0; GLuint Renderer::bloomTexture = 0; -static Shader tilemapShader; - void Renderer::InitQuad() { float vertices[] = { @@ -93,23 +100,51 @@ void Renderer::Init() // Load lit shader + // Core renderers spriteShader.LoadFromFile("src/assets/shaders/sprite.vert", "src/assets/shaders/sprite.frag"); - // Load unlit shader unlitShader.LoadFromFile("src/assets/shaders/unlit.vert", "src/assets/shaders/unlit.frag"); + tilemapShader.LoadFromFile("src/assets/shaders/tilemap.vert", "src/assets/shaders/tilemap.frag"); - bloomShader.LoadFromFile("src/assets/shaders/bloom.vert", "src/assets/shaders/bloom.frag"); + // Bloom pipeline + extractShader.LoadFromFile("src/assets/shaders/fullscreen.vert", "src/assets/shaders/extract.frag"); + blurShader.LoadFromFile("src/assets/shaders/fullscreen.vert", "src/assets/shaders/blur.frag"); + compositeShader.LoadFromFile("src/assets/shaders/fullscreen.vert", "src/assets/shaders/composite.frag"); SetColorCorrection(std::make_unique()); glGenBuffers(1, &s_ClusterSSBO); + // Bloom textures and framebuffers + glGenFramebuffers(1, &extractFBO); + glBindFramebuffer(GL_FRAMEBUFFER, extractFBO); + glGenTextures(1, &extractTexture); + glBindTexture(GL_TEXTURE_2D, extractTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, extractTexture, 0); + + glGenFramebuffers(1, &blurFBO_H); + glBindFramebuffer(GL_FRAMEBUFFER, blurFBO_H); + glGenTextures(1, &blurTexture_H); + glBindTexture(GL_TEXTURE_2D, blurTexture_H); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blurTexture_H, 0); + + glGenFramebuffers(1, &blurFBO_V); + glBindFramebuffer(GL_FRAMEBUFFER, blurFBO_V); + glGenTextures(1, &blurTexture_V); + glBindTexture(GL_TEXTURE_2D, blurTexture_V); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blurTexture_V, 0); + + // Final composite target glGenFramebuffers(1, &bloomFBO); glBindFramebuffer(GL_FRAMEBUFFER, bloomFBO); - - // Allocate bloom FBO/texture once - glGenFramebuffers(1, &bloomFBO); - glBindFramebuffer(GL_FRAMEBUFFER, bloomFBO); - glGenTextures(1, &bloomTexture); glBindTexture(GL_TEXTURE_2D, bloomTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); @@ -117,9 +152,6 @@ void Renderer::Init() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bloomTexture, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - Logger::LogError("Bloom framebuffer not complete!"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); // Create a 1x1 flat normal map (RGB: 128,128,255) @@ -180,22 +212,29 @@ void Renderer::UpdateClusterLights() void Renderer::Resize(int w, int h) { - if (w == width && h == height) return; width = w; height = h; + // Resize all textures glBindTexture(GL_TEXTURE_2D, textureColorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + + glBindTexture(GL_TEXTURE_2D, extractTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + + glBindTexture(GL_TEXTURE_2D, blurTexture_H); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + + glBindTexture(GL_TEXTURE_2D, blurTexture_V); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); + + glBindTexture(GL_TEXTURE_2D, bloomTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - - // Resize bloom texture if window changes - glBindTexture(GL_TEXTURE_2D, bloomTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); } void Renderer::Begin() @@ -527,49 +566,72 @@ void Renderer::DrawGizmoCircle( - GLuint Renderer::GetFinalTexture() { PROFILE_SCOPE("Renderer::GetFinalTexture"); - GLuint inputTexture = GetRenderTexture(); + GLuint sceneTex = GetRenderTexture(); - if (!s_ColorCorrection->bloom) - { - return inputTexture; - } + if (!s_ColorCorrection || !s_ColorCorrection->bloom) + return sceneTex; - // Bind persistent FBO - glBindFramebuffer(GL_FRAMEBUFFER, bloomFBO); - - // Setup and clear + // 1. Extract bright regions + glBindFramebuffer(GL_FRAMEBUFFER, extractFBO); glViewport(0, 0, width, height); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); - // Bloom shader pass - bloomShader.Use(); - bloomShader.SetInt("uTex", 0); - bloomShader.SetVec2("uTexelSize", glm::vec2(1.0f / width, 1.0f / height)); - bloomShader.SetFloat("uThreshold", s_ColorCorrection->threshold); - bloomShader.SetFloat("uIntensity", s_ColorCorrection->intensity); + extractShader.Use(); + extractShader.SetInt("uScene", 0); + extractShader.SetFloat("uThreshold", s_ColorCorrection->threshold); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, inputTexture); + glBindTexture(GL_TEXTURE_2D, sceneTex); glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + // 2. Horizontal blur + glBindFramebuffer(GL_FRAMEBUFFER, blurFBO_H); + glClear(GL_COLOR_BUFFER_BIT); + + blurShader.Use(); + blurShader.SetInt("uTex", 0); + blurShader.SetVec2("uDirection", glm::vec2(1.0f / width, 0.0f)); + + glBindTexture(GL_TEXTURE_2D, extractTexture); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // 3. Vertical blur + glBindFramebuffer(GL_FRAMEBUFFER, blurFBO_V); + glClear(GL_COLOR_BUFFER_BIT); + + blurShader.SetVec2("uDirection", glm::vec2(0.0f, 1.0f / height)); + glBindTexture(GL_TEXTURE_2D, blurTexture_H); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // 4. Final composite + glBindFramebuffer(GL_FRAMEBUFFER, bloomFBO); + glClear(GL_COLOR_BUFFER_BIT); + + compositeShader.Use(); + compositeShader.SetInt("uScene", 0); + compositeShader.SetInt("uBloom", 1); + compositeShader.SetFloat("uIntensity", s_ColorCorrection->intensity); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, sceneTex); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, blurTexture_V); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindFramebuffer(GL_FRAMEBUFFER, 0); return bloomTexture; } - - - - GLuint Renderer::GetRenderTexture() { return textureColorBuffer;