From 239f40a93ac6fff07717e33c58b0fc3f7b37bd76 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Sat, 19 Apr 2025 00:31:33 -0500 Subject: [PATCH] Added bloom --- imgui.ini | 40 ++++++------ remake/build.log | 2 + src/assets/scenes/lighting_test_2.cene | 25 ++++---- src/assets/shaders/bloom.frag | 39 ++++++++++++ src/assets/shaders/bloom.vert | 10 +++ src/assets/shaders/blur.frag | 0 src/assets/shaders/extract.frag | 13 ++++ src/src/Engine.cpp | 37 +++++++++-- src/src/Renderer.cpp | 87 ++++++++++++++++++++++++-- src/src/Renderer.h | 25 ++++++-- 10 files changed, 234 insertions(+), 44 deletions(-) create mode 100644 src/assets/shaders/bloom.frag create mode 100644 src/assets/shaders/bloom.vert create mode 100644 src/assets/shaders/blur.frag create mode 100644 src/assets/shaders/extract.frag diff --git a/imgui.ini b/imgui.ini index 99ce4f8..1272a06 100644 --- a/imgui.ini +++ b/imgui.ini @@ -27,7 +27,7 @@ DockId=0x00000009,0 [Window][Viewport] Pos=387,19 -Size=1533,453 +Size=1533,597 Collapsed=0 DockId=0x00000007,0 @@ -36,16 +36,16 @@ Size=1280,19 Collapsed=0 [Window][Performance Info] -Pos=1672,474 -Size=248,522 +Pos=1672,618 +Size=248,315 Collapsed=0 DockId=0x00000003,0 [Window][Console] -Pos=387,474 -Size=1283,703 +Pos=387,926 +Size=1283,251 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000C,0 [Window][Tilemap Editor] Pos=265,19 @@ -54,32 +54,32 @@ Collapsed=0 DockId=0x00000007,1 [Window][Profiler] -Pos=387,474 -Size=1283,703 +Pos=387,618 +Size=1283,306 Collapsed=0 -DockId=0x00000005,0 +DockId=0x0000000B,0 [Window][Profiler Timeline] Pos=265,69 Size=623,651 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000B,1 [Window][Profiler (Unity Style)] Pos=265,430 Size=623,290 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000B,1 [Window][Profiler Timeline View] Pos=265,526 Size=1263,651 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000B,1 [Window][Color Correction] -Pos=1672,998 -Size=248,179 +Pos=1672,935 +Size=248,242 Collapsed=0 DockId=0x00000004,0 @@ -89,10 +89,12 @@ DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split= DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,623 HiddenTabBar=1 Selected=0x12EF0F59 DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,533 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000002 Parent=0x11111111 SizeRef=1533,701 Split=Y Selected=0xC450F867 - DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,453 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 - DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,703 Split=X Selected=0x9B5D3198 - DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1283,481 Selected=0xEA83D666 + 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=0x00000006 Parent=0x00000008 SizeRef=248,481 Split=Y Selected=0x3FC1A724 - DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,522 Selected=0x3FC1A724 - DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,179 HiddenTabBar=1 Selected=0xA873C17F + DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,315 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 e69de29..60dc3d1 100644 --- a/remake/build.log +++ b/remake/build.log @@ -0,0 +1,2 @@ +[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 2ce155f..a16606d 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: 59f49b4319d714200de64e90f576e787dcc9aa5d0dfc217d78e87f8332be626f +scene_hash: f2105b58a0e6aed672541892cfc067be2cec4800ba5b5d780d0c035e9dc141a9 format_version: 1 objects: - name: Tiles @@ -67,7 +67,7 @@ objects: - name: Logo uid: c4ce6f16dfb347b0ae0ac67f5881b243 id: 8 - position: [2104, 56] + position: [3181, 56] rotation: 0 layer: 0 visable: true @@ -80,7 +80,7 @@ objects: - name: Carbooon Fobar uid: 5ea269572751401da6d86519d3513b7d id: 9 - position: [2048, 3070] + position: [4087.8999, 3070] rotation: 0 layer: 1 visable: true @@ -93,7 +93,7 @@ objects: - name: Carbooon Fobar 2 uid: a36b71937ba349bd8e6414f75be9ee16 id: 10 - position: [0, 3070] + position: [-7.69999981, 3070] rotation: 0 layer: 0 visable: true @@ -106,7 +106,7 @@ objects: - name: Lights uid: 051b338a725a4076ad53ad8fa00c5f4e id: 12 - position: [-556, 951] + position: [-560, 1118] rotation: 0 layer: 0 visable: true @@ -115,7 +115,7 @@ objects: - name: Red uid: 6afde2dd47aa4557b6afb1a607c99dc8 id: 13 - position: [1113.06287, 1516.00391] + position: [841.838257, 558.36377] rotation: 0 layer: 2 visable: true @@ -133,7 +133,7 @@ objects: - name: Green uid: 0f950d76d24b4dc18f54cab2c3aaaf9a id: 14 - position: [553.380676, 855.128784] + position: [1518.33362, 1099.0614] rotation: 0 layer: 2 visable: true @@ -151,7 +151,7 @@ objects: - name: Blue uid: 09f722f51c7c4b0f98de3a0a16d127c4 id: 15 - position: [1405.5564, 700.86731] + position: [711.828064, 1414.57483] rotation: 0 layer: 2 visable: true @@ -210,6 +210,9 @@ objects: primary: true children: [] color_correction: - brightness: 2 - saturation: 2 - gamma: 0.610000014 \ No newline at end of file + brightness: 1 + saturation: 1 + gamma: 1 + bloom: true + intensity: 1.20000005 + threshold: 0.200000003 \ No newline at end of file diff --git a/src/assets/shaders/bloom.frag b/src/assets/shaders/bloom.frag new file mode 100644 index 0000000..94729de --- /dev/null +++ b/src/assets/shaders/bloom.frag @@ -0,0 +1,39 @@ +#version 330 core +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D uTex; +uniform vec2 uTexelSize; +uniform float uThreshold; +uniform float uIntensity; + +const float weights[5] = float[](0.204164, 0.304005, 0.093913, 0.010381, 0.000336); + +vec3 blur(vec2 uv, vec2 dir) { + vec3 sum = vec3(0.0); + for (int i = -4; i <= 4; ++i) { + int index = abs(i); + vec2 offset = dir * float(i); + vec3 col = texture(uTex, uv + offset).rgb; + + float brightness = dot(col, vec3(0.2126, 0.7152, 0.0722)); // luminance + float mask = smoothstep(uThreshold, uThreshold + 0.05, brightness); + + sum += col * mask * weights[index]; + } + return sum; +} + +void main() { + vec3 color = texture(uTex, vUV).rgb; + + // Blur only bright pixels (thresholded inside blur) + vec3 blurH = blur(vUV, vec2(uTexelSize.x, 0.0)); + vec3 blurV = blur(vUV, vec2(0.0, uTexelSize.y)); + vec3 bloom = (blurH + blurV) * 0.5 * uIntensity; + + // Final composition + vec3 finalColor = color + bloom; + + FragColor = vec4(finalColor, 1.0); +} diff --git a/src/assets/shaders/bloom.vert b/src/assets/shaders/bloom.vert new file mode 100644 index 0000000..a3e2e11 --- /dev/null +++ b/src/assets/shaders/bloom.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); +} diff --git a/src/assets/shaders/blur.frag b/src/assets/shaders/blur.frag new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/shaders/extract.frag b/src/assets/shaders/extract.frag new file mode 100644 index 0000000..fee11de --- /dev/null +++ b/src/assets/shaders/extract.frag @@ -0,0 +1,13 @@ +#version 330 core +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D uScene; +uniform float uThreshold; + +void main() { + vec3 color = texture(uScene, vUV).rgb; + float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722)); + float mask = smoothstep(uThreshold, uThreshold + 0.05, brightness); + FragColor = vec4(color * mask, 1.0); +} diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index a7ac16d..397b2c2 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -307,7 +307,12 @@ void ShowColorCorrectionWindow() changed |= ImGui::SliderFloat("Saturation", &cc->saturation, 0.0f, 2.0f, "%.2f"); changed |= ImGui::SliderFloat("Gamma", &cc->gamma, 0.1f, 4.0f, "%.2f"); - ImGui::Spacing(); + ImGui::SeparatorText("Bloom"); + + + changed |= ImGui::Checkbox("Enable Bloom", &cc->bloom); + changed |= ImGui::SliderFloat("Threshold", &cc->threshold, 0.0f, 2.0f, "%.2f"); + changed |= ImGui::SliderFloat("Intensity", &cc->intensity, 0.0f, 4.0f, "%.2f"); if (ImGui::Button("Reset to Default")) { @@ -318,6 +323,7 @@ void ShowColorCorrectionWindow() ImGui::End(); } + void Engine::Init() { @@ -354,7 +360,7 @@ void Engine::Init() Renderer::Init(); auto obj = std::make_shared("Hello, Create"); - + objects.push_back(obj); selected = obj; @@ -403,7 +409,6 @@ void Engine::Init() // objects.push_back(obj); // } //} - Logger::LogVerbose("Resverving Objects"); @@ -1059,7 +1064,7 @@ void Engine::Run() profiler.EndEngineSection(); // Display render target texture - GLuint texID = Renderer::GetRenderTexture(); + GLuint texID = Renderer::GetFinalTexture(); ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0)); ImGui::End(); @@ -1267,6 +1272,11 @@ void Engine::SaveScene(const std::string &path) out << YAML::Key << "brightness" << YAML::Value << Renderer::GetColorCorrection()->brightness; out << YAML::Key << "saturation" << YAML::Value << Renderer::GetColorCorrection()->saturation; out << YAML::Key << "gamma" << YAML::Value << Renderer::GetColorCorrection()->gamma; + + out << YAML::Key << "bloom" << YAML::Value << Renderer::GetColorCorrection()->bloom; + out << YAML::Key << "intensity" << YAML::Value << Renderer::GetColorCorrection()->intensity; + out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold; + out << YAML::EndMap; out << YAML::EndMap; @@ -1327,6 +1337,13 @@ void Engine::LoadScene(const std::string &path) cc->saturation = data["saturation"].as(); if (data["gamma"]) cc->gamma = data["gamma"].as(); + + if (data["bloom"]) + cc->bloom = data["bloom"].as(); + if (data["intensity"]) + cc->intensity = data["intensity"].as(); + if (data["threshold"]) + cc->threshold = data["threshold"].as(); } } @@ -1348,6 +1365,11 @@ void Engine::SaveState() out << YAML::Key << "brightness" << YAML::Value << Renderer::GetColorCorrection()->brightness; out << YAML::Key << "saturation" << YAML::Value << Renderer::GetColorCorrection()->saturation; out << YAML::Key << "gamma" << YAML::Value << Renderer::GetColorCorrection()->gamma; + + out << YAML::Key << "bloom" << YAML::Value << Renderer::GetColorCorrection()->bloom; + out << YAML::Key << "intensity" << YAML::Value << Renderer::GetColorCorrection()->intensity; + out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold; + out << YAML::EndMap; out << YAML::EndMap; @@ -1398,6 +1420,13 @@ void Engine::LoadState() cc->saturation = data["saturation"].as(); if (data["gamma"]) cc->gamma = data["gamma"].as(); + + if (data["bloom"]) + cc->bloom = data["bloom"].as(); + if (data["intensity"]) + cc->intensity = data["intensity"].as(); + if (data["threshold"]) + cc->threshold = data["threshold"].as(); } } diff --git a/src/src/Renderer.cpp b/src/src/Renderer.cpp index 2060e93..39868b4 100644 --- a/src/src/Renderer.cpp +++ b/src/src/Renderer.cpp @@ -17,6 +17,7 @@ static Shader spriteShader; static Shader unlitShader; +static Shader bloomShader; GLuint Renderer::fbo = 0; GLuint Renderer::textureColorBuffer = 0; @@ -37,16 +38,19 @@ GLuint Renderer::s_ClusterSSBO = 0; int Renderer::s_ClusterCols = 0; int Renderer::s_ClusterRows = 0; +GLuint Renderer::bloomFBO = 0; +GLuint Renderer::bloomTexture = 0; + static Shader tilemapShader; void Renderer::InitQuad() { float vertices[] = { - // pos // uv - 0.f, 0.f, 0.f, 0.f, - 1.f, 0.f, 1.f, 0.f, + // pos // uv + -1.f, -1.f, 0.f, 0.f, + 1.f, -1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, - 0.f, 1.f, 0.f, 1.f}; + -1.f, 1.f, 0.f, 1.f}; glGenVertexArrays(1, &quadVAO); glBindVertexArray(quadVAO); @@ -93,10 +97,31 @@ void Renderer::Init() // Load unlit shader unlitShader.LoadFromFile("src/assets/shaders/unlit.vert", "src/assets/shaders/unlit.frag"); + bloomShader.LoadFromFile("src/assets/shaders/bloom.vert", "src/assets/shaders/bloom.frag"); + SetColorCorrection(std::make_unique()); glGenBuffers(1, &s_ClusterSSBO); + 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); + 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, 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) unsigned char flatNormal[3] = {128, 128, 255}; glGenTextures(1, &defaultNormalMap); @@ -167,6 +192,10 @@ void Renderer::Resize(int w, int h) 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() @@ -189,6 +218,10 @@ void Renderer::Begin() void Renderer::End() { + + { + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -491,6 +524,52 @@ void Renderer::DrawGizmoCircle( glEnd(); } + + + + +GLuint Renderer::GetFinalTexture() +{ + PROFILE_SCOPE("Renderer::GetFinalTexture"); + + GLuint inputTexture = GetRenderTexture(); + + if (!s_ColorCorrection->bloom) + { + return inputTexture; + } + + // Bind persistent FBO + glBindFramebuffer(GL_FRAMEBUFFER, bloomFBO); + + // Setup and clear + 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); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, inputTexture); + + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return bloomTexture; +} + + + + + + + GLuint Renderer::GetRenderTexture() { return textureColorBuffer; diff --git a/src/src/Renderer.h b/src/src/Renderer.h index e0efe4c..85f221c 100644 --- a/src/src/Renderer.h +++ b/src/src/Renderer.h @@ -10,26 +10,35 @@ #include "utils/Shader.h" #include "utils/Profiler.h" -struct ColorCorrection { +struct ColorCorrection +{ float brightness = 1.0f; float saturation = 1.0f; float gamma = 1.0f; - void Upload(Shader& shader) const { + bool bloom = true; + float threshold = 0.2f; + float intensity = 1.2f; + + + void Upload(Shader &shader) const + { shader.SetFloat("uBrightness", brightness); shader.SetFloat("uSaturation", saturation); shader.SetFloat("uGamma", gamma); } }; -struct Light { +struct Light +{ glm::vec2 screenPos; glm::vec3 color; float intensity; float radius; }; -class Renderer { +class Renderer +{ public: static void Init(); static void Resize(int w, int h); @@ -55,6 +64,8 @@ public: static void SetColorCorrection(std::unique_ptr correction); static ColorCorrection *GetColorCorrection(); + static GLuint GetFinalTexture(); + // Clustered lighting static void UpdateClusterLights(); // Call once per frame after all lights added @@ -77,7 +88,8 @@ private: static constexpr int CLUSTER_SIZE = 16; static constexpr int MAX_LIGHTS_PER_CLUSTER = 32; - struct Cluster { + struct Cluster + { std::vector lightIndices; }; @@ -86,5 +98,6 @@ private: static int s_ClusterCols; static int s_ClusterRows; - + static GLuint bloomFBO; + static GLuint bloomTexture; };