From f7e08825976c63af7437d135701fd5ae5cf7b143 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Wed, 21 May 2025 22:05:10 -0500 Subject: [PATCH] Improves renderer and adds shader support Adds shader class to core and modifies the renderer to use it, while also adding profiling macros and fixing resize issues. The changes ensure the render target is resized only when the requested size is different from the current size and also clears the screen to a dark gray color. --- CMakeLists.txt | 1 + src/core/renderer/Renderer.cpp | 246 ++++++++++++++++------------- src/core/renderer/Renderer.h | 3 +- src/core/systems/Shader.h | 2 +- src/editor/Editor.cpp | 2 +- src/editor/Windows/FileBrowser.cpp | 9 +- 6 files changed, 149 insertions(+), 114 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d627f2..eb023da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ add_library(Core STATIC src/core/systems/Asset.h src/core/systems/assets/Texture2D.cpp src/core/systems/assets/Texture2D.h + src/core/systems/Shader.cpp ) target_include_directories(Core PUBLIC src/core) diff --git a/src/core/renderer/Renderer.cpp b/src/core/renderer/Renderer.cpp index f5c4434..683c2b7 100644 --- a/src/core/renderer/Renderer.cpp +++ b/src/core/renderer/Renderer.cpp @@ -3,41 +3,59 @@ #include #include -namespace OX { +namespace OX +{ + // ——— Camera2D implementation (unchanged) ——— + Camera2D::Camera2D(float left, float right, float bottom, float top) + : _left(left), _right(right), _bottom(bottom), _top(top) + { + Recalculate(); + } -// ——— Camera2D implementation (unchanged) ——— -Camera2D::Camera2D(float left, float right, float bottom, float top) - : _left(left), _right(right), _bottom(bottom), _top(top) -{ Recalculate(); } + void Camera2D::SetPosition(const glm::vec2 &pos) + { + _position = pos; + Recalculate(); + } -void Camera2D::SetPosition(const glm::vec2& pos) { _position = pos; Recalculate(); } -void Camera2D::SetZoom(float z) { _zoom = z; Recalculate(); } + void Camera2D::SetZoom(float z) + { + _zoom = z; + Recalculate(); + } -void Camera2D::Recalculate() { - float halfW = (_right - _left) * 0.5f / _zoom; - float halfH = (_top - _bottom) * 0.5f / _zoom; - glm::mat4 proj = glm::ortho(-halfW, halfW, -halfH, halfH, -1.0f, 1.0f); - glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-_position, 0.0f)); - _viewProj = proj * view; -} + void Camera2D::Recalculate() + { + float halfW = (_right - _left) * 0.5f / _zoom; + float halfH = (_top - _bottom) * 0.5f / _zoom; + glm::mat4 proj = glm::ortho(-halfW, halfW, -halfH, halfH, -1.0f, 1.0f); + glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-_position, 0.0f)); + _viewProj = proj * view; + } -const glm::mat4& Camera2D::GetViewProjection() const { return _viewProj; } + const glm::mat4 &Camera2D::GetViewProjection() const { return _viewProj; } -// ——— Renderer ——— -Renderer::~Renderer() { - if (m_quadVAO) glDeleteVertexArrays(1, &m_quadVAO); - if (m_quadVBO) glDeleteBuffers(1, &m_quadVBO); - if (m_fbo) glDeleteFramebuffers(1, &m_fbo); - if (m_colorTex) glDeleteTextures(1, &m_colorTex); - if (m_depthRBO) glDeleteRenderbuffers(1, &m_depthRBO); -} + // ——— Renderer ——— + Renderer::~Renderer() + { + if (m_quadVAO) + glDeleteVertexArrays(1, &m_quadVAO); + if (m_quadVBO) + glDeleteBuffers(1, &m_quadVBO); + if (m_fbo) + glDeleteFramebuffers(1, &m_fbo); + if (m_colorTex) glDeleteTextures(1, &m_colorTex); + if (m_depthRBO) + glDeleteRenderbuffers(1, &m_depthRBO); + } -void Renderer::Init(int targetWidth, int targetHeight) { - // create offscreen FBO & attachments - CreateFramebuffer(targetWidth, targetHeight); + void Renderer::Init(int targetWidth, int targetHeight) + { + // create offscreen FBO & attachments + CreateFramebuffer(targetWidth, targetHeight); - // compile our sprite shader - static const char* vs = R"GLSL( + // compile our sprite shader + static const char *vs = R"GLSL( #version 330 core layout(location = 0) in vec2 aPos; layout(location = 1) in vec2 aUV; @@ -51,7 +69,7 @@ void Renderer::Init(int targetWidth, int targetHeight) { gl_Position = u_ViewProj * vec4(pos,0,1); } )GLSL"; - static const char* fs = R"GLSL( + static const char *fs = R"GLSL( #version 330 core in vec2 vUV; out vec4 FragColor; @@ -61,102 +79,116 @@ void Renderer::Init(int targetWidth, int targetHeight) { } )GLSL"; - m_shader.LoadFromSource(vs, fs); + m_shader.LoadFromSource(vs, fs); - CreateQuad(); -} + CreateQuad(); + } -void Renderer::CreateFramebuffer(int width, int height) { - // cleanup old - if (m_fbo) glDeleteFramebuffers(1, &m_fbo); - if (m_colorTex) glDeleteTextures(1, &m_colorTex); - if (m_depthRBO) glDeleteRenderbuffers(1, &m_depthRBO); + void Renderer::CreateFramebuffer(int width, int height) + { + size = {width, height}; - // color texture - glGenTextures(1, &m_colorTex); - glBindTexture(GL_TEXTURE_2D, m_colorTex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 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); + // cleanup old + if (m_fbo) + glDeleteFramebuffers(1, &m_fbo); + if (m_colorTex) glDeleteTextures(1, &m_colorTex); + if (m_depthRBO) + glDeleteRenderbuffers(1, &m_depthRBO); - // depth renderbuffer - glGenRenderbuffers(1, &m_depthRBO); - glBindRenderbuffer(GL_RENDERBUFFER, m_depthRBO); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + // color texture + glGenTextures(1, &m_colorTex); + glBindTexture(GL_TEXTURE_2D, m_colorTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 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); - // framebuffer - glGenFramebuffers(1, &m_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, m_colorTex, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, m_depthRBO); + // depth renderbuffer + glGenRenderbuffers(1, &m_depthRBO); + glBindRenderbuffer(GL_RENDERBUFFER, m_depthRBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cerr << "[Renderer] Framebuffer not complete!\n"; + // framebuffer + glGenFramebuffers(1, &m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, m_colorTex, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, m_depthRBO); - // unbind - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + std::cerr << "[Renderer] Framebuffer not complete!\n"; -void Renderer::ResizeTarget(int width, int height) { - CreateFramebuffer(width, height); -} + // unbind + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } -void Renderer::BeginScene(const Camera2D& camera) { - // bind offscreen - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); - // clear - glViewport(0, 0, /*width*/0, /*height*/0); // you may want to track size - glClearColor(0,0,0,1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + void Renderer::ResizeTarget(int width, int height) + { + OX_PROFILE_FUNCTION(); + if (size == Vec2i{width, height}) { + return; + } + CreateFramebuffer(width, height); + } - // setup shader & camera - m_viewProj = camera.GetViewProjection(); - m_shader.Use(); - m_shader.SetMat4("u_ViewProj", m_viewProj); - m_shader.SetInt("u_Texture", 0); -} + void Renderer::BeginScene(const Camera2D &camera) + { + OX_PROFILE_FUNCTION(); + // bind offscreen + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + // clear + glViewport(0, 0, size.x, size.y); + glClearColor(0.1f, 0.1f, 0.1f, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -void Renderer::DrawSprite(const Sprite& s) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, s.textureID); + // setup shader & camera + m_viewProj = camera.GetViewProjection(); + m_shader.Use(); + m_shader.SetMat4("u_ViewProj", m_viewProj); + m_shader.SetInt("u_Texture", 0); + } - m_shader.SetVec2("u_Offset", s.position); - m_shader.SetVec2("u_Scale", s.size); + void Renderer::DrawSprite(const Sprite &s) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, s.textureID); - glBindVertexArray(m_quadVAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); -} + m_shader.SetVec2("u_Offset", s.position); + m_shader.SetVec2("u_Scale", s.size); -void Renderer::EndScene() { - // unbind FBO → subsequent draws go to default framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} + glBindVertexArray(m_quadVAO); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); + } -void Renderer::CreateQuad() { - float verts[] = { - -0.5f, -0.5f, 0,0, - 0.5f, -0.5f, 1,0, - 0.5f, 0.5f, 1,1, - -0.5f, 0.5f, 0,1 - }; - unsigned int idx[] = {0,1,2, 2,3,0}; + void Renderer::EndScene() + { + // unbind FBO → subsequent draws go to default framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } - glGenVertexArrays(1, &m_quadVAO); - glGenBuffers(1, &m_quadVBO); + void Renderer::CreateQuad() + { + float verts[] = { + -0.5f, -0.5f, 0, 0, + 0.5f, -0.5f, 1, 0, + 0.5f, 0.5f, 1, 1, + -0.5f, 0.5f, 0, 1 + }; + unsigned int idx[] = {0, 1, 2, 2, 3, 0}; - glBindVertexArray(m_quadVAO); - glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); + glGenVertexArrays(1, &m_quadVAO); + glGenBuffers(1, &m_quadVBO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,4*sizeof(float),(void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,4*sizeof(float),(void*)(2*sizeof(float))); + glBindVertexArray(m_quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); - glBindVertexArray(0); -} + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2,GL_FLOAT,GL_FALSE, 4 * sizeof(float), (void *) 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2,GL_FLOAT,GL_FALSE, 4 * sizeof(float), (void *) (2 * sizeof(float))); + glBindVertexArray(0); + } } // namespace OX diff --git a/src/core/renderer/Renderer.h b/src/core/renderer/Renderer.h index 37beb91..44ceaf0 100644 --- a/src/core/renderer/Renderer.h +++ b/src/core/renderer/Renderer.h @@ -4,7 +4,7 @@ #include "glm/glm.hpp" #include "systems/Shader.h" #include - +#include "types/vec2.h" namespace OX { struct Sprite { @@ -54,6 +54,7 @@ namespace OX { private: // offscreen + Vec2i size; GLuint m_fbo = 0; GLuint m_colorTex = 0; GLuint m_depthRBO = 0; diff --git a/src/core/systems/Shader.h b/src/core/systems/Shader.h index 9b26ba5..e20fc7c 100644 --- a/src/core/systems/Shader.h +++ b/src/core/systems/Shader.h @@ -24,7 +24,7 @@ namespace OX void Use() const; - void CheckHotReload(); // 🔥 + void CheckHotReload(); GLuint GetID() const { return m_programID; } diff --git a/src/editor/Editor.cpp b/src/editor/Editor.cpp index 21c5fdd..02d7768 100644 --- a/src/editor/Editor.cpp +++ b/src/editor/Editor.cpp @@ -146,7 +146,7 @@ namespace OX // --- Render ImGui onto FBO 0 --- { - OX_PROFILE_LABEL("VSYNC Wait"); + ImGui::EndFrame(); ImGui::Render(); diff --git a/src/editor/Windows/FileBrowser.cpp b/src/editor/Windows/FileBrowser.cpp index 38540a6..9a89170 100644 --- a/src/editor/Windows/FileBrowser.cpp +++ b/src/editor/Windows/FileBrowser.cpp @@ -1,6 +1,7 @@ // File: src/FileBrowser.cpp #include "FileBrowser.h" #include +#include "systems/Profiler.h" namespace OX { @@ -13,6 +14,7 @@ namespace OX void FileBrowser::Draw(const char *title) { + OX_PROFILE_FUNCTION(); ImGui::Begin(title); // --- toolbar now contains back button, inline path, filter & view toggle all on one row --- @@ -86,6 +88,7 @@ namespace OX // ——— Polished grid view ——— void FileBrowser::DrawGridView(const std::shared_ptr &node) { + OX_PROFILE_FUNCTION(); const float cellW = _cfg.thumbnailSize + _cfg.padding * 2; ImVec2 avail = ImGui::GetContentRegionAvail(); int cols = std::max(1, int(avail.x / cellW)); @@ -93,13 +96,11 @@ namespace OX ImGui::BeginChild("GridRegion", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding); ImGui::Columns(cols, nullptr, false); - std::vector > children; - - { + std::vector > children; { std::lock_guard lock(AssetManager::s_TreeMutex); // assume you add this mutex children = node->children; } - for (auto& c : children) { + for (auto &c: children) { if (!c) return; if (!_filter.empty() && !PassesFilter(c->name)) continue;