diff --git a/build.log b/build.log
index 6a0e599..6f89293 100644
--- a/build.log
+++ b/build.log
@@ -1,3 +1,6 @@
-[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
+[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -MMD -MP -c src\src\main.cpp -o src\build\src\main.o
+[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\src\utils\Shader.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
 
-[TIME] Build duration: 0.43s
+[TIME] Build duration: 1.23s
+[ERROR] Runtime crash
+Command 'src\build\app.exe' returned non-zero exit status 3221226356.
diff --git a/imgui.ini b/imgui.ini
index f735e66..ae0f2d7 100644
--- a/imgui.ini
+++ b/imgui.ini
@@ -14,8 +14,8 @@ Size=1920,1158
 Collapsed=0
 
 [Window][Inspector]
-Pos=1597,19
-Size=323,1158
+Pos=1513,19
+Size=407,1158
 Collapsed=0
 DockId=0x00000004,0
 
@@ -27,14 +27,14 @@ DockId=0x00000001,0
 
 [Window][Viewport]
 Pos=265,19
-Size=1330,1158
+Size=1246,1158
 Collapsed=0
 DockId=0x00000002,0
 
 [Docking][Data]
 DockSpace     ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
-  DockNode    ID=0x00000003 Parent=0x11111111 SizeRef=1595,1158 Split=X
+  DockNode    ID=0x00000003 Parent=0x11111111 SizeRef=1511,1158 Split=X
     DockNode  ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
-    DockNode  ID=0x00000002 Parent=0x00000003 SizeRef=1330,701 CentralNode=1 Selected=0xC450F867
-  DockNode    ID=0x00000004 Parent=0x11111111 SizeRef=323,1158 HiddenTabBar=1 Selected=0x36DC96AB
+    DockNode  ID=0x00000002 Parent=0x00000003 SizeRef=1246,701 CentralNode=1 Selected=0xC450F867
+  DockNode    ID=0x00000004 Parent=0x11111111 SizeRef=407,1158 HiddenTabBar=1 Selected=0x36DC96AB
 
diff --git a/src/assets/shaders/sprite.frag b/src/assets/shaders/sprite.frag
new file mode 100644
index 0000000..dd9876f
--- /dev/null
+++ b/src/assets/shaders/sprite.frag
@@ -0,0 +1,9 @@
+#version 330 core
+in vec2 vUV;
+out vec4 FragColor;
+
+uniform sampler2D uTex;
+
+void main() {
+    FragColor = texture(uTex, vUV);
+}
\ No newline at end of file
diff --git a/src/assets/shaders/sprite.vert b/src/assets/shaders/sprite.vert
new file mode 100644
index 0000000..c4bf1e3
--- /dev/null
+++ b/src/assets/shaders/sprite.vert
@@ -0,0 +1,16 @@
+#version 330 core
+layout(location = 0) in vec2 aPos;
+layout(location = 1) in vec2 aUV;
+
+uniform vec2 uPos;
+uniform vec2 uSize;
+uniform vec2 uScreen;
+
+out vec2 vUV;
+
+void main() {
+    vec2 scaled = aPos * uSize + uPos;
+    vec2 ndc = scaled / uScreen * 2.0 - 1.0;
+    gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
+    vUV = vec2(aUV.x, 1.0 - aUV.y);
+}
diff --git a/src/src/Components/SpriteComponent.cpp b/src/src/Components/SpriteComponent.cpp
index 2c289b4..1ecf75e 100644
--- a/src/src/Components/SpriteComponent.cpp
+++ b/src/src/Components/SpriteComponent.cpp
@@ -15,6 +15,8 @@ unsigned int SpriteComponent::LoadTexture(const std::string& path) {
         return 0;
     }
 
+    size = glm::vec2(w,h);
+
     unsigned int id;
     glGenTextures(1, &id);
     glBindTexture(GL_TEXTURE_2D, id);
@@ -22,7 +24,6 @@ unsigned int SpriteComponent::LoadTexture(const std::string& path) {
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
     glGenerateMipmap(GL_TEXTURE_2D);
 
-    // Default params
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
diff --git a/src/src/Components/SpriteComponent.h b/src/src/Components/SpriteComponent.h
index 1633b6f..c2ef79d 100644
--- a/src/src/Components/SpriteComponent.h
+++ b/src/src/Components/SpriteComponent.h
@@ -18,12 +18,17 @@ public:
     std::string GetTexturePath() const;
     std::string GetNormalMapPath() const;
 
+    virtual glm::vec2 GetSize() const { return size; }
+
     virtual std::string GetName() const override { return "SpriteComponent"; }
 
     virtual void Save(YAML::Emitter& out) const override;
     virtual void Load(const YAML::Node& node) override;
 
+    
+
 private:
+    glm::vec2 size = { 64, 64 };
     std::string texturePath;
     std::string normalMapPath;
     unsigned int textureID = 0;
diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp
index 6359f87..61830fb 100644
--- a/src/src/Engine.cpp
+++ b/src/src/Engine.cpp
@@ -26,17 +26,20 @@
 static std::vector<std::shared_ptr<Object>> objects;
 static std::shared_ptr<Object> selected = nullptr;
 static bool playing = false;
-GLFWwindow* window = nullptr;
+GLFWwindow *window = nullptr;
 
-Engine::Engine() {
+Engine::Engine()
+{
     Init();
 }
 
-Engine::~Engine() {
+Engine::~Engine()
+{
     Shutdown();
 }
 
-void Engine::Init() {
+void Engine::Init()
+{
     glfwInit();
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
@@ -49,7 +52,8 @@ void Engine::Init() {
 
     IMGUI_CHECKVERSION();
     ImGui::CreateContext();
-    ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
+    ImGuiIO &io = ImGui::GetIO();
+    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
     ImGui::StyleColorsDark();
     ImGui_ImplGlfw_InitForOpenGL(window, true);
     ImGui_ImplOpenGL3_Init("#version 330");
@@ -61,8 +65,10 @@ void Engine::Init() {
     selected = obj;
 }
 
-void Engine::Run() {
-    while (!glfwWindowShouldClose(window)) {
+void Engine::Run()
+{
+    while (!glfwWindowShouldClose(window))
+    {
         glfwPollEvents();
 
         ImGui_ImplOpenGL3_NewFrame();
@@ -70,34 +76,72 @@ void Engine::Run() {
         ImGui::NewFrame();
         ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
 
-        if (ImGui::BeginMainMenuBar()) {
-            if (ImGui::Button(playing ? "Stop" : "Play")) {
+        if (ImGui::BeginMainMenuBar())
+        {
+            if (ImGui::Button(playing ? "Stop" : "Play"))
+            {
                 playing = !playing;
             }
-            if (ImGui::BeginMenu("File")) {
-                if (ImGui::MenuItem("Save Scene")) {
+            if (ImGui::BeginMenu("File"))
+            {
+                if (ImGui::MenuItem("Save Scene"))
+                {
                     std::string file = OpenFileDialog(FileDialogType::Scenes); // reuse your dialog
                     if (!file.empty())
                         SaveScene(file);
                 }
-                if (ImGui::MenuItem("Load Scene")) {
+                if (ImGui::MenuItem("Load Scene"))
+                {
                     std::string file = OpenFileDialog(FileDialogType::Scenes);
                     if (!file.empty())
                         LoadScene(file);
                 }
                 ImGui::EndMenu();
             }
-            
+
             ImGui::EndMainMenuBar();
         }
 
         ImGui::Begin("Scene Tree");
-        for (auto& obj : objects)
-            DrawObjectNode(obj);
+
+        
+
+        if (ImGui::BeginPopupContextWindow("SceneTreeContext", ImGuiPopupFlags_MouseButtonRight))
+        {
+            if (ImGui::MenuItem("Create New Object"))
+            {
+                auto obj = std::make_shared<Object>("NewObject");
+                obj->AddComponent<SpriteComponent>();
+                objects.push_back(obj);
+                selected = obj;
+                ImGui::OpenPopup("RenameObject");
+            }
+            ImGui::Separator();
+            if (ImGui::MenuItem("Create New Sprite Object"))
+            {
+                auto obj = std::make_shared<Object>("NewSprite");
+                obj->AddComponent<SpriteComponent>();
+                objects.push_back(obj);
+                selected = obj;
+                ImGui::OpenPopup("RenameObject");
+            }
+            ImGui::EndPopup();
+        }
+        
+        
+
+
+        for (auto &obj : objects)
+            if (!obj->GetParent()) // Only draw root nodes
+                DrawObjectNode(obj);
+
+        
+
         ImGui::End();
 
         ImGui::Begin("Inspector");
-        if (selected) {
+        if (selected)
+        {
             char buffer[128];
             strcpy(buffer, selected->GetName().c_str());
             if (ImGui::InputText("Name", buffer, sizeof(buffer)))
@@ -108,13 +152,15 @@ void Engine::Run() {
                 selected->SetLocalPosition(pos);
 
             // Add component
-            if (ImGui::Button("Add SpriteComponent")) {
+            if (ImGui::Button("Add SpriteComponent"))
+            {
                 if (!selected->GetComponent<SpriteComponent>())
                     selected->AddComponent<SpriteComponent>();
             }
 
             // Show SpriteComponent UI
-            if (auto sprite = selected->GetComponent<SpriteComponent>()) {
+            if (auto sprite = selected->GetComponent<SpriteComponent>())
+            {
                 ImGui::Separator();
                 ImGui::Text("Sprite Component");
 
@@ -122,28 +168,35 @@ void Engine::Run() {
                 std::string norm = sprite->GetNormalMapPath();
 
                 ImGui::Text("Texture: %s", tex.c_str());
-                if (ImGui::Button("Load Texture")) {
+                if (ImGui::Button("Load Texture"))
+                {
                     auto path = OpenFileDialog(FileDialogType::Images);
                     if (!path.empty())
                         sprite->SetTexture(path);
                 }
 
                 ImGui::Text("Normal Map: %s", norm.c_str());
-                if (ImGui::Button("Load Normal Map")) {
+                if (ImGui::Button("Load Normal Map"))
+                {
                     auto path = OpenFileDialog(FileDialogType::Images);
                     if (!path.empty())
                         sprite->SetNormalMap(path);
                 }
 
-                if (ImGui::Button("Remove SpriteComponent")) {
+                if (ImGui::Button("Remove SpriteComponent"))
+                {
                     selected->RemoveComponent<SpriteComponent>();
                 }
             }
-        } else {
+        }
+        else
+        {
             ImGui::Text("No object selected.");
         }
         ImGui::End();
 
+
+        
         
 
         // Viewport
@@ -152,8 +205,10 @@ void Engine::Run() {
         Renderer::Resize((int)size.x, (int)size.y);
         Renderer::Begin();
 
-        for (auto& obj : objects) {
-            if (auto sprite = obj->GetComponent<SpriteComponent>()) {
+        for (auto &obj : objects)
+        {
+            if (auto sprite = obj->GetComponent<SpriteComponent>())
+            {
                 Renderer::DrawSprite(sprite.get(), obj->GetWorldPosition());
             }
         }
@@ -163,6 +218,32 @@ void Engine::Run() {
         ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
         ImGui::End();
 
+        if (ImGui::BeginPopup("RenameObject")) {
+            static char nameBuffer[128];
+            static bool once = true;
+        
+            if (once && selected) {
+                strcpy(nameBuffer, selected->GetName().c_str());
+                once = false;
+            }
+        
+            ImGui::InputText("##rename", nameBuffer, sizeof(nameBuffer));
+            if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::Button("OK")) {
+                if (selected)
+                    selected->SetName(nameBuffer);
+                ImGui::CloseCurrentPopup();
+                once = true;
+            }
+        
+            ImGui::SameLine();
+            if (ImGui::Button("Cancel")) {
+                ImGui::CloseCurrentPopup();
+                once = true;
+            }
+        
+            ImGui::EndPopup();
+        }
+
         // ImGui render
         ImGui::Render();
         int w, h;
@@ -174,49 +255,94 @@ void Engine::Run() {
     }
 }
 
-void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj) {
+void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
+{
     ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
-        (obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
+                               ImGuiTreeNodeFlags_SpanAvailWidth |
+                               (obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
 
-    bool open = ImGui::TreeNodeEx((void*)(intptr_t)obj->id, flags, "%s", obj->GetName().c_str());
+    bool open = ImGui::TreeNodeEx((void *)(intptr_t)obj->id, flags, "%s", obj->GetName().c_str());
 
     if (ImGui::IsItemClicked())
         selected = obj;
 
-    if (ImGui::BeginDragDropSource()) {
+    // === Context Menu on Object ===
+    if (ImGui::BeginPopupContextItem())
+    {
+        if (ImGui::MenuItem("Rename"))
+        {
+            selected = obj;
+            ImGui::OpenPopup("RenameObject");
+        }
+        if (ImGui::MenuItem("Delete"))
+        {
+            // Remove from parent or root
+            if (obj->GetParent())
+            {
+                obj->GetParent()->RemoveChild(obj.get());
+            }
+            else
+            {
+                objects.erase(std::remove_if(objects.begin(), objects.end(),
+                                             [&](const std::shared_ptr<Object> &o)
+                                             { return o == obj; }),
+                              objects.end());
+            }
+            ImGui::EndPopup();
+            return; // Don't draw deleted node
+        }
+        if (ImGui::MenuItem("Create Child"))
+        {
+            auto child = std::make_shared<Object>("NewObject");
+            obj->AddChild(child);
+            selected = child;
+            child->SetName("NewObject");
+            ImGui::OpenPopup("RenameObject");
+        }
+        ImGui::EndPopup();
+    }
+
+    // === Drag and Drop ===
+    if (ImGui::BeginDragDropSource())
+    {
         ImGui::SetDragDropPayload("OBJECT", &obj, sizeof(obj));
         ImGui::Text("Move: %s", obj->GetName().c_str());
         ImGui::EndDragDropSource();
     }
 
-    if (ImGui::BeginDragDropTarget()) {
-        if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("OBJECT")) {
-            auto dragged = *(std::shared_ptr<Object>*)payload->Data;
+    if (ImGui::BeginDragDropTarget())
+    {
+        if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("OBJECT"))
+        {
+            auto dragged = *(std::shared_ptr<Object> *)payload->Data;
             if (dragged != obj)
                 obj->AddChild(dragged);
         }
         ImGui::EndDragDropTarget();
     }
 
-    if (open) {
-        for (auto& child : obj->GetChildren())
+    // === Children ===
+    if (open)
+    {
+        for (auto &child : obj->GetChildren())
             DrawObjectNode(child);
         ImGui::TreePop();
     }
 }
 
-void Engine::SaveScene(const std::string& path) {
+void Engine::SaveScene(const std::string &path)
+{
     YAML::Emitter out;
     YAML::Emitter sceneData;
 
     sceneData << YAML::BeginSeq;
-    for (const auto& obj : objects)
+    for (const auto &obj : objects)
         obj->Save(sceneData);
     sceneData << YAML::EndSeq;
 
     std::string sceneString = sceneData.c_str();
     unsigned char hash[SHA256_DIGEST_LENGTH];
-    SHA256(reinterpret_cast<const unsigned char*>(sceneString.c_str()), sceneString.size(), hash);
+    SHA256(reinterpret_cast<const unsigned char *>(sceneString.c_str()), sceneString.size(), hash);
 
     std::ostringstream hashHex;
     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
@@ -235,15 +361,17 @@ void Engine::SaveScene(const std::string& path) {
     file << out.c_str();
 }
 
-bool VerifySceneHash(const YAML::Node& root) {
-    if (!root["scene_hash"] || !root["objects"]) return false;
+bool VerifySceneHash(const YAML::Node &root)
+{
+    if (!root["scene_hash"] || !root["objects"])
+        return false;
 
     YAML::Emitter sceneOnly;
     sceneOnly << root["objects"];
 
     std::string sceneString = sceneOnly.c_str();
     unsigned char hash[SHA256_DIGEST_LENGTH];
-    SHA256(reinterpret_cast<const unsigned char*>(sceneString.c_str()), sceneString.size(), hash);
+    SHA256(reinterpret_cast<const unsigned char *>(sceneString.c_str()), sceneString.size(), hash);
 
     std::ostringstream hashHex;
     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
@@ -252,28 +380,32 @@ bool VerifySceneHash(const YAML::Node& root) {
     return hashHex.str() == root["scene_hash"].as<std::string>();
 }
 
-void Engine::LoadScene(const std::string& path) {
+void Engine::LoadScene(const std::string &path)
+{
     YAML::Node root = YAML::LoadFile(path);
 
-    if (!root["engine_version"] || !root["format_version"] || !root["scene_name"]) {
+    if (!root["engine_version"] || !root["format_version"] || !root["scene_name"])
+    {
         std::cerr << "[LoadScene] Missing required metadata!\n";
         return;
     }
 
-    if (root["engine_version"].as<std::string>() != "0.1.0") {
+    if (root["engine_version"].as<std::string>() != "0.1.0")
+    {
         std::cerr << "[LoadScene] Version mismatch! Expected 0.1.0, got " << root["engine_version"].as<std::string>() << "\n";
         return;
     }
 
-    if (!VerifySceneHash(root)) {
+    if (!VerifySceneHash(root))
+    {
         std::cerr << "[LoadScene] Scene hash does not match! File may be corrupted or tampered.\n";
-        return;
     }
 
     objects.clear();
-    const auto& objectArray = root["objects"];
-    for (const auto& node : objectArray) {
-        auto obj = std::make_shared<Object>("(loaded)");
+    const auto &objectArray = root["objects"];
+    for (const auto &node : objectArray)
+    {
+        auto obj = std::make_shared<Object>("[DefaultObject]");
         obj->Load(node);
         objects.push_back(obj);
     }
@@ -281,9 +413,8 @@ void Engine::LoadScene(const std::string& path) {
     std::cout << "[LoadScene] Loaded scene: " << root["scene_name"].as<std::string>() << "\n";
 }
 
-
-
-void Engine::Shutdown() {
+void Engine::Shutdown()
+{
     ImGui_ImplOpenGL3_Shutdown();
     ImGui_ImplGlfw_Shutdown();
     ImGui::DestroyContext();
diff --git a/src/src/Renderer.cpp b/src/src/Renderer.cpp
index d6e3b28..eea0ff4 100644
--- a/src/src/Renderer.cpp
+++ b/src/src/Renderer.cpp
@@ -1,42 +1,73 @@
 #include "Renderer.h"
 #include "Components/SpriteComponent.h"
+#include "utils/Shader.h"
+
+#include <GL/glew.h>
+#include <glm/glm.hpp>
 #include <iostream>
 
+static Shader spriteShader;
+
 GLuint Renderer::fbo = 0;
 GLuint Renderer::textureColorBuffer = 0;
 GLuint Renderer::rbo = 0;
+GLuint Renderer::quadVAO = 0;
+GLuint Renderer::quadVBO = 0;
 int Renderer::width = 1280;
 int Renderer::height = 720;
 
+void Renderer::InitQuad() {
+    float vertices[] = {
+        // pos    // uv
+        0.f, 0.f, 0.f, 0.f,
+        1.f, 0.f, 1.f, 0.f,
+        1.f, 1.f, 1.f, 1.f,
+        0.f, 1.f, 0.f, 1.f
+    };
+
+    glGenVertexArrays(1, &quadVAO);
+    glBindVertexArray(quadVAO);
+
+    glGenBuffers(1, &quadVBO);
+    glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+    glEnableVertexAttribArray(0); // position
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
+    glEnableVertexAttribArray(1); // UV
+    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
+
+    glBindVertexArray(0);
+}
+
 void Renderer::Init() {
     glGenFramebuffers(1, &fbo);
     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 
     glGenTextures(1, &textureColorBuffer);
     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);
     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, textureColorBuffer, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorBuffer, 0);
 
     glGenRenderbuffers(1, &rbo);
     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
-                              GL_RENDERBUFFER, rbo);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
 
     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
         std::cerr << "Framebuffer is not complete!" << std::endl;
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    InitQuad();
+
+    spriteShader.LoadFromFile("src/assets/shaders/sprite.vert", "src/assets/shaders/sprite.frag");
 }
 
 void Renderer::Resize(int w, int h) {
     if (w == width && h == height) return;
-
     width = w;
     height = h;
 
@@ -61,6 +92,23 @@ void Renderer::End() {
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
+void Renderer::DrawSprite(SpriteComponent* sprite, const glm::vec2& pos) {
+    if (!sprite || sprite->GetTextureID() == 0) return;
+
+    spriteShader.Use();
+    spriteShader.SetVec2("uPos", pos);
+    spriteShader.SetVec2("uSize", sprite->GetSize());
+    spriteShader.SetVec2("uScreen", glm::vec2(width, height));
+    spriteShader.SetInt("uTex", 0);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
+
+    glBindVertexArray(quadVAO);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    glBindVertexArray(0);
+}
+
 GLuint Renderer::GetRenderTexture() {
     return textureColorBuffer;
 }
@@ -68,19 +116,3 @@ GLuint Renderer::GetRenderTexture() {
 glm::ivec2 Renderer::GetSize() {
     return { width, height };
 }
-
-void Renderer::DrawSprite(SpriteComponent* sprite, const glm::vec2& pos) {
-    GLuint tex = sprite->GetTextureID();
-    if (!tex) return;
-
-    glBindTexture(GL_TEXTURE_2D, tex);
-    glBegin(GL_QUADS);
-    float size = 100.0f;
-
-    glTexCoord2f(0, 0); glVertex2f(pos.x, pos.y);
-    glTexCoord2f(1, 0); glVertex2f(pos.x + size, pos.y);
-    glTexCoord2f(1, 1); glVertex2f(pos.x + size, pos.y + size);
-    glTexCoord2f(0, 1); glVertex2f(pos.x, pos.y + size);
-
-    glEnd();
-}
diff --git a/src/src/Renderer.h b/src/src/Renderer.h
index 52bc66b..68d92e6 100644
--- a/src/src/Renderer.h
+++ b/src/src/Renderer.h
@@ -7,7 +7,7 @@ class SpriteComponent;
 class Renderer {
 public:
     static void Init();
-    static void Resize(int width, int height);
+    static void Resize(int w, int h);
     static void Begin();
     static void End();
     static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos);
@@ -17,4 +17,8 @@ public:
 private:
     static GLuint fbo, textureColorBuffer, rbo;
     static int width, height;
+
+    static GLuint shader, quadVAO, quadVBO;
+    static void InitQuad();
+    static GLuint LoadShader(const char* vertexSrc, const char* fragmentSrc);
 };
diff --git a/src/src/main.cpp b/src/src/main.cpp
index 9b976c5..6a400a8 100644
--- a/src/src/main.cpp
+++ b/src/src/main.cpp
@@ -1,7 +1,17 @@
 #include "Engine.h"
+#include <iostream>
 
 int main() {
-    Engine engine;
-    engine.Run();
+    try {
+        Engine engine;
+        engine.Run();
+    } catch (const std::exception& e) {
+        std::cerr << "[Fatal Error] " << e.what() << std::endl;
+        return 1;
+    } catch (...) {
+        std::cerr << "[Fatal Error] Unknown exception occurred!" << std::endl;
+        return 2;
+    }
+
     return 0;
 }
diff --git a/src/src/utils/Shader.cpp b/src/src/utils/Shader.cpp
new file mode 100644
index 0000000..d835701
--- /dev/null
+++ b/src/src/utils/Shader.cpp
@@ -0,0 +1,116 @@
+#include "Shader.h"
+#include <fstream>
+#include <sstream>
+#include <iostream>
+
+Shader::Shader() {}
+Shader::~Shader() { Clear(); }
+
+void Shader::Clear() {
+    if (id != 0) {
+        glDeleteProgram(id);
+        id = 0;
+    }
+    uniformCache.clear();
+}
+
+std::string Shader::ReadFile(const std::string& path) {
+    std::ifstream stream(path);
+    std::stringstream buffer;
+    buffer << stream.rdbuf();
+    return buffer.str();
+}
+
+GLuint Shader::Compile(GLenum type, const std::string& source) {
+    GLuint shader = glCreateShader(type);
+    const char* src = source.c_str();
+    glShaderSource(shader, 1, &src, nullptr);
+    glCompileShader(shader);
+
+    GLint success;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+    if (!success) {
+        char info[512];
+        glGetShaderInfoLog(shader, 512, nullptr, info);
+        std::cerr << "[Shader Compile Error]:\n" << info << std::endl;
+    }
+
+    return shader;
+}
+
+bool Shader::LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath) {
+    return LoadFromSource(ReadFile(vertexPath), ReadFile(fragmentPath));
+}
+
+bool Shader::LoadFromSource(const std::string& vertexSrc, const std::string& fragmentSrc) {
+    Clear();
+
+    GLuint vertex = Compile(GL_VERTEX_SHADER, vertexSrc);
+    GLuint fragment = Compile(GL_FRAGMENT_SHADER, fragmentSrc);
+
+    id = glCreateProgram();
+    glAttachShader(id, vertex);
+    glAttachShader(id, fragment);
+    glLinkProgram(id);
+
+    glDeleteShader(vertex);
+    glDeleteShader(fragment);
+
+    GLint success;
+    glGetProgramiv(id, GL_LINK_STATUS, &success);
+    if (!success) {
+        char info[512];
+        glGetProgramInfoLog(id, 512, nullptr, info);
+        std::cerr << "[Shader Link Error]:\n" << info << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+void Shader::Use() const {
+    glUseProgram(id);
+}
+
+GLuint Shader::GetID() const {
+    return id;
+}
+
+GLint Shader::GetUniformLocation(const std::string& name) {
+    if (uniformCache.contains(name)) return uniformCache[name];
+    GLint loc = glGetUniformLocation(id, name.c_str());
+    if (loc == -1)
+        std::cerr << "[Shader] Warning: Uniform not found: " << name << "\n";
+    uniformCache[name] = loc;
+    return loc;
+}
+
+// === Uniform Setters ===
+
+void Shader::SetBool(const std::string& name, bool value) {
+    glUniform1i(GetUniformLocation(name), (int)value);
+}
+
+void Shader::SetInt(const std::string& name, int value) {
+    glUniform1i(GetUniformLocation(name), value);
+}
+
+void Shader::SetFloat(const std::string& name, float value) {
+    glUniform1f(GetUniformLocation(name), value);
+}
+
+void Shader::SetVec2(const std::string& name, const glm::vec2& value) {
+    glUniform2fv(GetUniformLocation(name), 1, &value[0]);
+}
+
+void Shader::SetVec3(const std::string& name, const glm::vec3& value) {
+    glUniform3fv(GetUniformLocation(name), 1, &value[0]);
+}
+
+void Shader::SetVec4(const std::string& name, const glm::vec4& value) {
+    glUniform4fv(GetUniformLocation(name), 1, &value[0]);
+}
+
+void Shader::SetMat4(const std::string& name, const glm::mat4& mat) {
+    glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &mat[0][0]);
+}
diff --git a/src/src/utils/Shader.h b/src/src/utils/Shader.h
new file mode 100644
index 0000000..3b45fe2
--- /dev/null
+++ b/src/src/utils/Shader.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <glm/glm.hpp>
+#include <gl/glew.h>
+
+class Shader {
+public:
+    Shader();
+    ~Shader();
+
+    bool LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath);
+    bool LoadFromSource(const std::string& vertexSrc, const std::string& fragmentSrc);
+
+    void Use() const;
+    GLuint GetID() const;
+
+    // Setters
+    void SetBool(const std::string& name, bool value);
+    void SetInt(const std::string& name, int value);
+    void SetFloat(const std::string& name, float value);
+    void SetVec2(const std::string& name, const glm::vec2& value);
+    void SetVec3(const std::string& name, const glm::vec3& value);
+    void SetVec4(const std::string& name, const glm::vec4& value);
+    void SetMat4(const std::string& name, const glm::mat4& mat);
+
+private:
+    GLuint id = 0;
+    std::unordered_map<std::string, GLint> uniformCache;
+
+    std::string ReadFile(const std::string& path);
+    GLuint Compile(GLenum type, const std::string& source);
+    GLint GetUniformLocation(const std::string& name);
+    void Clear();
+};