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<ColorCorrection>());
 
     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;