From 6e28d329c926dbef3c02c53a7493810b56c5610c Mon Sep 17 00:00:00 2001 From: jyxiong Date: Wed, 7 Jan 2026 17:42:28 +0800 Subject: [PATCH] refactor: move pass to engine --- example/damaged_helmet/main.cpp | 28 +--------- example/damaged_helmet/renderer.cpp | 56 ------------------- source/paimon/app/application.cpp | 10 +++- source/paimon/app/application.h | 31 ++++++---- source/paimon/app/imgui/imgui_layer.cpp | 4 +- source/paimon/app/imgui/imgui_layer.h | 2 +- source/paimon/app/panel/viewport_panel.cpp | 55 ++++++++++-------- .../rendering/render_pass}/color_pass.cpp | 2 +- .../rendering/render_pass}/color_pass.h | 2 +- .../rendering/render_pass}/final_pass.cpp | 2 +- .../rendering/render_pass}/final_pass.h | 0 source/paimon/rendering/renderer.cpp | 41 ++++++++++++++ .../paimon/rendering}/renderer.h | 9 ++- 13 files changed, 116 insertions(+), 126 deletions(-) delete mode 100644 example/damaged_helmet/renderer.cpp rename {example/damaged_helmet => source/paimon/rendering/render_pass}/color_pass.cpp (99%) rename {example/damaged_helmet => source/paimon/rendering/render_pass}/color_pass.h (100%) rename {example/damaged_helmet => source/paimon/rendering/render_pass}/final_pass.cpp (97%) rename {example/damaged_helmet => source/paimon/rendering/render_pass}/final_pass.h (100%) create mode 100644 source/paimon/rendering/renderer.cpp rename {example/damaged_helmet => source/paimon/rendering}/renderer.h (67%) diff --git a/example/damaged_helmet/main.cpp b/example/damaged_helmet/main.cpp index d269b28..7e1a59d 100644 --- a/example/damaged_helmet/main.cpp +++ b/example/damaged_helmet/main.cpp @@ -1,38 +1,12 @@ -#include - -#include -#include -#include -#include -#include - #include "paimon/app/application.h" -#include "paimon/app/panel/editor_layer.h" -#include "paimon/app/panel/interaction_layer.h" #include "paimon/core/log_system.h" -#include "renderer.h" - using namespace paimon; -class HelmetApp : public Application { -public: - HelmetApp() : Application() { - // Setup editor layer first - auto* editorLayer = pushLayer(std::make_unique()); - - // Setup interaction layer for camera control - auto* interactionLayer = pushLayer(std::make_unique()); - - // Setup renderer with the scene and viewport - auto *renderer = pushLayer(std::make_unique()); - } -}; - int main() { LogSystem::init(); - HelmetApp app; + Application app; app.run(); return 0; diff --git a/example/damaged_helmet/renderer.cpp b/example/damaged_helmet/renderer.cpp deleted file mode 100644 index ab27c16..0000000 --- a/example/damaged_helmet/renderer.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "renderer.h" - -#include - -#include "paimon/app/application.h" -#include "paimon/app/event/application_event.h" - -using namespace paimon; - -Renderer::Renderer() - : Layer("Renderer"), - m_renderContext(std::make_unique()), - m_color_pass(*m_renderContext), m_final_pass(*m_renderContext) {} - -void Renderer::onAttach() { - // Initialization if needed -} - -void Renderer::onUpdate() { - auto& scene = Application::getInstance().getScene(); - - // First Pass: Render to FBO - m_color_pass.draw(*m_renderContext, m_resolution, scene); - - // Second Pass: Render FBO texture to screen (optional, for debugging) - // m_final_pass.draw(*m_renderContext, *m_color_pass.getColorTexture(), m_resolution); -} - -void Renderer::onEvent(Event &event) { - EventDispatcher dispatcher(event); - dispatcher.dispatch([this](ViewportResizeEvent& e) { - m_resolution = glm::ivec2(e.getWidth(), e.getHeight()); - return false; - }); -} - -void Renderer::onImGuiRender() { - // Get the Viewport window and draw the rendered texture - if (ImGui::Begin("Viewport")) { - ImVec2 viewportSize = ImGui::GetContentRegionAvail(); - - if (viewportSize.x > 0 && viewportSize.y > 0) { - GLuint textureId = m_color_pass.getColorTexture()->get_name(); - - // Display the texture using ImGui::Image - // Note: OpenGL uses bottom-left origin, so flip UV coordinates - ImGui::Image( - (ImTextureID)(intptr_t)textureId, - viewportSize, - ImVec2(0, 1), // UV top-left (flipped) - ImVec2(1, 0) // UV bottom-right (flipped) - ); - } - } - ImGui::End(); -} diff --git a/source/paimon/app/application.cpp b/source/paimon/app/application.cpp index ac0bd1c..4f4ff7f 100644 --- a/source/paimon/app/application.cpp +++ b/source/paimon/app/application.cpp @@ -1,5 +1,7 @@ #include "paimon/app/application.h" +#include "paimon/app/panel/editor_layer.h" +#include "paimon/app/panel/interaction_layer.h" #include "paimon/config.h" namespace paimon { @@ -17,7 +19,13 @@ Application::Application(const ApplicationConfig& config) { m_shaderManager.load(PAIMON_SHADER_DIR); - m_imguiLayer = pushLayer(std::make_unique("ImGuiLayer")); + m_imguiLayer = pushLayer(std::make_unique()); + + pushLayer(std::make_unique()); + + pushLayer(std::make_unique()); + + m_renderer = pushLayer(std::make_unique()); } void Application::onEvent(Event& event) { diff --git a/source/paimon/app/application.h b/source/paimon/app/application.h index 70dd7f5..148bde6 100644 --- a/source/paimon/app/application.h +++ b/source/paimon/app/application.h @@ -9,6 +9,7 @@ #include "paimon/app/window.h" #include "paimon/core/ecs/scene.h" #include "paimon/platform/context.h" +#include "paimon/rendering/renderer.h" #include "paimon/rendering/shader_manager.h" namespace paimon { @@ -20,13 +21,13 @@ struct ApplicationConfig { class Application { public: - static Application& getInstance() { return *s_instance; } + static Application &getInstance() { return *s_instance; } - Application(const ApplicationConfig& config = {}); + Application(const ApplicationConfig &config = {}); virtual ~Application() = default; - Application(const Application&) = delete; - Application& operator=(const Application&) = delete; + Application(const Application &) = delete; + Application &operator=(const Application &) = delete; template requires std::is_base_of::value @@ -36,21 +37,28 @@ class Application { return static_cast(m_layers.back().get()); } - void onEvent(Event& event); + void onEvent(Event &event); void run(); - Window* getWindow() const { return m_window.get(); } + Window *getWindow() const { return m_window.get(); } - ShaderManager& getShaderManager() { return m_shaderManager; } - const ShaderManager& getShaderManager() const { return m_shaderManager; } + ShaderManager &getShaderManager() { return m_shaderManager; } + const ShaderManager &getShaderManager() const { return m_shaderManager; } // Scene management - ecs::Scene& getScene() { return *m_scene; } - const ecs::Scene& getScene() const { return *m_scene; } + ecs::Scene &getScene() { return *m_scene; } + const ecs::Scene &getScene() const { return *m_scene; } + + void setScene(std::unique_ptr scene) { + m_scene = std::move(scene); + } + + Renderer& getRenderer() { return *m_renderer; } + const Renderer& getRenderer() const { return *m_renderer; } private: - static Application* s_instance; + static Application *s_instance; std::unique_ptr m_window; @@ -60,6 +68,7 @@ class Application { std::vector> m_layers; ImGuiLayer *m_imguiLayer; + Renderer *m_renderer; }; } // namespace paimon \ No newline at end of file diff --git a/source/paimon/app/imgui/imgui_layer.cpp b/source/paimon/app/imgui/imgui_layer.cpp index 6f73fd8..b4c748e 100644 --- a/source/paimon/app/imgui/imgui_layer.cpp +++ b/source/paimon/app/imgui/imgui_layer.cpp @@ -10,8 +10,8 @@ using namespace paimon; bool ImGuiLayer::s_showDockSpace = true; -ImGuiLayer::ImGuiLayer(const std::string &name) - : Layer(name) {} +ImGuiLayer::ImGuiLayer() + : Layer("ImGuiLayer") {} void ImGuiLayer::onAttach() { diff --git a/source/paimon/app/imgui/imgui_layer.h b/source/paimon/app/imgui/imgui_layer.h index 1bb2607..0367f01 100644 --- a/source/paimon/app/imgui/imgui_layer.h +++ b/source/paimon/app/imgui/imgui_layer.h @@ -6,7 +6,7 @@ namespace paimon { class ImGuiLayer : public Layer { public: - ImGuiLayer(const std::string &name); + ImGuiLayer(); ~ImGuiLayer() = default; diff --git a/source/paimon/app/panel/viewport_panel.cpp b/source/paimon/app/panel/viewport_panel.cpp index 62c46c5..98bf3e6 100644 --- a/source/paimon/app/panel/viewport_panel.cpp +++ b/source/paimon/app/panel/viewport_panel.cpp @@ -14,69 +14,80 @@ ViewportPanel::ViewportPanel() = default; ViewportPanel::~ViewportPanel() = default; void ViewportPanel::onImGuiRender() { + auto &app = Application::getInstance(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin("Viewport"); - + // Get available content region ImVec2 viewportSize = ImGui::GetContentRegionAvail(); - + + auto textureId = + app.getRenderer().getColorPass().getColorTexture()->get_name(); + + // Display the texture using ImGui::Image + // Note: OpenGL uses bottom-left origin, so flip UV coordinates + ImGui::Image((ImTextureID)(intptr_t)textureId, viewportSize, + ImVec2(0, 1), // UV top-left (flipped) + ImVec2(1, 0) // UV bottom-right (flipped) + ); + // Check if viewport size changed glm::ivec2 newSize = glm::ivec2(viewportSize.x, viewportSize.y); if (newSize.x > 0 && newSize.y > 0 && newSize != m_viewportSize) { m_viewportSize = newSize; - + // Dispatch viewport resize event ViewportResizeEvent event(newSize.x, newSize.y); - Application::getInstance().onEvent(event); + app.onEvent(event); } - // Handle camera control input when viewport is focused and hovered - if (ImGui::IsWindowFocused() && ImGui::IsWindowHovered()) { - auto& io = ImGui::GetIO(); - + // Handle camera control input when viewport is hovered + if (ImGui::IsWindowHovered()) { + auto &io = ImGui::GetIO(); + // Handle right mouse button (camera rotation) if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { m_isRightButtonPressed = true; MouseButtonPressedEvent event(MouseCode::Right); - Application::getInstance().onEvent(event); + app.onEvent(event); } if (ImGui::IsMouseReleased(ImGuiMouseButton_Right)) { m_isRightButtonPressed = false; MouseButtonReleasedEvent event(MouseCode::Right); - Application::getInstance().onEvent(event); + app.onEvent(event); } - + // Handle middle mouse button (camera panning) if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle)) { m_isMiddleButtonPressed = true; MouseButtonPressedEvent event(MouseCode::Middle); - Application::getInstance().onEvent(event); + app.onEvent(event); } if (ImGui::IsMouseReleased(ImGuiMouseButton_Middle)) { m_isMiddleButtonPressed = false; MouseButtonReleasedEvent event(MouseCode::Middle); - Application::getInstance().onEvent(event); + app.onEvent(event); } - + // Handle mouse movement (only when right or middle button is pressed) if (m_isRightButtonPressed || m_isMiddleButtonPressed) { ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 windowPos = ImGui::GetWindowPos(); - ImVec2 relativePos = ImVec2(mousePos.x - windowPos.x, mousePos.y - windowPos.y); - + ImVec2 relativePos = + ImVec2(mousePos.x - windowPos.x, mousePos.y - windowPos.y); + MouseMovedEvent event(relativePos.x, relativePos.y); - Application::getInstance().onEvent(event); + app.onEvent(event); } - + // Handle mouse scroll (camera zoom) if (io.MouseWheel != 0.0f) { MouseScrolledEvent event(0.0f, io.MouseWheel); - Application::getInstance().onEvent(event); + app.onEvent(event); } } - - // Viewport content will be rendered by Renderer in its onImGuiRender - + ImGui::End(); ImGui::PopStyleVar(); } diff --git a/example/damaged_helmet/color_pass.cpp b/source/paimon/rendering/render_pass/color_pass.cpp similarity index 99% rename from example/damaged_helmet/color_pass.cpp rename to source/paimon/rendering/render_pass/color_pass.cpp index 29fe111..006ae4f 100644 --- a/example/damaged_helmet/color_pass.cpp +++ b/source/paimon/rendering/render_pass/color_pass.cpp @@ -1,4 +1,4 @@ -#include "color_pass.h" +#include "paimon/rendering/render_pass/color_pass.h" #include diff --git a/example/damaged_helmet/color_pass.h b/source/paimon/rendering/render_pass/color_pass.h similarity index 100% rename from example/damaged_helmet/color_pass.h rename to source/paimon/rendering/render_pass/color_pass.h index 8222955..4c9dda2 100644 --- a/example/damaged_helmet/color_pass.h +++ b/source/paimon/rendering/render_pass/color_pass.h @@ -2,12 +2,12 @@ #include +#include "paimon/core/ecs/scene.h" #include "paimon/opengl/buffer.h" #include "paimon/opengl/sampler.h" #include "paimon/opengl/texture.h" #include "paimon/rendering/graphics_pipeline.h" #include "paimon/rendering/render_context.h" -#include "paimon/core/ecs/scene.h" namespace paimon { diff --git a/example/damaged_helmet/final_pass.cpp b/source/paimon/rendering/render_pass/final_pass.cpp similarity index 97% rename from example/damaged_helmet/final_pass.cpp rename to source/paimon/rendering/render_pass/final_pass.cpp index 64dcaec..7f16d9b 100644 --- a/example/damaged_helmet/final_pass.cpp +++ b/source/paimon/rendering/render_pass/final_pass.cpp @@ -1,4 +1,4 @@ -#include "final_pass.h" +#include "paimon/rendering/render_pass/final_pass.h" #include diff --git a/example/damaged_helmet/final_pass.h b/source/paimon/rendering/render_pass/final_pass.h similarity index 100% rename from example/damaged_helmet/final_pass.h rename to source/paimon/rendering/render_pass/final_pass.h diff --git a/source/paimon/rendering/renderer.cpp b/source/paimon/rendering/renderer.cpp new file mode 100644 index 0000000..8fba649 --- /dev/null +++ b/source/paimon/rendering/renderer.cpp @@ -0,0 +1,41 @@ +#include "paimon/rendering/renderer.h" + +#include + +#include "paimon/app/application.h" +#include "paimon/app/event/application_event.h" + +using namespace paimon; + +Renderer::Renderer() + : Layer("Renderer"), m_renderContext(std::make_unique()), + m_color_pass(*m_renderContext), m_final_pass(*m_renderContext) {} + +void Renderer::onAttach() { + // Initialization if needed +} + +void Renderer::onUpdate() { + if (m_resolution.x == 0 || m_resolution.y == 0) { + return; // Skip rendering if resolution is zero + } + + auto &scene = Application::getInstance().getScene(); + + // First Pass: Render to FBO + m_color_pass.draw(*m_renderContext, m_resolution, scene); + + // Second Pass: Render FBO texture to screen (optional, for debugging) + // m_final_pass.draw(*m_renderContext, *m_color_pass.getColorTexture(), + // m_resolution); +} + +void Renderer::onEvent(Event &event) { + EventDispatcher dispatcher(event); + dispatcher.dispatch([this](ViewportResizeEvent &e) { + m_resolution = glm::ivec2(e.getWidth(), e.getHeight()); + return false; + }); +} + +void Renderer::onImGuiRender() {} diff --git a/example/damaged_helmet/renderer.h b/source/paimon/rendering/renderer.h similarity index 67% rename from example/damaged_helmet/renderer.h rename to source/paimon/rendering/renderer.h index 1231f7a..e6f4769 100644 --- a/example/damaged_helmet/renderer.h +++ b/source/paimon/rendering/renderer.h @@ -2,9 +2,8 @@ #include "paimon/app/layer.h" #include "paimon/rendering/render_context.h" - -#include "color_pass.h" -#include "final_pass.h" +#include "paimon/rendering/render_pass/color_pass.h" +#include "paimon/rendering/render_pass/final_pass.h" namespace paimon { @@ -17,6 +16,10 @@ class Renderer : public Layer { void onUpdate() override; void onEvent(Event &event) override; void onImGuiRender() override; + + const ColorPass &getColorPass() const { return m_color_pass; } + ColorPass &getColorPass() { return m_color_pass; } + private: std::unique_ptr m_renderContext;