From 0999644a711f3500489137bd48e0ebf97854475a Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Fri, 20 Feb 2026 03:35:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor(render):=20=E7=A7=BB=E9=99=A4RenderBac?= =?UTF-8?q?kend=E5=B9=B6=E9=87=8D=E6=9E=84=E6=B8=B2=E6=9F=93=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将RenderBackend相关代码移除,重构渲染系统使用Renderer类 更新所有相关引用和接口,移除backend_factory和render_backend 调整SDL2和GLFW窗口实现,不再直接处理OpenGL上下文 优化GLRHIDevice以支持多种窗口后端创建OpenGL上下文 --- Extra2D/include/extra2d/app/application.h | 4 +- Extra2D/include/extra2d/extra2d.h | 3 - .../backends/opengl/gl_render_backend.h | 302 ------ .../render/backends/opengl/gl_rhi_device.h | 25 + .../extra2d/render/core/backend_factory.h | 182 ---- .../extra2d/render/core/render_backend.h | 324 ------- .../extra2d/render/core/render_context.h | 8 - .../extra2d/render/core/render_module.h | 1 - Extra2D/include/extra2d/render/renderer.h | 314 +++++-- .../include/extra2d/render/rhi/rhi_device.h | 870 +++++++++--------- Extra2D/include/extra2d/scene/node.h | 16 +- Extra2D/include/extra2d/scene/scene.h | 9 +- Extra2D/include/extra2d/scene/scene_manager.h | 3 +- Extra2D/include/extra2d/scene/shape_node.h | 2 +- Extra2D/include/extra2d/scene/sprite.h | 2 +- .../extra2d/scene/transition_box_scene.h | 4 +- .../extra2d/scene/transition_fade_scene.h | 4 +- .../extra2d/scene/transition_flip_scene.h | 4 +- .../extra2d/scene/transition_scale_scene.h | 4 +- .../include/extra2d/scene/transition_scene.h | 8 +- .../extra2d/scene/transition_slide_scene.h | 4 +- .../include/extra2d/services/scene_service.h | 6 +- Extra2D/src/app/application.cpp | 9 +- .../platform/backends/glfw/glfw_window.cpp | 21 +- .../platform/backends/sdl2/sdl2_window.cpp | 52 +- .../src/platform/backends/sdl2/sdl2_window.h | 6 - .../backends/opengl/gl_render_backend.cpp | 521 ----------- .../render/backends/opengl/gl_rhi_device.cpp | 158 +++- Extra2D/src/render/core/backend_factory.cpp | 262 ------ Extra2D/src/render/core/render_context.cpp | 17 - Extra2D/src/render/renderer.cpp | 489 +++++----- Extra2D/src/scene/node.cpp | 8 +- Extra2D/src/scene/scene.cpp | 10 +- Extra2D/src/scene/scene_manager.cpp | 6 +- Extra2D/src/scene/shape_node.cpp | 6 +- Extra2D/src/scene/sprite.cpp | 10 +- Extra2D/src/scene/transition_box_scene.cpp | 6 +- Extra2D/src/scene/transition_fade_scene.cpp | 4 +- Extra2D/src/scene/transition_flip_scene.cpp | 6 +- Extra2D/src/scene/transition_scale_scene.cpp | 6 +- Extra2D/src/scene/transition_scene.cpp | 14 +- Extra2D/src/scene/transition_slide_scene.cpp | 6 +- Extra2D/src/services/scene_service.cpp | 3 +- xmake/engine.lua | 2 - 44 files changed, 1224 insertions(+), 2497 deletions(-) delete mode 100644 Extra2D/include/extra2d/render/backends/opengl/gl_render_backend.h delete mode 100644 Extra2D/include/extra2d/render/core/backend_factory.h delete mode 100644 Extra2D/include/extra2d/render/core/render_backend.h delete mode 100644 Extra2D/src/render/backends/opengl/gl_render_backend.cpp delete mode 100644 Extra2D/src/render/core/backend_factory.cpp diff --git a/Extra2D/include/extra2d/app/application.h b/Extra2D/include/extra2d/app/application.h index bb81cad..151f0b6 100644 --- a/Extra2D/include/extra2d/app/application.h +++ b/Extra2D/include/extra2d/app/application.h @@ -10,7 +10,7 @@ namespace extra2d { class IWindow; class IInput; -class RenderBackend; +class Renderer; class WindowModule; class RenderModule; class InputModule; @@ -93,7 +93,7 @@ public: * @brief 获取渲染器 * @return 渲染器指针 */ - RenderBackend *renderer(); + Renderer *renderer(); /** * @brief 获取输入 diff --git a/Extra2D/include/extra2d/extra2d.h b/Extra2D/include/extra2d/extra2d.h index d3f7835..e78795f 100644 --- a/Extra2D/include/extra2d/extra2d.h +++ b/Extra2D/include/extra2d/extra2d.h @@ -22,13 +22,10 @@ #include // Render Core -#include #include #include #include -#include #include -#include // Render Camera #include diff --git a/Extra2D/include/extra2d/render/backends/opengl/gl_render_backend.h b/Extra2D/include/extra2d/render/backends/opengl/gl_render_backend.h deleted file mode 100644 index 70edfc8..0000000 --- a/Extra2D/include/extra2d/render/backends/opengl/gl_render_backend.h +++ /dev/null @@ -1,302 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace extra2d { - -class IWindow; - -/** - * @brief OpenGL 渲染后端实现 - * - * 实现 RenderBackend 接口,使用 OpenGL 作为底层图形 API - */ -class GLRenderBackend : public RenderBackend { -public: - /** - * @brief 构造函数 - */ - GLRenderBackend(); - - /** - * @brief 析构函数 - */ - ~GLRenderBackend() override; - - // ======================================================================== - // 生命周期 - // ======================================================================== - - /** - * @brief 初始化渲染后端 - * @param window 窗口接口 - * @param config 配置参数 - * @return 成功返回 true - */ - bool init(IWindow *window, const RenderBackendConfig &config = {}) override; - - /** - * @brief 关闭渲染后端 - */ - void shutdown() override; - - /** - * @brief 检查是否已初始化 - */ - bool isValid() const override; - - // ======================================================================== - // 帧管理 - // ======================================================================== - - /** - * @brief 开始帧渲染 - * @param clearColor 清屏颜色 - */ - void beginFrame(const Color &clearColor = Colors::Black) override; - - /** - * @brief 结束帧渲染 - */ - void endFrame() override; - - /** - * @brief 呈现帧 - */ - void present() override; - - // ======================================================================== - // 渲染状态 - // ======================================================================== - - /** - * @brief 设置视口 - */ - void setViewport(int x, int y, int width, int height) override; - - /** - * @brief 设置裁剪区域 - */ - void setScissor(int x, int y, int width, int height) override; - - /** - * @brief 启用/禁用裁剪测试 - */ - void setScissorEnabled(bool enabled) override; - - /** - * @brief 设置投影矩阵 - */ - void setProjectionMatrix(const glm::mat4 &matrix) override; - - /** - * @brief 设置视图矩阵 - */ - void setViewMatrix(const glm::mat4 &matrix) override; - - /** - * @brief 设置垂直同步 - */ - void setVSync(bool enabled) override; - - /** - * @brief 获取垂直同步状态 - */ - bool isVSyncEnabled() const override; - - // ======================================================================== - // 精灵渲染 - // ======================================================================== - - /** - * @brief 绘制精灵 - */ - void drawSprite(Ptr texture, const Rect &destRect, - const Rect &srcRect = Rect(0, 0, 1, 1), - const Color &color = Colors::White, - float rotation = 0.0f, bool flipX = false, - bool flipY = false) override; - - /** - * @brief 绘制精灵(使用变换矩阵) - */ - void drawSprite(Ptr texture, - const glm::mat4 &transform, - const Rect &srcRect = Rect(0, 0, 1, 1), - const Color &color = Colors::White) override; - - /** - * @brief 绘制九宫格精灵 - */ - void draw9Slice(Ptr texture, const Rect &destRect, - const Rect &srcRect, const Vec2 &borderSize, - const Color &color = Colors::White) override; - - // ======================================================================== - // 文本渲染 - // ======================================================================== - - /** - * @brief 绘制文本 - */ - void drawText(const std::string &text, const Vec2 &position, - float fontSize, const Color &color = Colors::White) override; - - /** - * @brief 绘制文本(UTF-32) - */ - void drawText(const std::u32string &text, const Vec2 &position, - float fontSize, const Color &color = Colors::White) override; - - /** - * @brief 测量文本尺寸 - */ - Vec2 measureText(const std::string &text, float fontSize) override; - - /** - * @brief 测量文本尺寸(UTF-32) - */ - Vec2 measureText(const std::u32string &text, float fontSize) override; - - // ======================================================================== - // 形状渲染 - // ======================================================================== - - /** - * @brief 绘制矩形 - */ - void drawRect(const Rect &rect, const Color &color, - float lineWidth = 1.0f) override; - - /** - * @brief 绘制填充矩形 - */ - void fillRect(const Rect &rect, const Color &color) override; - - /** - * @brief 绘制圆形 - */ - void drawCircle(const Vec2 ¢er, float radius, const Color &color, - float lineWidth = 1.0f, uint32_t segments = 32) override; - - /** - * @brief 绘制填充圆形 - */ - void fillCircle(const Vec2 ¢er, float radius, const Color &color, - uint32_t segments = 32) override; - - /** - * @brief 绘制线段 - */ - void drawLine(const Vec2 &start, const Vec2 &end, const Color &color, - float lineWidth = 1.0f) override; - - /** - * @brief 绘制多边形 - */ - void drawPolygon(const Vec2 *points, size_t count, const Color &color, - float lineWidth = 1.0f) override; - - /** - * @brief 绘制填充多边形 - */ - void fillPolygon(const Vec2 *points, size_t count, - const Color &color) override; - - // ======================================================================== - // 批处理控制 - // ======================================================================== - - /** - * @brief 开始精灵批处理 - */ - void beginSpriteBatch() override; - - /** - * @brief 结束精灵批处理 - */ - void endSpriteBatch() override; - - /** - * @brief 刷新当前批次 - */ - void flush() override; - - /** - * @brief 设置渲染排序键 - */ - void setSortKey(uint64_t key) override; - - /** - * @brief 设置渲染层 - */ - void setLayer(int layer) override; - - /** - * @brief 设置混合模式 - */ - void setBlendMode(rhi::BlendState blend) override; - - // ======================================================================== - // 访问器 - // ======================================================================== - - /** - * @brief 获取 RHI 设备 - */ - rhi::RHIDevice *getDevice() const override; - - /** - * @brief 获取窗口宽度 - */ - int getWidth() const override; - - /** - * @brief 获取窗口高度 - */ - int getHeight() const override; - - /** - * @brief 获取渲染统计 - */ - const RenderStats &getStats() const override; - - /** - * @brief 重置渲染统计 - */ - void resetStats() override; - - /** - * @brief 获取图形 API 类型 - */ - rhi::GraphicsAPI getAPI() const override; - - /** - * @brief 获取设备能力 - */ - const rhi::DeviceCaps &getCaps() const override; - -private: - bool initialized_ = false; - IWindow *window_ = nullptr; - RenderBackendConfig config_; - RenderStats stats_; - - Ptr device_; - glm::mat4 projectionMatrix_ = glm::mat4(1.0f); - glm::mat4 viewMatrix_ = glm::mat4(1.0f); - - int width_ = 0; - int height_ = 0; - - uint64_t sortKey_ = 0; - int layer_ = 0; - rhi::BlendState blendState_ = rhi::BlendState::alphaBlend(); - bool inBatch_ = false; -}; - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/render/backends/opengl/gl_rhi_device.h b/Extra2D/include/extra2d/render/backends/opengl/gl_rhi_device.h index a442c56..ad5bb71 100644 --- a/Extra2D/include/extra2d/render/backends/opengl/gl_rhi_device.h +++ b/Extra2D/include/extra2d/render/backends/opengl/gl_rhi_device.h @@ -11,6 +11,15 @@ class IWindow; namespace rhi { +/** + * @brief OpenGL 上下文类型 + */ +enum class GLContextType { + None, + GLFW, + SDL2 +}; + /** * @brief OpenGL RHI 设备实现 * @@ -176,6 +185,12 @@ private: DeviceStats stats_; std::string debugName_; + // OpenGL 上下文相关 + GLContextType contextType_ = GLContextType::None; + void *glfwWindow_ = nullptr; + void *sdlWindow_ = nullptr; + void *glContext_ = nullptr; + // 当前绑定的资源 Ptr currentPipeline_; Ptr currentShader_; @@ -205,6 +220,16 @@ private: void applyPipelineState(const BlendState &blend, const DepthStencilState &depthStencil, const RasterizerState &rasterizer); + + /** + * @brief 初始化 GLFW 上下文 + */ + bool initGLFWContext(); + + /** + * @brief 初始化 SDL2 上下文 + */ + bool initSDL2Context(); }; } // namespace rhi diff --git a/Extra2D/include/extra2d/render/core/backend_factory.h b/Extra2D/include/extra2d/render/core/backend_factory.h deleted file mode 100644 index d067bc9..0000000 --- a/Extra2D/include/extra2d/render/core/backend_factory.h +++ /dev/null @@ -1,182 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace extra2d { - -/** - * @brief 渲染后端工厂 - * - * 管理渲染后端的注册和创建 - * 支持多后端(OpenGL、Vulkan、DirectX 等) - */ -class BackendFactory { -public: - /** - * @brief 后端创建函数类型 - */ - using BackendFn = std::function()>; - - /** - * @brief 后端注册信息 - */ - struct BackendInfo { - std::string name; - BackendFn createFn; - std::vector compatibleWindowBackends; - rhi::GraphicsAPI api; - std::string description; - int priority; - }; - - /** - * @brief 注册渲染后端 - * @param name 后端名称(如 "opengl", "vulkan") - * @param backend 后端创建函数 - * @param windowBackends 兼容的窗口后端列表 - * @param api 图形 API 类型 - * @param description 后端描述 - * @param priority 优先级(用于默认选择) - */ - static void reg(const std::string& name, - BackendFn backend, - const std::vector& windowBackends = {}, - rhi::GraphicsAPI api = rhi::GraphicsAPI::OpenGL, - const std::string& description = "", - int priority = 0); - - /** - * @brief 注销渲染后端 - * @param name 后端名称 - */ - static void unreg(const std::string& name); - - /** - * @brief 创建渲染后端 - * @param name 后端名称 - * @return 后端实例,失败返回 nullptr - */ - static UniquePtr createBackend(const std::string& name); - - /** - * @brief 创建默认渲染后端 - * - * 按优先级选择最佳可用后端 - * @return 后端实例,失败返回 nullptr - */ - static UniquePtr createDefaultBackend(); - - /** - * @brief 根据窗口后端创建兼容的渲染后端 - * @param windowBackend 窗口后端名称 - * @return 后端实例,失败返回 nullptr - */ - static UniquePtr createBackendForWindow(const std::string& windowBackend); - - /** - * @brief 根据图形 API 创建后端 - * @param api 图形 API 类型 - * @return 后端实例,失败返回 nullptr - */ - static UniquePtr createBackendForAPI(rhi::GraphicsAPI api); - - /** - * @brief 检查后端是否已注册 - * @param name 后端名称 - */ - static bool hasBackend(const std::string& name); - - /** - * @brief 获取所有已注册的后端名称 - */ - static std::vector getBackendNames(); - - /** - * @brief 获取后端信息 - * @param name 后端名称 - * @return 后端信息,不存在返回 nullptr - */ - static const BackendInfo* getBackendInfo(const std::string& name); - - /** - * @brief 获取所有后端信息 - */ - static std::vector getAllBackendInfos(); - - /** - * @brief 获取兼容指定窗口后端的所有渲染后端 - * @param windowBackend 窗口后端名称 - */ - static std::vector getCompatibleBackends(const std::string& windowBackend); - - /** - * @brief 清除所有注册的后端 - */ - static void clear(); - - /** - * @brief 获取默认后端名称 - */ - static std::string getDefaultBackendName(); - - /** - * @brief 设置默认后端名称 - */ - static void setDefaultBackendName(const std::string& name); - -private: - static std::unordered_map& getRegistry(); - static std::mutex& getMutex(); - static std::string& getDefaultName(); -}; - -/** - * @brief 后端自动注册器 - * - * 用于静态初始化时自动注册后端 - */ -class BackendRegistrar { -public: - BackendRegistrar(const std::string& name, - BackendFactory::BackendFn backend, - const std::vector& windowBackends = {}, - rhi::GraphicsAPI api = rhi::GraphicsAPI::OpenGL, - const std::string& description = "", - int priority = 0) { - BackendFactory::reg(name, backend, windowBackends, api, description, priority); - } -}; - -/** - * @brief 渲染后端注册宏 - * - * 使用方法: - * E2D_REG_RENDER_BACKEND(opengl, GLRenderBackend, {"sdl2", "glfw"}) - */ -#define E2D_REG_RENDER_BACKEND(name, BackendClass, windowBackends) \ - static ::extra2d::BackendRegistrar E2D_CONCAT(backend_reg_, name)( \ - #name, \ - []() -> ::extra2d::UniquePtr<::extra2d::RenderBackend> { \ - return ::extra2d::makeUnique(); \ - }, \ - windowBackends) - -/** - * @brief 渲染后端注册宏(带优先级) - */ -#define E2D_REG_RENDER_BACKEND_EX(name, BackendClass, windowBackends, api, desc, prio) \ - static ::extra2d::BackendRegistrar E2D_CONCAT(backend_reg_, name)( \ - #name, \ - []() -> ::extra2d::UniquePtr<::extra2d::RenderBackend> { \ - return ::extra2d::makeUnique(); \ - }, \ - windowBackends, api, desc, prio) - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/render/core/render_backend.h b/Extra2D/include/extra2d/render/core/render_backend.h deleted file mode 100644 index 738deff..0000000 --- a/Extra2D/include/extra2d/render/core/render_backend.h +++ /dev/null @@ -1,324 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace extra2d { - -class IWindow; - -/** - * @brief 渲染统计信息 - */ -struct RenderStats { - uint32_t drawCalls = 0; - uint32_t spriteCount = 0; - uint32_t textCharCount = 0; - uint32_t shapeCount = 0; - uint32_t batchCount = 0; - uint32_t textureBinds = 0; - uint32_t shaderBinds = 0; - - void reset() { - drawCalls = 0; - spriteCount = 0; - textCharCount = 0; - shapeCount = 0; - batchCount = 0; - textureBinds = 0; - shaderBinds = 0; - } -}; - -/** - * @brief 渲染后端配置 - */ -struct RenderBackendConfig { - rhi::GraphicsAPI api = rhi::GraphicsAPI::OpenGL; - bool vsync = true; - uint32_t maxBatchSize = 10000; - bool enableDebug = false; -}; - -/** - * @brief 高层渲染后端接口 - * - * 封装 RHI 层,提供游戏逻辑使用的简化渲染接口 - * 支持精灵、文本、形状等高层渲染功能 - */ -class RenderBackend { -public: - virtual ~RenderBackend() = default; - - // ======================================================================== - // 生命周期 - // ======================================================================== - - /** - * @brief 初始化渲染后端 - * @param window 窗口接口 - * @param config 配置参数 - * @return 成功返回 true - */ - virtual bool init(IWindow *window, - const RenderBackendConfig &config = {}) = 0; - - /** - * @brief 关闭渲染后端 - */ - virtual void shutdown() = 0; - - /** - * @brief 检查是否已初始化 - */ - virtual bool isValid() const = 0; - - // ======================================================================== - // 帧管理 - // ======================================================================== - - /** - * @brief 开始帧渲染 - * @param clearColor 清屏颜色 - */ - virtual void beginFrame(const Color &clearColor = Colors::Black) = 0; - - /** - * @brief 结束帧渲染 - */ - virtual void endFrame() = 0; - - /** - * @brief 呈现帧 - */ - virtual void present() = 0; - - // ======================================================================== - // 渲染状态 - // ======================================================================== - - /** - * @brief 设置视口 - */ - virtual void setViewport(int x, int y, int width, int height) = 0; - - /** - * @brief 设置裁剪区域 - */ - virtual void setScissor(int x, int y, int width, int height) = 0; - - /** - * @brief 启用/禁用裁剪测试 - */ - virtual void setScissorEnabled(bool enabled) = 0; - - /** - * @brief 设置投影矩阵 - */ - virtual void setProjectionMatrix(const glm::mat4 &matrix) = 0; - - /** - * @brief 设置视图矩阵 - */ - virtual void setViewMatrix(const glm::mat4 &matrix) = 0; - - /** - * @brief 设置垂直同步 - */ - virtual void setVSync(bool enabled) = 0; - - /** - * @brief 获取垂直同步状态 - */ - virtual bool isVSyncEnabled() const = 0; - - // ======================================================================== - // 精灵渲染 - // ======================================================================== - - /** - * @brief 绘制精灵 - * @param texture 纹理 - * @param destRect 目标矩形 - * @param srcRect 源矩形(纹理坐标) - * @param color 颜色调制 - * @param rotation 旋转角度(度) - * @param flipX 水平翻转 - * @param flipY 垂直翻转 - */ - virtual void drawSprite(Ptr texture, const Rect &destRect, - const Rect &srcRect = Rect(0, 0, 1, 1), - const Color &color = Colors::White, - float rotation = 0.0f, bool flipX = false, - bool flipY = false) = 0; - - /** - * @brief 绘制精灵(使用变换矩阵) - */ - virtual void drawSprite(Ptr texture, - const glm::mat4 &transform, - const Rect &srcRect = Rect(0, 0, 1, 1), - const Color &color = Colors::White) = 0; - - /** - * @brief 绘制九宫格精灵 - */ - virtual void draw9Slice(Ptr texture, const Rect &destRect, - const Rect &srcRect, const Vec2 &borderSize, - const Color &color = Colors::White) = 0; - - // ======================================================================== - // 文本渲染 - // ======================================================================== - - /** - * @brief 绘制文本 - * @param text UTF-8 编码文本 - * @param position 位置 - * @param fontSize 字体大小 - * @param color 颜色 - */ - virtual void drawText(const std::string &text, const Vec2 &position, - float fontSize, const Color &color = Colors::White) = 0; - - /** - * @brief 绘制文本(UTF-32) - */ - virtual void drawText(const std::u32string &text, const Vec2 &position, - float fontSize, const Color &color = Colors::White) = 0; - - /** - * @brief 测量文本尺寸 - */ - virtual Vec2 measureText(const std::string &text, float fontSize) = 0; - - /** - * @brief 测量文本尺寸(UTF-32) - */ - virtual Vec2 measureText(const std::u32string &text, float fontSize) = 0; - - // ======================================================================== - // 形状渲染 - // ======================================================================== - - /** - * @brief 绘制矩形 - */ - virtual void drawRect(const Rect &rect, const Color &color, - float lineWidth = 1.0f) = 0; - - /** - * @brief 绘制填充矩形 - */ - virtual void fillRect(const Rect &rect, const Color &color) = 0; - - /** - * @brief 绘制圆形 - */ - virtual void drawCircle(const Vec2 ¢er, float radius, const Color &color, - float lineWidth = 1.0f, uint32_t segments = 32) = 0; - - /** - * @brief 绘制填充圆形 - */ - virtual void fillCircle(const Vec2 ¢er, float radius, const Color &color, - uint32_t segments = 32) = 0; - - /** - * @brief 绘制线段 - */ - virtual void drawLine(const Vec2 &start, const Vec2 &end, const Color &color, - float lineWidth = 1.0f) = 0; - - /** - * @brief 绘制多边形 - */ - virtual void drawPolygon(const Vec2 *points, size_t count, const Color &color, - float lineWidth = 1.0f) = 0; - - /** - * @brief 绘制填充多边形 - */ - virtual void fillPolygon(const Vec2 *points, size_t count, - const Color &color) = 0; - - // ======================================================================== - // 批处理控制 - // ======================================================================== - - /** - * @brief 开始精灵批处理 - */ - virtual void beginSpriteBatch() = 0; - - /** - * @brief 结束精灵批处理 - */ - virtual void endSpriteBatch() = 0; - - /** - * @brief 刷新当前批次 - */ - virtual void flush() = 0; - - /** - * @brief 设置渲染排序键 - */ - virtual void setSortKey(uint64_t key) = 0; - - /** - * @brief 设置渲染层 - */ - virtual void setLayer(int layer) = 0; - - /** - * @brief 设置混合模式 - */ - virtual void setBlendMode(rhi::BlendState blend) = 0; - - // ======================================================================== - // 访问器 - // ======================================================================== - - /** - * @brief 获取 RHI 设备 - */ - virtual rhi::RHIDevice *getDevice() const = 0; - - /** - * @brief 获取窗口宽度 - */ - virtual int getWidth() const = 0; - - /** - * @brief 获取窗口高度 - */ - virtual int getHeight() const = 0; - - /** - * @brief 获取渲染统计 - */ - virtual const RenderStats &getStats() const = 0; - - /** - * @brief 重置渲染统计 - */ - virtual void resetStats() = 0; - - /** - * @brief 获取图形 API 类型 - */ - virtual rhi::GraphicsAPI getAPI() const = 0; - - /** - * @brief 获取设备能力 - */ - virtual const rhi::DeviceCaps &getCaps() const = 0; -}; - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/render/core/render_context.h b/Extra2D/include/extra2d/render/core/render_context.h index ef2aa56..0e0a537 100644 --- a/Extra2D/include/extra2d/render/core/render_context.h +++ b/Extra2D/include/extra2d/render/core/render_context.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -132,12 +131,6 @@ public: */ IWindow *getWindow() const { return window_; } - /** - * @brief 获取统计信息 - */ - const RenderStats &getStats() const { return stats_; } - void resetStats(); - /** * @brief 获取配置 */ @@ -167,7 +160,6 @@ private: Ptr device_; IWindow *window_; RenderQueue queue_; - RenderStats stats_; RenderContextConfig config_; std::stack transformStack_; diff --git a/Extra2D/include/extra2d/render/core/render_module.h b/Extra2D/include/extra2d/render/core/render_module.h index b3165be..8b1aedc 100644 --- a/Extra2D/include/extra2d/render/core/render_module.h +++ b/Extra2D/include/extra2d/render/core/render_module.h @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/Extra2D/include/extra2d/render/renderer.h b/Extra2D/include/extra2d/render/renderer.h index 44c8026..e67e7b6 100644 --- a/Extra2D/include/extra2d/render/renderer.h +++ b/Extra2D/include/extra2d/render/renderer.h @@ -1,22 +1,46 @@ #pragma once #include +#include #include #include -#include #include -#include #include #include -#include -#include +#include +#include #include +#include +#include namespace extra2d { class IWindow; class Scene; +/** + * @brief 渲染统计信息 + */ +struct RenderStats { + uint32_t drawCalls = 0; + uint32_t spriteCount = 0; + uint32_t textCharCount = 0; + uint32_t shapeCount = 0; + uint32_t batchCount = 0; + uint32_t textureBinds = 0; + uint32_t shaderBinds = 0; + + void reset() { + drawCalls = 0; + spriteCount = 0; + textCharCount = 0; + shapeCount = 0; + batchCount = 0; + textureBinds = 0; + shaderBinds = 0; + } +}; + /** * @brief 渲染器配置 */ @@ -42,7 +66,7 @@ struct RendererConfig { /** * @brief 高层渲染器 * - * 整合渲染后端、批处理器和相机系统 + * 整合 RHI 设备、批处理器和相机系统 * 提供统一的渲染接口供游戏逻辑使用 */ class Renderer : public Module { @@ -105,6 +129,7 @@ public: /** * @brief 开始帧渲染 + * @param clearColor 清屏颜色 */ void beginFrame(const Color &clearColor = Colors::Black); @@ -127,10 +152,188 @@ public: */ void renderScene(Scene *scene); + // ======================================================================== + // 渲染状态 + // ======================================================================== + /** - * @brief 渲染场景(指定相机) + * @brief 设置视口 */ - void renderScene(Scene *scene, Camera *camera); + void setViewport(int x, int y, int width, int height); + + /** + * @brief 设置裁剪区域 + */ + void setScissor(int x, int y, int width, int height); + + /** + * @brief 启用/禁用裁剪测试 + */ + void setScissorEnabled(bool enabled); + + /** + * @brief 设置投影矩阵 + */ + void setProjectionMatrix(const glm::mat4 &matrix); + + /** + * @brief 设置视图矩阵 + */ + void setViewMatrix(const glm::mat4 &matrix); + + /** + * @brief 设置垂直同步 + */ + void setVSync(bool enabled); + + /** + * @brief 获取垂直同步状态 + */ + bool isVSyncEnabled() const; + + // ======================================================================== + // 精灵渲染 + // ======================================================================== + + /** + * @brief 绘制精灵 + * @param texture 纹理 + * @param destRect 目标矩形 + * @param srcRect 源矩形(纹理坐标) + * @param color 颜色调制 + * @param rotation 旋转角度(度) + * @param flipX 水平翻转 + * @param flipY 垂直翻转 + */ + void drawSprite(Ptr texture, const Rect &destRect, + const Rect &srcRect = Rect(0, 0, 1, 1), + const Color &color = Colors::White, + float rotation = 0.0f, bool flipX = false, + bool flipY = false); + + /** + * @brief 绘制精灵(使用变换矩阵) + */ + void drawSprite(Ptr texture, + const glm::mat4 &transform, + const Rect &srcRect = Rect(0, 0, 1, 1), + const Color &color = Colors::White); + + /** + * @brief 绘制九宫格精灵 + */ + void draw9Slice(Ptr texture, const Rect &destRect, + const Rect &srcRect, const Vec2 &borderSize, + const Color &color = Colors::White); + + // ======================================================================== + // 文本渲染 + // ======================================================================== + + /** + * @brief 绘制文本 + * @param text UTF-8 编码文本 + * @param position 位置 + * @param fontSize 字体大小 + * @param color 颜色 + */ + void drawText(const std::string &text, const Vec2 &position, + float fontSize, const Color &color = Colors::White); + + /** + * @brief 绘制文本(UTF-32) + */ + void drawText(const std::u32string &text, const Vec2 &position, + float fontSize, const Color &color = Colors::White); + + /** + * @brief 测量文本尺寸 + */ + Vec2 measureText(const std::string &text, float fontSize); + + /** + * @brief 测量文本尺寸(UTF-32) + */ + Vec2 measureText(const std::u32string &text, float fontSize); + + // ======================================================================== + // 形状渲染 + // ======================================================================== + + /** + * @brief 绘制矩形 + */ + void drawRect(const Rect &rect, const Color &color, + float lineWidth = 1.0f); + + /** + * @brief 绘制填充矩形 + */ + void fillRect(const Rect &rect, const Color &color); + + /** + * @brief 绘制圆形 + */ + void drawCircle(const Vec2 ¢er, float radius, const Color &color, + float lineWidth = 1.0f, uint32_t segments = 32); + + /** + * @brief 绘制填充圆形 + */ + void fillCircle(const Vec2 ¢er, float radius, const Color &color, + uint32_t segments = 32); + + /** + * @brief 绘制线段 + */ + void drawLine(const Vec2 &start, const Vec2 &end, const Color &color, + float lineWidth = 1.0f); + + /** + * @brief 绘制多边形 + */ + void drawPolygon(const Vec2 *points, size_t count, const Color &color, + float lineWidth = 1.0f); + + /** + * @brief 绘制填充多边形 + */ + void fillPolygon(const Vec2 *points, size_t count, + const Color &color); + + // ======================================================================== + // 批处理控制 + // ======================================================================== + + /** + * @brief 开始精灵批处理 + */ + void beginSpriteBatch(); + + /** + * @brief 结束精灵批处理 + */ + void endSpriteBatch(); + + /** + * @brief 刷新当前批次 + */ + void flush(); + + /** + * @brief 设置渲染排序键 + */ + void setSortKey(uint64_t key); + + /** + * @brief 设置渲染层 + */ + void setLayer(int layer); + + /** + * @brief 设置混合模式 + */ + void setBlendMode(rhi::BlendState blend); // ======================================================================== // 相机系统 @@ -162,71 +365,23 @@ public: const ViewportAdapter &getViewportAdapter() const { return viewportAdapter_; } // ======================================================================== - // 渲染状态 + // RHI 设备访问 // ======================================================================== - /** - * @brief 设置视口 - */ - void setViewport(int x, int y, int width, int height); - - /** - * @brief 设置裁剪区域 - */ - void setScissor(int x, int y, int width, int height); - - /** - * @brief 启用/禁用裁剪测试 - */ - void setScissorEnabled(bool enabled); - - /** - * @brief 设置垂直同步 - */ - void setVSync(bool enabled); - - /** - * @brief 获取垂直同步状态 - */ - bool isVSyncEnabled() const; - - // ======================================================================== - // 批处理器访问 - // ======================================================================== - - /** - * @brief 获取精灵批处理器 - */ - SpriteBatcher *getSpriteBatcher() const { return spriteBatcher_.get(); } - - /** - * @brief 获取形状批处理器 - */ - ShapeBatcher *getShapeBatcher() const { return shapeBatcher_.get(); } - - /** - * @brief 获取文本批处理器 - */ - TextBatcher *getTextBatcher() const { return textBatcher_.get(); } - - // ======================================================================== - // 渲染上下文 - // ======================================================================== - - /** - * @brief 获取渲染上下文 - */ - RenderContext *getContext() const { return context_.get(); } - - /** - * @brief 获取渲染后端 - */ - RenderBackend *getBackend() const { return backend_.get(); } - /** * @brief 获取 RHI 设备 */ - rhi::RHIDevice *getDevice() const; + rhi::RHIDevice *getDevice() const { return device_.get(); } + + /** + * @brief 获取图形 API 类型 + */ + rhi::GraphicsAPI getAPI() const; + + /** + * @brief 获取设备能力 + */ + const rhi::DeviceCaps &getCaps() const; // ======================================================================== // 统计信息 @@ -285,11 +440,6 @@ public: static Ptr create(const RendererConfig &config = {}); private: - /** - * @brief 创建批处理器 - */ - bool createBatchers(); - /** * @brief 创建默认相机 */ @@ -300,27 +450,29 @@ private: */ void updateViewportAdapter(); - /** - * @brief 应用相机变换 - */ - void applyCameraTransform(Camera *camera); - IWindow *window_; RendererConfig config_; - UniquePtr context_; - UniquePtr backend_; + Ptr device_; UniquePtr spriteBatcher_; - UniquePtr shapeBatcher_; - UniquePtr textBatcher_; + UniquePtr renderQueue_; ViewportAdapter viewportAdapter_; Ptr activeCamera_; Ptr defaultCamera_; + glm::mat4 projectionMatrix_; + glm::mat4 viewMatrix_; + int width_; int height_; bool initialized_; + + RenderStats stats_; + uint64_t sortKey_; + int layer_; + rhi::BlendState blendState_; + bool inBatch_; }; } // namespace extra2d diff --git a/Extra2D/include/extra2d/render/rhi/rhi_device.h b/Extra2D/include/extra2d/render/rhi/rhi_device.h index a564019..e5746c1 100644 --- a/Extra2D/include/extra2d/render/rhi/rhi_device.h +++ b/Extra2D/include/extra2d/render/rhi/rhi_device.h @@ -9,7 +9,6 @@ #include #include #include -#include namespace extra2d { @@ -21,433 +20,452 @@ namespace rhi { * @brief RHI 设备能力信息 */ struct DeviceCaps { - GraphicsAPI api = GraphicsAPI::OpenGL; - std::string apiVersion; - std::string deviceName; - std::string vendorName; - uint32_t maxTextureSize = 0; - uint32_t maxTextureUnits = 0; - uint32_t maxVertexAttributes = 0; - uint32_t maxUniformBufferBindings = 0; - uint32_t maxColorAttachments = 0; - float maxAnisotropy = 1.0f; - bool supportsCompute = false; - bool supportsGeometry = false; - bool supportsTessellation = false; - bool supportsInstancing = false; - bool supportsIndirectDraw = false; - bool supportsMultiDrawIndirect = false; - bool supportsPersistentMapping = false; - bool supportsBindlessTextures = false; + GraphicsAPI api = GraphicsAPI::OpenGL; + std::string apiVersion; + std::string deviceName; + std::string vendorName; + uint32_t maxTextureSize = 0; + uint32_t maxTextureUnits = 0; + uint32_t maxVertexAttributes = 0; + uint32_t maxUniformBufferBindings = 0; + uint32_t maxColorAttachments = 0; + float maxAnisotropy = 1.0f; + bool supportsCompute = false; + bool supportsGeometry = false; + bool supportsTessellation = false; + bool supportsInstancing = false; + bool supportsIndirectDraw = false; + bool supportsMultiDrawIndirect = false; + bool supportsPersistentMapping = false; + bool supportsBindlessTextures = false; }; /** * @brief RHI 设备统计信息 */ struct DeviceStats { - uint32_t drawCalls = 0; - uint32_t triangleCount = 0; - uint32_t vertexCount = 0; - uint32_t textureBinds = 0; - uint32_t shaderBinds = 0; - uint32_t bufferBinds = 0; - uint32_t framebufferBinds = 0; - uint64_t textureMemory = 0; - uint64_t bufferMemory = 0; + uint32_t drawCalls = 0; + uint32_t triangleCount = 0; + uint32_t vertexCount = 0; + uint32_t textureBinds = 0; + uint32_t shaderBinds = 0; + uint32_t bufferBinds = 0; + uint32_t framebufferBinds = 0; + uint64_t textureMemory = 0; + uint64_t bufferMemory = 0; }; /** * @brief RHI 设备接口 - * + * * 核心渲染硬件接口抽象层 * 提供资源创建、渲染命令提交等功能 */ class RHIDevice { public: - virtual ~RHIDevice() = default; - - // ======================================================================== - // 生命周期 - // ======================================================================== - - /** - * @brief 初始化设备 - * @param window 窗口接口 - * @return 成功返回 true - */ - virtual bool init(IWindow* window) = 0; - - /** - * @brief 关闭设备 - */ - virtual void shutdown() = 0; - - /** - * @brief 检查设备是否有效 - */ - virtual bool isValid() const = 0; - - /** - * @brief 获取图形 API 类型 - */ - virtual GraphicsAPI getAPI() const = 0; - - /** - * @brief 获取设备能力 - */ - virtual const DeviceCaps& getCaps() const = 0; - - // ======================================================================== - // 帧管理 - // ======================================================================== - - /** - * @brief 开始帧 - */ - virtual void beginFrame() = 0; - - /** - * @brief 结束帧 - */ - virtual void endFrame() = 0; - - /** - * @brief 呈现帧 - */ - virtual void present() = 0; - - /** - * @brief 设置垂直同步 - */ - virtual void setVSync(bool enabled) = 0; - - /** - * @brief 获取垂直同步状态 - */ - virtual bool isVSyncEnabled() const = 0; - - /** - * @brief 设置默认帧缓冲尺寸 - */ - virtual void setDefaultFramebufferSize(uint32_t width, uint32_t height) = 0; - - // ======================================================================== - // 资源创建 - 缓冲区 - // ======================================================================== - - /** - * @brief 创建缓冲区 - */ - virtual Ptr createBuffer(const BufferDesc& desc) = 0; - - /** - * @brief 创建顶点缓冲区 - */ - virtual Ptr createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static, - const void* data = nullptr) = 0; - - /** - * @brief 创建索引缓冲区 - */ - virtual Ptr createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static, - const void* data = nullptr) = 0; - - /** - * @brief 创建 Uniform 缓冲区 - */ - virtual Ptr createUniformBuffer(size_t size, BufferUsage usage = BufferUsage::Dynamic) = 0; - - // ======================================================================== - // 资源创建 - 纹理 - // ======================================================================== - - /** - * @brief 创建纹理 - */ - virtual Ptr createTexture(const TextureDesc& desc) = 0; - - /** - * @brief 创建 2D 纹理 - */ - virtual Ptr createTexture2D(uint32_t width, uint32_t height, Format format, - const void* data = nullptr) = 0; - - /** - * @brief 创建采样器 - */ - virtual Ptr createSampler(const SamplerDesc& desc) = 0; - - /** - * @brief 创建纹理视图 - */ - virtual Ptr createTextureView(Ptr texture, - const TextureViewDesc& desc) = 0; - - // ======================================================================== - // 资源创建 - 着色器 - // ======================================================================== - - /** - * @brief 创建着色器 - */ - virtual Ptr createShader(const ShaderDesc& desc) = 0; - - /** - * @brief 从源码创建着色器 - */ - virtual Ptr createShaderFromSource(const std::string& name, - const std::string& vertexSource, - const std::string& fragmentSource) = 0; - - /** - * @brief 从文件创建着色器 - */ - virtual Ptr createShaderFromFile(const std::string& vertexPath, - const std::string& fragmentPath) = 0; - - // ======================================================================== - // 资源创建 - 管线 - // ======================================================================== - - /** - * @brief 创建渲染管线 - */ - virtual Ptr createPipeline(const PipelineDesc& desc, Ptr shader) = 0; - - /** - * @brief 使用构建器创建渲染管线 - */ - virtual Ptr createPipeline(const PipelineBuilder& builder) = 0; - - // ======================================================================== - // 资源创建 - 帧缓冲 - // ======================================================================== - - /** - * @brief 创建帧缓冲 - */ - virtual Ptr createFramebuffer(const FramebufferDesc& desc) = 0; - - /** - * @brief 使用构建器创建帧缓冲 - */ - virtual Ptr createFramebuffer(const FramebufferBuilder& builder) = 0; - - // ======================================================================== - // 渲染状态设置 - // ======================================================================== - - /** - * @brief 设置视口 - */ - virtual void setViewport(const Viewport& viewport) = 0; - - /** - * @brief 设置视口(简化版) - */ - void setViewport(float x, float y, float width, float height, - float minDepth = 0.0f, float maxDepth = 1.0f) { - setViewport(Viewport(x, y, width, height, minDepth, maxDepth)); - } - - /** - * @brief 设置裁剪矩形 - */ - virtual void setScissorRect(const ScissorRect& rect) = 0; - - /** - * @brief 设置裁剪矩形(简化版) - */ - void setScissorRect(int32_t x, int32_t y, uint32_t width, uint32_t height) { - setScissorRect(ScissorRect(x, y, width, height)); - } - - /** - * @brief 启用/禁用裁剪测试 - */ - virtual void setScissorEnabled(bool enabled) = 0; - - // ======================================================================== - // 渲染命令 - 绑定资源 - // ======================================================================== - - /** - * @brief 绑定管线 - */ - virtual void setPipeline(Ptr pipeline) = 0; - - /** - * @brief 绑定着色器 - */ - virtual void setShader(Ptr shader) = 0; - - /** - * @brief 绑定顶点缓冲区 - */ - virtual void setVertexBuffer(uint32_t slot, Ptr buffer, uint32_t offset = 0) = 0; - - /** - * @brief 绑定索引缓冲区 - */ - virtual void setIndexBuffer(Ptr buffer, IndexFormat format) = 0; - - /** - * @brief 绑定纹理 - */ - virtual void setTexture(uint32_t slot, Ptr texture, Ptr sampler = nullptr) = 0; - - /** - * @brief 绑定 Uniform 缓冲区 - */ - virtual void setUniformBuffer(uint32_t slot, Ptr buffer) = 0; - - /** - * @brief 绑定帧缓冲 - */ - virtual void setFramebuffer(Ptr framebuffer) = 0; - - /** - * @brief 解绑帧缓冲(恢复默认) - */ - virtual void setDefaultFramebuffer() = 0; - - // ======================================================================== - // 渲染命令 - Uniform 设置 - // ======================================================================== - - /** - * @brief 设置浮点 Uniform - */ - virtual void setUniformFloat(const std::string& name, float value) = 0; - - /** - * @brief 设置向量 Uniform - */ - virtual void setUniformVec2(const std::string& name, const glm::vec2& value) = 0; - virtual void setUniformVec3(const std::string& name, const glm::vec3& value) = 0; - virtual void setUniformVec4(const std::string& name, const glm::vec4& value) = 0; - - /** - * @brief 设置矩阵 Uniform - */ - virtual void setUniformMat4(const std::string& name, const glm::mat4& value) = 0; - - /** - * @brief 设置整数 Uniform - */ - virtual void setUniformInt(const std::string& name, int value) = 0; - - // ======================================================================== - // 渲染命令 - 绘制 - // ======================================================================== - - /** - * @brief 绘制 - */ - virtual void draw(const DrawCommand& cmd) = 0; - - /** - * @brief 绘制(简化版) - */ - void draw(uint32_t vertexCount, uint32_t firstVertex = 0, uint32_t instanceCount = 1) { - DrawCommand cmd; - cmd.vertexCount = vertexCount; - cmd.firstVertex = firstVertex; - cmd.instanceCount = instanceCount; - draw(cmd); - } - - /** - * @brief 索引绘制 - */ - virtual void drawIndexed(const DrawIndexedCommand& cmd) = 0; - - /** - * @brief 索引绘制(简化版) - */ - void drawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, int32_t vertexOffset = 0, - uint32_t instanceCount = 1) { - DrawIndexedCommand cmd; - cmd.indexCount = indexCount; - cmd.firstIndex = firstIndex; - cmd.vertexOffset = vertexOffset; - cmd.instanceCount = instanceCount; - drawIndexed(cmd); - } - - /** - * @brief 间接绘制 - */ - virtual void drawIndirect(Ptr indirectBuffer, size_t offset) = 0; - - /** - * @brief 索引间接绘制 - */ - virtual void drawIndexedIndirect(Ptr indirectBuffer, size_t offset) = 0; - - // ======================================================================== - // 渲染命令 - 清除 - // ======================================================================== - - /** - * @brief 清除颜色缓冲 - */ - virtual void clearColor(const ColorValue& color) = 0; - - /** - * @brief 清除深度缓冲 - */ - virtual void clearDepth(float depth = 1.0f) = 0; - - /** - * @brief 清除模板缓冲 - */ - virtual void clearStencil(uint8_t stencil = 0) = 0; - - /** - * @brief 清除所有缓冲 - */ - virtual void clear(const ColorValue& color, float depth = 1.0f, uint8_t stencil = 0) = 0; - - // ======================================================================== - // 统计与调试 - // ======================================================================== - - /** - * @brief 获取统计信息 - */ - virtual const DeviceStats& getStats() const = 0; - - /** - * @brief 重置统计信息 - */ - virtual void resetStats() = 0; - - /** - * @brief 检查错误 - */ - virtual bool checkError() = 0; - - /** - * @brief 获取调试名称 - */ - virtual const std::string& getDebugName() const = 0; - - /** - * @brief 设置调试名称 - */ - virtual void setDebugName(const std::string& name) = 0; - - // ======================================================================== - // 静态工厂方法 - // ======================================================================== - - /** - * @brief 创建 RHI 设备 - * @param api 图形 API 类型 - * @return 设备实例 - */ - static Ptr create(GraphicsAPI api); + virtual ~RHIDevice() = default; + + // ======================================================================== + // 生命周期 + // ======================================================================== + + /** + * @brief 初始化设备 + * @param window 窗口接口 + * @return 成功返回 true + */ + virtual bool init(IWindow *window) = 0; + + /** + * @brief 关闭设备 + */ + virtual void shutdown() = 0; + + /** + * @brief 检查设备是否有效 + */ + virtual bool isValid() const = 0; + + /** + * @brief 获取图形 API 类型 + */ + virtual GraphicsAPI getAPI() const = 0; + + /** + * @brief 获取设备能力 + */ + virtual const DeviceCaps &getCaps() const = 0; + + // ======================================================================== + // 帧管理 + // ======================================================================== + + /** + * @brief 开始帧 + */ + virtual void beginFrame() = 0; + + /** + * @brief 结束帧 + */ + virtual void endFrame() = 0; + + /** + * @brief 呈现帧 + */ + virtual void present() = 0; + + /** + * @brief 设置垂直同步 + */ + virtual void setVSync(bool enabled) = 0; + + /** + * @brief 获取垂直同步状态 + */ + virtual bool isVSyncEnabled() const = 0; + + /** + * @brief 设置默认帧缓冲尺寸 + */ + virtual void setDefaultFramebufferSize(uint32_t width, uint32_t height) = 0; + + // ======================================================================== + // 资源创建 - 缓冲区 + // ======================================================================== + + /** + * @brief 创建缓冲区 + */ + virtual Ptr createBuffer(const BufferDesc &desc) = 0; + + /** + * @brief 创建顶点缓冲区 + */ + virtual Ptr + createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static, + const void *data = nullptr) = 0; + + /** + * @brief 创建索引缓冲区 + */ + virtual Ptr + createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static, + const void *data = nullptr) = 0; + + /** + * @brief 创建 Uniform 缓冲区 + */ + virtual Ptr + createUniformBuffer(size_t size, + BufferUsage usage = BufferUsage::Dynamic) = 0; + + // ======================================================================== + // 资源创建 - 纹理 + // ======================================================================== + + /** + * @brief 创建纹理 + */ + virtual Ptr createTexture(const TextureDesc &desc) = 0; + + /** + * @brief 创建 2D 纹理 + */ + virtual Ptr createTexture2D(uint32_t width, uint32_t height, + Format format, + const void *data = nullptr) = 0; + + /** + * @brief 创建采样器 + */ + virtual Ptr createSampler(const SamplerDesc &desc) = 0; + + /** + * @brief 创建纹理视图 + */ + virtual Ptr + createTextureView(Ptr texture, const TextureViewDesc &desc) = 0; + + // ======================================================================== + // 资源创建 - 着色器 + // ======================================================================== + + /** + * @brief 创建着色器 + */ + virtual Ptr createShader(const ShaderDesc &desc) = 0; + + /** + * @brief 从源码创建着色器 + */ + virtual Ptr + createShaderFromSource(const std::string &name, + const std::string &vertexSource, + const std::string &fragmentSource) = 0; + + /** + * @brief 从文件创建着色器 + */ + virtual Ptr + createShaderFromFile(const std::string &vertexPath, + const std::string &fragmentPath) = 0; + + // ======================================================================== + // 资源创建 - 管线 + // ======================================================================== + + /** + * @brief 创建渲染管线 + */ + virtual Ptr createPipeline(const PipelineDesc &desc, + Ptr shader) = 0; + + /** + * @brief 使用构建器创建渲染管线 + */ + virtual Ptr createPipeline(const PipelineBuilder &builder) = 0; + + // ======================================================================== + // 资源创建 - 帧缓冲 + // ======================================================================== + + /** + * @brief 创建帧缓冲 + */ + virtual Ptr + createFramebuffer(const FramebufferDesc &desc) = 0; + + /** + * @brief 使用构建器创建帧缓冲 + */ + virtual Ptr + createFramebuffer(const FramebufferBuilder &builder) = 0; + + // ======================================================================== + // 渲染状态设置 + // ======================================================================== + + /** + * @brief 设置视口 + */ + virtual void setViewport(const Viewport &viewport) = 0; + + /** + * @brief 设置视口(简化版) + */ + void setViewport(float x, float y, float width, float height, + float minDepth = 0.0f, float maxDepth = 1.0f) { + setViewport(Viewport(x, y, width, height, minDepth, maxDepth)); + } + + /** + * @brief 设置裁剪矩形 + */ + virtual void setScissorRect(const ScissorRect &rect) = 0; + + /** + * @brief 设置裁剪矩形(简化版) + */ + void setScissorRect(int32_t x, int32_t y, uint32_t width, uint32_t height) { + setScissorRect(ScissorRect(x, y, width, height)); + } + + /** + * @brief 启用/禁用裁剪测试 + */ + virtual void setScissorEnabled(bool enabled) = 0; + + // ======================================================================== + // 渲染命令 - 绑定资源 + // ======================================================================== + + /** + * @brief 绑定管线 + */ + virtual void setPipeline(Ptr pipeline) = 0; + + /** + * @brief 绑定着色器 + */ + virtual void setShader(Ptr shader) = 0; + + /** + * @brief 绑定顶点缓冲区 + */ + virtual void setVertexBuffer(uint32_t slot, Ptr buffer, + uint32_t offset = 0) = 0; + + /** + * @brief 绑定索引缓冲区 + */ + virtual void setIndexBuffer(Ptr buffer, IndexFormat format) = 0; + + /** + * @brief 绑定纹理 + */ + virtual void setTexture(uint32_t slot, Ptr texture, + Ptr sampler = nullptr) = 0; + + /** + * @brief 绑定 Uniform 缓冲区 + */ + virtual void setUniformBuffer(uint32_t slot, Ptr buffer) = 0; + + /** + * @brief 绑定帧缓冲 + */ + virtual void setFramebuffer(Ptr framebuffer) = 0; + + /** + * @brief 解绑帧缓冲(恢复默认) + */ + virtual void setDefaultFramebuffer() = 0; + + // ======================================================================== + // 渲染命令 - Uniform 设置 + // ======================================================================== + + /** + * @brief 设置浮点 Uniform + */ + virtual void setUniformFloat(const std::string &name, float value) = 0; + + /** + * @brief 设置向量 Uniform + */ + virtual void setUniformVec2(const std::string &name, + const glm::vec2 &value) = 0; + virtual void setUniformVec3(const std::string &name, + const glm::vec3 &value) = 0; + virtual void setUniformVec4(const std::string &name, + const glm::vec4 &value) = 0; + + /** + * @brief 设置矩阵 Uniform + */ + virtual void setUniformMat4(const std::string &name, + const glm::mat4 &value) = 0; + + /** + * @brief 设置整数 Uniform + */ + virtual void setUniformInt(const std::string &name, int value) = 0; + + // ======================================================================== + // 渲染命令 - 绘制 + // ======================================================================== + + /** + * @brief 绘制 + */ + virtual void draw(const DrawCommand &cmd) = 0; + + /** + * @brief 绘制(简化版) + */ + void draw(uint32_t vertexCount, uint32_t firstVertex = 0, + uint32_t instanceCount = 1) { + DrawCommand cmd; + cmd.vertexCount = vertexCount; + cmd.firstVertex = firstVertex; + cmd.instanceCount = instanceCount; + draw(cmd); + } + + /** + * @brief 索引绘制 + */ + virtual void drawIndexed(const DrawIndexedCommand &cmd) = 0; + + /** + * @brief 索引绘制(简化版) + */ + void drawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, + int32_t vertexOffset = 0, uint32_t instanceCount = 1) { + DrawIndexedCommand cmd; + cmd.indexCount = indexCount; + cmd.firstIndex = firstIndex; + cmd.vertexOffset = vertexOffset; + cmd.instanceCount = instanceCount; + drawIndexed(cmd); + } + + /** + * @brief 间接绘制 + */ + virtual void drawIndirect(Ptr indirectBuffer, size_t offset) = 0; + + /** + * @brief 索引间接绘制 + */ + virtual void drawIndexedIndirect(Ptr indirectBuffer, + size_t offset) = 0; + + // ======================================================================== + // 渲染命令 - 清除 + // ======================================================================== + + /** + * @brief 清除颜色缓冲 + */ + virtual void clearColor(const ColorValue &color) = 0; + + /** + * @brief 清除深度缓冲 + */ + virtual void clearDepth(float depth = 1.0f) = 0; + + /** + * @brief 清除模板缓冲 + */ + virtual void clearStencil(uint8_t stencil = 0) = 0; + + /** + * @brief 清除所有缓冲 + */ + virtual void clear(const ColorValue &color, float depth = 1.0f, + uint8_t stencil = 0) = 0; + + // ======================================================================== + // 统计与调试 + // ======================================================================== + + /** + * @brief 获取统计信息 + */ + virtual const DeviceStats &getStats() const = 0; + + /** + * @brief 重置统计信息 + */ + virtual void resetStats() = 0; + + /** + * @brief 检查错误 + */ + virtual bool checkError() = 0; + + /** + * @brief 获取调试名称 + */ + virtual const std::string &getDebugName() const = 0; + + /** + * @brief 设置调试名称 + */ + virtual void setDebugName(const std::string &name) = 0; + + // ======================================================================== + // 静态工厂方法 + // ======================================================================== + + /** + * @brief 创建 RHI 设备 + * @param api 图形 API 类型 + * @return 设备实例 + */ + static Ptr create(GraphicsAPI api); }; /** @@ -455,26 +473,26 @@ public: */ class RHIDeviceScope { public: - explicit RHIDeviceScope(Ptr device) : device_(device) { - if (device_) { - device_->beginFrame(); - } + explicit RHIDeviceScope(Ptr device) : device_(device) { + if (device_) { + device_->beginFrame(); } + } - ~RHIDeviceScope() { - if (device_) { - device_->endFrame(); - } + ~RHIDeviceScope() { + if (device_) { + device_->endFrame(); } + } - RHIDeviceScope(const RHIDeviceScope&) = delete; - RHIDeviceScope& operator=(const RHIDeviceScope&) = delete; + RHIDeviceScope(const RHIDeviceScope &) = delete; + RHIDeviceScope &operator=(const RHIDeviceScope &) = delete; - RHIDevice* operator->() { return device_.get(); } - RHIDevice* get() { return device_.get(); } + RHIDevice *operator->() { return device_.get(); } + RHIDevice *get() { return device_.get(); } private: - Ptr device_; + Ptr device_; }; } // namespace rhi diff --git a/Extra2D/include/extra2d/scene/node.h b/Extra2D/include/extra2d/scene/node.h index 0191894..3e4425c 100644 --- a/Extra2D/include/extra2d/scene/node.h +++ b/Extra2D/include/extra2d/scene/node.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -15,7 +15,7 @@ namespace extra2d { class Scene; -class RenderBackend; +class Renderer; struct RenderCommand; class RenderQueue; @@ -450,9 +450,9 @@ public: /** * @brief 渲染回调 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ - virtual void onRender(RenderBackend &renderer); + virtual void onRender(Renderer &renderer); /** * @brief 附加到场景时的回调 @@ -497,9 +497,9 @@ public: /** * @brief 渲染节点 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ - void render(RenderBackend &renderer); + void render(Renderer &renderer); /** * @brief 对子节点排序 @@ -535,9 +535,9 @@ public: protected: /** * @brief 绘制回调(子类重写) - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ - virtual void onDraw(RenderBackend &renderer) {} + virtual void onDraw(Renderer &renderer) {} /** * @brief 节点更新回调(子类重写) diff --git a/Extra2D/include/extra2d/scene/scene.h b/Extra2D/include/extra2d/scene/scene.h index 41f40f7..f55a590 100644 --- a/Extra2D/include/extra2d/scene/scene.h +++ b/Extra2D/include/extra2d/scene/scene.h @@ -8,6 +8,7 @@ namespace extra2d { class RenderQueue; +class Renderer; /** * @brief 场景类 - 节点容器,管理整个场景图 @@ -120,15 +121,15 @@ public: /** * @brief 渲染场景 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ - void renderScene(RenderBackend &renderer); + void renderScene(Renderer &renderer); /** * @brief 渲染场景内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ - virtual void renderContent(RenderBackend &renderer); + virtual void renderContent(Renderer &renderer); /** * @brief 更新场景 diff --git a/Extra2D/include/extra2d/scene/scene_manager.h b/Extra2D/include/extra2d/scene/scene_manager.h index 66ade15..2bbc8e3 100644 --- a/Extra2D/include/extra2d/scene/scene_manager.h +++ b/Extra2D/include/extra2d/scene/scene_manager.h @@ -14,6 +14,7 @@ namespace extra2d { struct RenderCommand; class TransitionScene; enum class TransitionType; +class Renderer; /** * @brief 场景管理器 - 管理场景的生命周期和切换 @@ -102,7 +103,7 @@ public: // 更新和渲染 // ------------------------------------------------------------------------ void update(float dt); - void render(RenderBackend &renderer); + void render(Renderer &renderer); void collectRenderCommands(std::vector &commands); // ------------------------------------------------------------------------ diff --git a/Extra2D/include/extra2d/scene/shape_node.h b/Extra2D/include/extra2d/scene/shape_node.h index 3e0caa3..9d75b82 100644 --- a/Extra2D/include/extra2d/scene/shape_node.h +++ b/Extra2D/include/extra2d/scene/shape_node.h @@ -84,7 +84,7 @@ public: Rect getBounds() const override; protected: - void onDraw(RenderBackend &renderer) override; + void onDraw(Renderer &renderer) override; void generateRenderCommand(std::vector &commands, int zOrder) override; diff --git a/Extra2D/include/extra2d/scene/sprite.h b/Extra2D/include/extra2d/scene/sprite.h index 915e1ee..a06ba32 100644 --- a/Extra2D/include/extra2d/scene/sprite.h +++ b/Extra2D/include/extra2d/scene/sprite.h @@ -40,7 +40,7 @@ public: Rect getBounds() const override; protected: - void onDraw(RenderBackend &renderer) override; + void onDraw(Renderer &renderer) override; void generateRenderCommand(std::vector &commands, int zOrder) override; diff --git a/Extra2D/include/extra2d/scene/transition_box_scene.h b/Extra2D/include/extra2d/scene/transition_box_scene.h index c48b481..226b0a1 100644 --- a/Extra2D/include/extra2d/scene/transition_box_scene.h +++ b/Extra2D/include/extra2d/scene/transition_box_scene.h @@ -4,6 +4,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 方块/马赛克过渡场景 // 实现原理: @@ -25,7 +27,7 @@ public: protected: void onTransitionStart() override; - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; void updateTransition(float dt) override; private: diff --git a/Extra2D/include/extra2d/scene/transition_fade_scene.h b/Extra2D/include/extra2d/scene/transition_fade_scene.h index 541bf26..2225bf4 100644 --- a/Extra2D/include/extra2d/scene/transition_fade_scene.h +++ b/Extra2D/include/extra2d/scene/transition_fade_scene.h @@ -5,6 +5,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 淡入淡出过渡场景 // 实现原理: @@ -44,7 +46,7 @@ protected: * @brief 渲染内容 * 根据进度控制新旧场景的显示 */ - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; private: /** diff --git a/Extra2D/include/extra2d/scene/transition_flip_scene.h b/Extra2D/include/extra2d/scene/transition_flip_scene.h index 116529e..6096145 100644 --- a/Extra2D/include/extra2d/scene/transition_flip_scene.h +++ b/Extra2D/include/extra2d/scene/transition_flip_scene.h @@ -4,6 +4,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 翻页过渡场景 // 实现原理: @@ -28,7 +30,7 @@ public: protected: void onTransitionStart() override; - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; void updateTransition(float dt) override; private: diff --git a/Extra2D/include/extra2d/scene/transition_scale_scene.h b/Extra2D/include/extra2d/scene/transition_scale_scene.h index 59628a7..8f1892c 100644 --- a/Extra2D/include/extra2d/scene/transition_scale_scene.h +++ b/Extra2D/include/extra2d/scene/transition_scale_scene.h @@ -4,6 +4,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 缩放过渡场景 // 实现原理: @@ -23,7 +25,7 @@ public: protected: void onTransitionStart() override; - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; void updateTransition(float dt) override; }; diff --git a/Extra2D/include/extra2d/scene/transition_scene.h b/Extra2D/include/extra2d/scene/transition_scene.h index 1e15e47..b1a33c2 100644 --- a/Extra2D/include/extra2d/scene/transition_scene.h +++ b/Extra2D/include/extra2d/scene/transition_scene.h @@ -5,6 +5,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 过渡方向 // ============================================================================ @@ -99,7 +101,7 @@ public: // ------------------------------------------------------------------------ // 渲染 - 在 TransitionScene 上渲染新旧两个子场景 // ------------------------------------------------------------------------ - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; // ------------------------------------------------------------------------ // 生命周期 @@ -117,12 +119,12 @@ protected: /** * @brief 绘制源场景(旧场景) */ - virtual void drawOutScene(RenderBackend &renderer); + virtual void drawOutScene(Renderer &renderer); /** * @brief 绘制目标场景(新场景) */ - virtual void drawInScene(RenderBackend &renderer); + virtual void drawInScene(Renderer &renderer); /** * @brief 更新过渡进度(子类重写此方法更新动画) diff --git a/Extra2D/include/extra2d/scene/transition_slide_scene.h b/Extra2D/include/extra2d/scene/transition_slide_scene.h index 7457c64..81bd938 100644 --- a/Extra2D/include/extra2d/scene/transition_slide_scene.h +++ b/Extra2D/include/extra2d/scene/transition_slide_scene.h @@ -4,6 +4,8 @@ namespace extra2d { +class Renderer; + // ============================================================================ // 滑动过渡场景 // 实现原理: @@ -26,7 +28,7 @@ public: protected: void onTransitionStart() override; - void renderContent(RenderBackend &renderer) override; + void renderContent(Renderer &renderer) override; void updateTransition(float dt) override; private: diff --git a/Extra2D/include/extra2d/services/scene_service.h b/Extra2D/include/extra2d/services/scene_service.h index 0f30608..3545047 100644 --- a/Extra2D/include/extra2d/services/scene_service.h +++ b/Extra2D/include/extra2d/services/scene_service.h @@ -6,6 +6,8 @@ namespace extra2d { +class Renderer; + /** * @brief 场景服务接口 * 定义场景管理的抽象接口,便于测试和Mock @@ -30,7 +32,7 @@ public: virtual bool isEmpty() const = 0; virtual bool hasScene(const std::string& name) const = 0; - virtual void render(RenderBackend& renderer) = 0; + virtual void render(Renderer& renderer) = 0; virtual void collectRenderCommands(std::vector& commands) = 0; virtual bool isTransitioning() const = 0; @@ -72,7 +74,7 @@ public: bool isEmpty() const override; bool hasScene(const std::string& name) const override; - void render(RenderBackend& renderer) override; + void render(Renderer& renderer) override; void collectRenderCommands(std::vector& commands) override; bool isTransitioning() const override; diff --git a/Extra2D/src/app/application.cpp b/Extra2D/src/app/application.cpp index c0b727b..458db52 100644 --- a/Extra2D/src/app/application.cpp +++ b/Extra2D/src/app/application.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -209,8 +208,8 @@ void Application::render() { } auto sceneService = ServiceLocator::instance().getService(); - if (sceneService && renderer->getBackend()) { - sceneService->render(*renderer->getBackend()); + if (sceneService) { + sceneService->render(*renderer); } winMod->win()->swap(); @@ -221,9 +220,9 @@ IWindow *Application::window() { return winMod ? winMod->win() : nullptr; } -RenderBackend *Application::renderer() { +Renderer *Application::renderer() { auto *renderMod = get(); - return renderMod ? (renderMod->getRenderer() ? renderMod->getRenderer()->getBackend() : nullptr) : nullptr; + return renderMod ? renderMod->getRenderer() : nullptr; } IInput *Application::input() { diff --git a/Extra2D/src/platform/backends/glfw/glfw_window.cpp b/Extra2D/src/platform/backends/glfw/glfw_window.cpp index 9b4f846..f88af8c 100644 --- a/Extra2D/src/platform/backends/glfw/glfw_window.cpp +++ b/Extra2D/src/platform/backends/glfw/glfw_window.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace extra2d { @@ -19,10 +18,6 @@ bool GLFWWindow::create(const std::string &title, int width, int height, return false; } - glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_DEPTH_BITS, 24); glfwWindowHint(GLFW_STENCIL_BITS, 8); @@ -65,17 +60,6 @@ bool GLFWWindow::create(const std::string &title, int width, int height, } #endif - glfwMakeContextCurrent(glfwWindow_); - - if (!gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress)) { - E2D_LOG_ERROR("初始化 GLAD GLES2 失败"); - glfwDestroyWindow(glfwWindow_); - glfwWindow_ = nullptr; - deinitGLFW(); - return false; - } - - glfwSwapInterval(vsync ? 1 : 0); vsync_ = vsync; glfwGetWindowSize(glfwWindow_, &width_, &height_); @@ -194,10 +178,7 @@ void GLFWWindow::setFullscreen(bool fs) { } void GLFWWindow::setVSync(bool vsync) { - if (glfwWindow_) { - glfwSwapInterval(vsync ? 1 : 0); - vsync_ = vsync; - } + vsync_ = vsync; } void GLFWWindow::setVisible(bool visible) { diff --git a/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp b/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp index 88727f7..e2a6f94 100644 --- a/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp +++ b/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace extra2d { @@ -24,20 +23,12 @@ bool SDL2Window::create(const std::string &title, int width, int height, return false; } - Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; + Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; #ifdef __SWITCH__ flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - sdlWindow_ = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags); @@ -47,27 +38,6 @@ bool SDL2Window::create(const std::string &title, int width, int height, return false; } - glContext_ = SDL_GL_CreateContext(sdlWindow_); - if (!glContext_) { - E2D_LOG_ERROR("创建 OpenGL 上下文失败: {}", SDL_GetError()); - SDL_DestroyWindow(sdlWindow_); - sdlWindow_ = nullptr; - deinitSDL(); - return false; - } - - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - E2D_LOG_ERROR("初始化 GLAD 失败"); - SDL_GL_DeleteContext(glContext_); - glContext_ = nullptr; - SDL_DestroyWindow(sdlWindow_); - sdlWindow_ = nullptr; - deinitSDL(); - return false; - } - - SDL_GL_SetSwapInterval(vsync ? 1 : 0); - SDL_GetWindowSize(sdlWindow_, &width_, &height_); fullscreen_ = (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; vsync_ = vsync; @@ -81,7 +51,6 @@ bool SDL2Window::create(const std::string &title, int width, int height, input_->init(); E2D_LOG_INFO("SDL2 窗口创建成功: {}x{}", width_, height_); - E2D_LOG_INFO(" 平台: OpenGL ES 3.2"); return true; } @@ -95,11 +64,6 @@ void SDL2Window::destroy() { deinitCursors(); #endif - if (glContext_) { - SDL_GL_DeleteContext(glContext_); - glContext_ = nullptr; - } - if (sdlWindow_) { SDL_DestroyWindow(sdlWindow_); sdlWindow_ = nullptr; @@ -123,9 +87,6 @@ void SDL2Window::poll() { } void SDL2Window::swap() { - if (sdlWindow_ && glContext_) { - SDL_GL_SwapWindow(sdlWindow_); - } } bool SDL2Window::shouldClose() const { return shouldClose_; } @@ -169,10 +130,7 @@ void SDL2Window::setFullscreen(bool fs) { } void SDL2Window::setVSync(bool vsync) { - if (glContext_) { - SDL_GL_SetSwapInterval(vsync ? 1 : 0); - vsync_ = vsync; - } + vsync_ = vsync; } void SDL2Window::setVisible(bool visible) { @@ -313,10 +271,8 @@ void SDL2Window::deinitCursors() { void SDL2Window::updateContentScale() { if (sdlWindow_) { SDL_GetWindowSize(sdlWindow_, &width_, &height_); - int dw, dh; - SDL_GL_GetDrawableSize(sdlWindow_, &dw, &dh); - scaleX_ = dw > 0 ? static_cast(dw) / width_ : 1.0f; - scaleY_ = dh > 0 ? static_cast(dh) / height_ : 1.0f; + scaleX_ = 1.0f; + scaleY_ = 1.0f; } } diff --git a/Extra2D/src/platform/backends/sdl2/sdl2_window.h b/Extra2D/src/platform/backends/sdl2/sdl2_window.h index a9f4047..b35139f 100644 --- a/Extra2D/src/platform/backends/sdl2/sdl2_window.h +++ b/Extra2D/src/platform/backends/sdl2/sdl2_window.h @@ -60,11 +60,6 @@ public: */ SDL_Window* sdlWindow() const { return sdlWindow_; } - /** - * @brief 获取 OpenGL 上下文 - */ - SDL_GLContext glContext() const { return glContext_; } - private: bool initSDL(); void deinitSDL(); @@ -75,7 +70,6 @@ private: Key sdlScancodeToKey(int scancode); SDL_Window* sdlWindow_ = nullptr; - SDL_GLContext glContext_ = nullptr; SDL_Cursor* sdlCursors_[7] = {}; int currentCursor_ = 0; diff --git a/Extra2D/src/render/backends/opengl/gl_render_backend.cpp b/Extra2D/src/render/backends/opengl/gl_render_backend.cpp deleted file mode 100644 index 6e0aa46..0000000 --- a/Extra2D/src/render/backends/opengl/gl_render_backend.cpp +++ /dev/null @@ -1,521 +0,0 @@ -#include -#include -#include -#include - -namespace extra2d { - -/** - * @brief 构造函数 - */ -GLRenderBackend::GLRenderBackend() - : initialized_(false) - , window_(nullptr) - , config_() - , stats_() - , device_(nullptr) - , projectionMatrix_(1.0f) - , viewMatrix_(1.0f) - , width_(0) - , height_(0) - , sortKey_(0) - , layer_(0) - , blendState_(rhi::BlendState::alphaBlend()) - , inBatch_(false) { -} - -/** - * @brief 析构函数 - */ -GLRenderBackend::~GLRenderBackend() { - shutdown(); -} - -// ============================================================================ -// 生命周期 -// ============================================================================ - -/** - * @brief 初始化渲染后端 - */ -bool GLRenderBackend::init(IWindow *window, const RenderBackendConfig &config) { - if (initialized_) { - return true; - } - - if (!window) { - return false; - } - - window_ = window; - config_ = config; - width_ = window->width(); - height_ = window->height(); - - device_ = rhi::RHIDevice::create(rhi::GraphicsAPI::OpenGL); - if (!device_) { - return false; - } - - if (!device_->init(window)) { - device_.reset(); - return false; - } - - projectionMatrix_ = glm::ortho(0.0f, static_cast(width_), - static_cast(height_), 0.0f, - -1.0f, 1.0f); - viewMatrix_ = glm::mat4(1.0f); - - initialized_ = true; - return true; -} - -/** - * @brief 关闭渲染后端 - */ -void GLRenderBackend::shutdown() { - if (!initialized_) { - return; - } - - if (device_) { - device_->shutdown(); - device_.reset(); - } - - window_ = nullptr; - width_ = 0; - height_ = 0; - initialized_ = false; -} - -/** - * @brief 检查是否已初始化 - */ -bool GLRenderBackend::isValid() const { - return initialized_ && device_ && device_->isValid(); -} - -// ============================================================================ -// 帧管理 -// ============================================================================ - -/** - * @brief 开始帧渲染 - */ -void GLRenderBackend::beginFrame(const Color &clearColor) { - if (!isValid()) { - return; - } - - stats_.reset(); - device_->beginFrame(); - device_->resetStats(); - - rhi::ColorValue cv(clearColor.r, clearColor.g, clearColor.b, clearColor.a); - device_->clearColor(cv); - - device_->setViewport(rhi::Viewport(0.0f, 0.0f, - static_cast(width_), - static_cast(height_))); -} - -/** - * @brief 结束帧渲染 - */ -void GLRenderBackend::endFrame() { - if (!isValid()) { - return; - } - - if (inBatch_) { - endSpriteBatch(); - } - - device_->endFrame(); -} - -/** - * @brief 呈现帧 - */ -void GLRenderBackend::present() { - if (!isValid()) { - return; - } - - device_->present(); -} - -// ============================================================================ -// 渲染状态 -// ============================================================================ - -/** - * @brief 设置视口 - */ -void GLRenderBackend::setViewport(int x, int y, int width, int height) { - if (!isValid()) { - return; - } - - device_->setViewport(rhi::Viewport( - static_cast(x), - static_cast(y), - static_cast(width), - static_cast(height))); -} - -/** - * @brief 设置裁剪区域 - */ -void GLRenderBackend::setScissor(int x, int y, int width, int height) { - if (!isValid()) { - return; - } - - device_->setScissorRect(rhi::ScissorRect(x, y, - static_cast(width), - static_cast(height))); -} - -/** - * @brief 启用/禁用裁剪测试 - */ -void GLRenderBackend::setScissorEnabled(bool enabled) { - if (!isValid()) { - return; - } - - device_->setScissorEnabled(enabled); -} - -/** - * @brief 设置投影矩阵 - */ -void GLRenderBackend::setProjectionMatrix(const glm::mat4 &matrix) { - projectionMatrix_ = matrix; -} - -/** - * @brief 设置视图矩阵 - */ -void GLRenderBackend::setViewMatrix(const glm::mat4 &matrix) { - viewMatrix_ = matrix; -} - -/** - * @brief 设置垂直同步 - */ -void GLRenderBackend::setVSync(bool enabled) { - if (!isValid()) { - return; - } - - device_->setVSync(enabled); -} - -/** - * @brief 获取垂直同步状态 - */ -bool GLRenderBackend::isVSyncEnabled() const { - return isValid() ? device_->isVSyncEnabled() : false; -} - -// ============================================================================ -// 精灵渲染 -// ============================================================================ - -/** - * @brief 绘制精灵 - */ -void GLRenderBackend::drawSprite(Ptr texture, const Rect &destRect, - const Rect &srcRect, const Color &color, - float rotation, bool flipX, bool flipY) { - if (!isValid() || !texture) { - return; - } - - stats_.spriteCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制精灵(使用变换矩阵) - */ -void GLRenderBackend::drawSprite(Ptr texture, - const glm::mat4 &transform, - const Rect &srcRect, const Color &color) { - if (!isValid() || !texture) { - return; - } - - stats_.spriteCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制九宫格精灵 - */ -void GLRenderBackend::draw9Slice(Ptr texture, const Rect &destRect, - const Rect &srcRect, const Vec2 &borderSize, - const Color &color) { - if (!isValid() || !texture) { - return; - } - - stats_.spriteCount += 9; - stats_.drawCalls++; -} - -// ============================================================================ -// 文本渲染 -// ============================================================================ - -/** - * @brief 绘制文本 - */ -void GLRenderBackend::drawText(const std::string &text, const Vec2 &position, - float fontSize, const Color &color) { - if (!isValid() || text.empty()) { - return; - } - - stats_.textCharCount += static_cast(text.length()); - stats_.drawCalls++; -} - -/** - * @brief 绘制文本(UTF-32) - */ -void GLRenderBackend::drawText(const std::u32string &text, const Vec2 &position, - float fontSize, const Color &color) { - if (!isValid() || text.empty()) { - return; - } - - stats_.textCharCount += static_cast(text.length()); - stats_.drawCalls++; -} - -/** - * @brief 测量文本尺寸 - */ -Vec2 GLRenderBackend::measureText(const std::string &text, float fontSize) { - float width = static_cast(text.length()) * fontSize * 0.6f; - return Vec2(width, fontSize); -} - -/** - * @brief 测量文本尺寸(UTF-32) - */ -Vec2 GLRenderBackend::measureText(const std::u32string &text, float fontSize) { - float width = static_cast(text.length()) * fontSize * 0.6f; - return Vec2(width, fontSize); -} - -// ============================================================================ -// 形状渲染 -// ============================================================================ - -/** - * @brief 绘制矩形 - */ -void GLRenderBackend::drawRect(const Rect &rect, const Color &color, float lineWidth) { - if (!isValid()) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制填充矩形 - */ -void GLRenderBackend::fillRect(const Rect &rect, const Color &color) { - if (!isValid()) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制圆形 - */ -void GLRenderBackend::drawCircle(const Vec2 ¢er, float radius, const Color &color, - float lineWidth, uint32_t segments) { - if (!isValid()) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制填充圆形 - */ -void GLRenderBackend::fillCircle(const Vec2 ¢er, float radius, const Color &color, - uint32_t segments) { - if (!isValid()) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制线段 - */ -void GLRenderBackend::drawLine(const Vec2 &start, const Vec2 &end, const Color &color, - float lineWidth) { - if (!isValid()) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制多边形 - */ -void GLRenderBackend::drawPolygon(const Vec2 *points, size_t count, const Color &color, - float lineWidth) { - if (!isValid() || !points || count < 3) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -/** - * @brief 绘制填充多边形 - */ -void GLRenderBackend::fillPolygon(const Vec2 *points, size_t count, const Color &color) { - if (!isValid() || !points || count < 3) { - return; - } - - stats_.shapeCount++; - stats_.drawCalls++; -} - -// ============================================================================ -// 批处理控制 -// ============================================================================ - -/** - * @brief 开始精灵批处理 - */ -void GLRenderBackend::beginSpriteBatch() { - inBatch_ = true; -} - -/** - * @brief 结束精灵批处理 - */ -void GLRenderBackend::endSpriteBatch() { - if (!inBatch_) { - return; - } - - flush(); - inBatch_ = false; -} - -/** - * @brief 刷新当前批次 - */ -void GLRenderBackend::flush() { - if (!isValid()) { - return; - } - - stats_.batchCount++; -} - -/** - * @brief 设置渲染排序键 - */ -void GLRenderBackend::setSortKey(uint64_t key) { - sortKey_ = key; -} - -/** - * @brief 设置渲染层 - */ -void GLRenderBackend::setLayer(int layer) { - layer_ = layer; -} - -/** - * @brief 设置混合模式 - */ -void GLRenderBackend::setBlendMode(rhi::BlendState blend) { - blendState_ = blend; -} - -// ============================================================================ -// 访问器 -// ============================================================================ - -/** - * @brief 获取 RHI 设备 - */ -rhi::RHIDevice *GLRenderBackend::getDevice() const { - return device_.get(); -} - -/** - * @brief 获取窗口宽度 - */ -int GLRenderBackend::getWidth() const { - return width_; -} - -/** - * @brief 获取窗口高度 - */ -int GLRenderBackend::getHeight() const { - return height_; -} - -/** - * @brief 获取渲染统计 - */ -const RenderStats &GLRenderBackend::getStats() const { - return stats_; -} - -/** - * @brief 重置渲染统计 - */ -void GLRenderBackend::resetStats() { - stats_.reset(); - if (device_) { - device_->resetStats(); - } -} - -/** - * @brief 获取图形 API 类型 - */ -rhi::GraphicsAPI GLRenderBackend::getAPI() const { - return rhi::GraphicsAPI::OpenGL; -} - -/** - * @brief 获取设备能力 - */ -const rhi::DeviceCaps &GLRenderBackend::getCaps() const { - static rhi::DeviceCaps empty; - return device_ ? device_->getCaps() : empty; -} - -} // namespace extra2d diff --git a/Extra2D/src/render/backends/opengl/gl_rhi_device.cpp b/Extra2D/src/render/backends/opengl/gl_rhi_device.cpp index 02914c3..fae772c 100644 --- a/Extra2D/src/render/backends/opengl/gl_rhi_device.cpp +++ b/Extra2D/src/render/backends/opengl/gl_rhi_device.cpp @@ -6,6 +6,15 @@ #include #include #include + +#ifdef E2D_BACKEND_GLFW +#include +#endif + +#ifdef E2D_BACKEND_SDL2 +#include +#endif + #include #include @@ -28,10 +37,35 @@ bool GLRHIDevice::init(IWindow* window) { } window_ = window; + if (!window_) { + E2D_LOG_ERROR("窗口不能为空"); + return false; + } - // 初始化 OpenGL 上下文 - if (!GLContext::get().init()) { - E2D_LOG_ERROR("初始化 OpenGL 上下文失败"); + // 尝试识别窗口类型并创建 OpenGL 上下文 + void* nativeHandle = window_->native(); + if (!nativeHandle) { + E2D_LOG_ERROR("无法获取原生窗口句柄"); + return false; + } + + // 首先尝试 GLFW 窗口(通过动态类型检查或已知的窗口类) + // 注意:这里我们需要通过某种方式识别窗口类型 + // 由于没有 RTTI 信息,我们尝试两种方式 + + bool contextCreated = false; + + // 先尝试 GLFW + if (initGLFWContext()) { + contextCreated = true; + } + // 如果 GLFW 失败,尝试 SDL2 + else if (initSDL2Context()) { + contextCreated = true; + } + + if (!contextCreated) { + E2D_LOG_ERROR("无法创建 OpenGL 上下文"); return false; } @@ -62,12 +96,108 @@ void GLRHIDevice::shutdown() { currentShader_.reset(); currentFramebuffer_.reset(); + // 销毁 OpenGL 上下文 +#ifdef E2D_BACKEND_SDL2 + if (contextType_ == GLContextType::SDL2 && glContext_) { + SDL_GL_DeleteContext(static_cast(glContext_)); + } +#endif + GLContext::get().shutdown(); initialized_ = false; + contextType_ = GLContextType::None; + glfwWindow_ = nullptr; + sdlWindow_ = nullptr; + glContext_ = nullptr; E2D_LOG_INFO("OpenGL RHI 设备已关闭"); } +bool GLRHIDevice::initGLFWContext() { +#ifdef E2D_BACKEND_GLFW + // 尝试将窗口句柄作为 GLFWwindow 使用 + GLFWwindow* glfwWin = static_cast(window_->native()); + if (!glfwWin) { + return false; + } + + // 设置 OpenGL 上下文属性 + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); + glfwWindowHint(GLFW_DEPTH_BITS, 24); + glfwWindowHint(GLFW_STENCIL_BITS, 8); + + // 对于 GLFW,我们需要重新创建带上下文的窗口 + // 或者尝试使用当前窗口创建上下文 + // 这里我们假设窗口已经存在,但没有 OpenGL 上下文 + // 实际上,GLFW 窗口创建时必须指定 API + // 所以我们需要一个不同的方法 + // 这里我们简化处理,尝试直接使用 gladLoadGLLoader + glfwMakeContextCurrent(glfwWin); + + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + E2D_LOG_ERROR("初始化 GLAD 失败 (GLFW)"); + return false; + } + + glfwSwapInterval(window_->vsync() ? 1 : 0); + + contextType_ = GLContextType::GLFW; + glfwWindow_ = glfwWin; + + E2D_LOG_INFO("GLFW OpenGL 上下文创建成功"); + return true; +#else + return false; +#endif +} + +bool GLRHIDevice::initSDL2Context() { +#ifdef E2D_BACKEND_SDL2 + // 尝试将窗口句柄作为 SDL_Window 使用 + SDL_Window* sdlWin = static_cast(window_->native()); + if (!sdlWin) { + return false; + } + + // 设置 OpenGL 属性 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + + // 创建 OpenGL 上下文 + SDL_GLContext context = SDL_GL_CreateContext(sdlWin); + if (!context) { + E2D_LOG_ERROR("创建 OpenGL 上下文失败 (SDL2): {}", SDL_GetError()); + return false; + } + + // 初始化 GLAD + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { + E2D_LOG_ERROR("初始化 GLAD 失败 (SDL2)"); + SDL_GL_DeleteContext(context); + return false; + } + + SDL_GL_SetSwapInterval(window_->vsync() ? 1 : 0); + + contextType_ = GLContextType::SDL2; + sdlWindow_ = sdlWin; + glContext_ = context; + + E2D_LOG_INFO("SDL2 OpenGL 上下文创建成功"); + return true; +#else + return false; +#endif +} + void GLRHIDevice::initCaps() { caps_.api = GraphicsAPI::OpenGL; caps_.apiVersion = GLContext::get().getVersionString(); @@ -124,16 +254,30 @@ void GLRHIDevice::endFrame() { } void GLRHIDevice::present() { - if (window_) { - window_->swap(); +#ifdef E2D_BACKEND_GLFW + if (contextType_ == GLContextType::GLFW && glfwWindow_) { + glfwSwapBuffers(static_cast(glfwWindow_)); } +#endif +#ifdef E2D_BACKEND_SDL2 + if (contextType_ == GLContextType::SDL2 && sdlWindow_) { + SDL_GL_SwapWindow(static_cast(sdlWindow_)); + } +#endif } void GLRHIDevice::setVSync(bool enabled) { vsyncEnabled_ = enabled; - if (window_) { - window_->setVSync(enabled); +#ifdef E2D_BACKEND_GLFW + if (contextType_ == GLContextType::GLFW) { + glfwSwapInterval(enabled ? 1 : 0); } +#endif +#ifdef E2D_BACKEND_SDL2 + if (contextType_ == GLContextType::SDL2) { + SDL_GL_SetSwapInterval(enabled ? 1 : 0); + } +#endif } void GLRHIDevice::setDefaultFramebufferSize(uint32_t width, uint32_t height) { diff --git a/Extra2D/src/render/core/backend_factory.cpp b/Extra2D/src/render/core/backend_factory.cpp deleted file mode 100644 index bb85034..0000000 --- a/Extra2D/src/render/core/backend_factory.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include -#include -#include - -namespace extra2d { - -std::unordered_map& BackendFactory::getRegistry() { - static std::unordered_map registry; - return registry; -} - -std::mutex& BackendFactory::getMutex() { - static std::mutex mutex; - return mutex; -} - -std::string& BackendFactory::getDefaultName() { - static std::string defaultName = "opengl"; - return defaultName; -} - -/** - * @brief 注册渲染后端 - */ -void BackendFactory::reg(const std::string& name, - BackendFn backend, - const std::vector& windowBackends, - rhi::GraphicsAPI api, - const std::string& description, - int priority) { - std::lock_guard lock(getMutex()); - - BackendInfo info; - info.name = name; - info.createFn = backend; - info.compatibleWindowBackends = windowBackends; - info.api = api; - info.description = description; - info.priority = priority; - - getRegistry()[name] = info; -} - -/** - * @brief 注销渲染后端 - */ -void BackendFactory::unreg(const std::string& name) { - std::lock_guard lock(getMutex()); - getRegistry().erase(name); -} - -/** - * @brief 创建渲染后端 - */ -UniquePtr BackendFactory::createBackend(const std::string& name) { - std::lock_guard lock(getMutex()); - - auto& registry = getRegistry(); - auto it = registry.find(name); - if (it != registry.end() && it->second.createFn) { - return it->second.createFn(); - } - - return nullptr; -} - -/** - * @brief 创建默认渲染后端 - */ -UniquePtr BackendFactory::createDefaultBackend() { - std::lock_guard lock(getMutex()); - - auto& registry = getRegistry(); - if (registry.empty()) { - return makeUnique(); - } - - std::string defaultName = getDefaultName(); - auto it = registry.find(defaultName); - if (it != registry.end() && it->second.createFn) { - return it->second.createFn(); - } - - std::vector sorted; - for (auto& pair : registry) { - sorted.push_back(&pair.second); - } - std::sort(sorted.begin(), sorted.end(), - [](const BackendInfo* a, const BackendInfo* b) { - return a->priority > b->priority; - }); - - if (!sorted.empty() && sorted.front()->createFn) { - return sorted.front()->createFn(); - } - - return makeUnique(); -} - -/** - * @brief 根据窗口后端创建兼容的渲染后端 - */ -UniquePtr BackendFactory::createBackendForWindow(const std::string& windowBackend) { - std::lock_guard lock(getMutex()); - - auto& registry = getRegistry(); - - std::vector compatible; - for (auto& pair : registry) { - const auto& windowBackends = pair.second.compatibleWindowBackends; - if (windowBackends.empty() || - std::find(windowBackends.begin(), windowBackends.end(), windowBackend) != windowBackends.end()) { - compatible.push_back(&pair.second); - } - } - - std::sort(compatible.begin(), compatible.end(), - [](const BackendInfo* a, const BackendInfo* b) { - return a->priority > b->priority; - }); - - if (!compatible.empty() && compatible.front()->createFn) { - return compatible.front()->createFn(); - } - - return makeUnique(); -} - -/** - * @brief 根据图形 API 创建后端 - */ -UniquePtr BackendFactory::createBackendForAPI(rhi::GraphicsAPI api) { - std::lock_guard lock(getMutex()); - - auto& registry = getRegistry(); - - std::vector matching; - for (auto& pair : registry) { - if (pair.second.api == api) { - matching.push_back(&pair.second); - } - } - - std::sort(matching.begin(), matching.end(), - [](const BackendInfo* a, const BackendInfo* b) { - return a->priority > b->priority; - }); - - if (!matching.empty() && matching.front()->createFn) { - return matching.front()->createFn(); - } - - if (api == rhi::GraphicsAPI::OpenGL) { - return makeUnique(); - } - - return nullptr; -} - -/** - * @brief 检查后端是否已注册 - */ -bool BackendFactory::hasBackend(const std::string& name) { - std::lock_guard lock(getMutex()); - return getRegistry().find(name) != getRegistry().end(); -} - -/** - * @brief 获取所有已注册的后端名称 - */ -std::vector BackendFactory::getBackendNames() { - std::lock_guard lock(getMutex()); - - std::vector names; - for (const auto& pair : getRegistry()) { - names.push_back(pair.first); - } - return names; -} - -/** - * @brief 获取后端信息 - */ -const BackendFactory::BackendInfo* BackendFactory::getBackendInfo(const std::string& name) { - std::lock_guard lock(getMutex()); - - auto& registry = getRegistry(); - auto it = registry.find(name); - if (it != registry.end()) { - return &it->second; - } - return nullptr; -} - -/** - * @brief 获取所有后端信息 - */ -std::vector BackendFactory::getAllBackendInfos() { - std::lock_guard lock(getMutex()); - - std::vector infos; - for (const auto& pair : getRegistry()) { - infos.push_back(pair.second); - } - return infos; -} - -/** - * @brief 获取兼容指定窗口后端的所有渲染后端 - */ -std::vector BackendFactory::getCompatibleBackends(const std::string& windowBackend) { - std::lock_guard lock(getMutex()); - - std::vector names; - for (const auto& pair : getRegistry()) { - const auto& windowBackends = pair.second.compatibleWindowBackends; - if (windowBackends.empty() || - std::find(windowBackends.begin(), windowBackends.end(), windowBackend) != windowBackends.end()) { - names.push_back(pair.first); - } - } - return names; -} - -/** - * @brief 清除所有注册的后端 - */ -void BackendFactory::clear() { - std::lock_guard lock(getMutex()); - getRegistry().clear(); -} - -/** - * @brief 获取默认后端名称 - */ -std::string BackendFactory::getDefaultBackendName() { - return getDefaultName(); -} - -/** - * @brief 设置默认后端名称 - */ -void BackendFactory::setDefaultBackendName(const std::string& name) { - getDefaultName() = name; -} - -namespace { - -static BackendRegistrar s_openglBackendReg( - "opengl", - []() -> UniquePtr { - return makeUnique(); - }, - {"sdl2", "glfw"}, - rhi::GraphicsAPI::OpenGL, - "OpenGL 4.5 Core Profile", - 100 -); - -} - -} // namespace extra2d diff --git a/Extra2D/src/render/core/render_context.cpp b/Extra2D/src/render/core/render_context.cpp index 8aa033d..26eae09 100644 --- a/Extra2D/src/render/core/render_context.cpp +++ b/Extra2D/src/render/core/render_context.cpp @@ -7,7 +7,6 @@ RenderContext::RenderContext() : device_(nullptr), window_(nullptr), queue_(), - stats_(), config_(), currentBlend_(rhi::BlendState::alphaBlend()), viewport_(), @@ -23,7 +22,6 @@ RenderContext::RenderContext(const RenderContextConfig& config) : device_(nullptr), window_(nullptr), queue_(), - stats_(), config_(config), currentBlend_(rhi::BlendState::alphaBlend()), viewport_(), @@ -100,7 +98,6 @@ void RenderContext::beginFrame() { return; } - stats_.reset(); device_->beginFrame(); device_->resetStats(); @@ -244,13 +241,6 @@ void RenderContext::flushQueue() { const auto& commands = queue_.getCommands(); const RenderQueueStats& queueStats = queue_.getStats(); - stats_.spriteCount = queueStats.spriteCommands; - stats_.textCharCount = queueStats.textCommands; - stats_.shapeCount = queueStats.shapeCommands; - - stats_.batchCount = queueStats.batchCount; - stats_.drawCalls = queueStats.drawCalls; - queue_.clear(); } @@ -282,11 +272,4 @@ void RenderContext::initDefaultState() { scissorEnabled_ = false; } -void RenderContext::resetStats() { - stats_.reset(); - if (device_) { - device_->resetStats(); - } -} - } // namespace extra2d diff --git a/Extra2D/src/render/renderer.cpp b/Extra2D/src/render/renderer.cpp index cc4ad38..c15103e 100644 --- a/Extra2D/src/render/renderer.cpp +++ b/Extra2D/src/render/renderer.cpp @@ -1,19 +1,24 @@ #include #include -#include -#include #include #include +#include +#include namespace extra2d { Renderer::Renderer() - : window_(nullptr), width_(0), height_(0), initialized_(false) {} + : window_(nullptr), config_(), width_(0), height_(0), initialized_(false), + projectionMatrix_(1.0f), viewMatrix_(1.0f), stats_(), + sortKey_(0), layer_(0), blendState_(rhi::BlendState::alphaBlend()), + inBatch_(false) {} Renderer::Renderer(const RendererConfig &config) - : window_(nullptr), config_(config), width_(0), height_(0), - initialized_(false) {} + : window_(nullptr), config_(config), width_(0), height_(0), initialized_(false), + projectionMatrix_(1.0f), viewMatrix_(1.0f), stats_(), + sortKey_(0), layer_(0), blendState_(rhi::BlendState::alphaBlend()), + inBatch_(false) {} Renderer::~Renderer() { shutdown(); } @@ -38,36 +43,24 @@ bool Renderer::init(IWindow *window, const RendererConfig &config) { viewportAdapter_.setConfig(config.viewportConfig); viewportAdapter_.update(width_, height_); - RenderBackendConfig backendConfig; - backendConfig.api = config.api; - backendConfig.vsync = config.vsync; - backendConfig.maxBatchSize = config.maxBatchSize; - backendConfig.enableDebug = config.enableDebug; - - backend_ = BackendFactory::createBackendForAPI(config.api); - if (!backend_ || !backend_->init(window, backendConfig)) { + device_ = rhi::RHIDevice::create(config.api); + if (!device_ || !device_->init(window)) { return false; } - RenderContextConfig contextConfig; - contextConfig.maxBatchSize = config.maxBatchSize; - contextConfig.preferredAPI = config.api; - - context_ = makeUnique(contextConfig); - if (!context_->init(window, config.api)) { + spriteBatcher_ = makeUnique(); + SpriteBatcherConfig batcherConfig; + batcherConfig.maxBatchSize = config.maxBatchSize; + if (!spriteBatcher_->init(device_)) { return false; } - auto& shaderManager = ShaderManager::getInstance(); - if (!shaderManager.isInitialized()) { - if (!shaderManager.init(context_->getDevice(), "shaders")) { - return false; - } - } + renderQueue_ = makeUnique(); - if (!createBatchers()) { - return false; - } + projectionMatrix_ = glm::ortho(0.0f, static_cast(width_), + static_cast(height_), 0.0f, + -1.0f, 1.0f); + viewMatrix_ = glm::mat4(1.0f); createDefaultCamera(); @@ -80,11 +73,19 @@ void Renderer::shutdown() { return; } - textBatcher_.reset(); - shapeBatcher_.reset(); - spriteBatcher_.reset(); - context_.reset(); - backend_.reset(); + if (spriteBatcher_) { + spriteBatcher_->shutdown(); + spriteBatcher_.reset(); + } + + if (renderQueue_) { + renderQueue_.reset(); + } + + if (device_) { + device_->shutdown(); + device_.reset(); + } activeCamera_.reset(); defaultCamera_.reset(); @@ -96,88 +97,271 @@ void Renderer::shutdown() { } void Renderer::beginFrame(const Color &clearColor) { - if (!initialized_) { + if (!initialized_ || !device_) { return; } - if (backend_) { - backend_->beginFrame(clearColor); - } + stats_.reset(); + device_->beginFrame(); + device_->resetStats(); - if (context_) { - context_->beginFrame(); - context_->clear(clearColor); - } + rhi::ColorValue cv(clearColor.r, clearColor.g, clearColor.b, clearColor.a); + device_->clearColor(cv); + + device_->setViewport(rhi::Viewport(0.0f, 0.0f, + static_cast(width_), + static_cast(height_))); } void Renderer::endFrame() { - if (!initialized_) { + if (!initialized_ || !device_) { return; } - if (spriteBatcher_) { - spriteBatcher_->end(); - } - if (shapeBatcher_) { - shapeBatcher_->end(); - } - if (textBatcher_) { - textBatcher_->end(); + if (inBatch_) { + endSpriteBatch(); } - if (context_) { - context_->endFrame(); - } - - if (backend_) { - backend_->endFrame(); - } + device_->endFrame(); } void Renderer::present() { - if (!initialized_) { + if (!initialized_ || !device_) { return; } - if (backend_) { - backend_->present(); - } - - if (context_) { - context_->present(); - } + device_->present(); } void Renderer::renderScene(Scene *scene) { if (!initialized_ || !scene) { return; } - - Camera *camera = activeCamera_ ? activeCamera_.get() : defaultCamera_.get(); - if (!camera) { - camera = scene->getActiveCamera(); - } - - renderScene(scene, camera); } -void Renderer::renderScene(Scene *scene, Camera *camera) { - if (!initialized_ || !scene) { +void Renderer::setViewport(int x, int y, int width, int height) { + if (!device_) { return; } - if (!camera) { - camera = defaultCamera_.get(); + device_->setViewport(rhi::Viewport( + static_cast(x), + static_cast(y), + static_cast(width), + static_cast(height))); +} + +void Renderer::setScissor(int x, int y, int width, int height) { + if (!device_) { + return; } - if (camera) { - camera->setViewportAdapter(&viewportAdapter_); - camera->applyViewportAdapter(); + device_->setScissorRect(rhi::ScissorRect(x, y, + static_cast(width), + static_cast(height))); +} + +void Renderer::setScissorEnabled(bool enabled) { + if (!device_) { + return; } - applyCameraTransform(camera); + device_->setScissorEnabled(enabled); +} - scene->renderScene(*backend_); +void Renderer::setProjectionMatrix(const glm::mat4 &matrix) { + projectionMatrix_ = matrix; +} + +void Renderer::setViewMatrix(const glm::mat4 &matrix) { + viewMatrix_ = matrix; +} + +void Renderer::setVSync(bool enabled) { + if (!device_) { + return; + } + + device_->setVSync(enabled); +} + +bool Renderer::isVSyncEnabled() const { + if (!device_) { + return false; + } + return device_->isVSyncEnabled(); +} + +void Renderer::drawSprite(Ptr texture, const Rect &destRect, + const Rect &srcRect, const Color &color, + float rotation, bool flipX, bool flipY) { + if (!initialized_ || !texture || !spriteBatcher_) { + return; + } + + stats_.spriteCount++; + + if (!inBatch_) { + beginSpriteBatch(); + } + + Vec2 anchor(0.5f, 0.5f); + spriteBatcher_->draw(texture, destRect, srcRect, color, rotation, anchor, blendState_); +} + +void Renderer::drawSprite(Ptr texture, + const glm::mat4 &transform, + const Rect &srcRect, const Color &color) { + if (!initialized_ || !texture || !spriteBatcher_) { + return; + } + + stats_.spriteCount++; + + if (!inBatch_) { + beginSpriteBatch(); + } + + spriteBatcher_->draw(texture, srcRect, transform, color, blendState_); +} + +void Renderer::draw9Slice(Ptr texture, const Rect &destRect, + const Rect &srcRect, const Vec2 &borderSize, + const Color &color) { + if (!initialized_ || !texture) { + return; + } + + stats_.spriteCount += 9; +} + +void Renderer::drawText(const std::string &text, const Vec2 &position, + float fontSize, const Color &color) { + if (!initialized_ || text.empty()) { + return; + } + + stats_.textCharCount += static_cast(text.length()); +} + +void Renderer::drawText(const std::u32string &text, const Vec2 &position, + float fontSize, const Color &color) { + if (!initialized_ || text.empty()) { + return; + } + + stats_.textCharCount += static_cast(text.length()); +} + +Vec2 Renderer::measureText(const std::string &text, float fontSize) { + float width = static_cast(text.length()) * fontSize * 0.6f; + return Vec2(width, fontSize); +} + +Vec2 Renderer::measureText(const std::u32string &text, float fontSize) { + float width = static_cast(text.length()) * fontSize * 0.6f; + return Vec2(width, fontSize); +} + +void Renderer::drawRect(const Rect &rect, const Color &color, float lineWidth) { + if (!initialized_) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::fillRect(const Rect &rect, const Color &color) { + if (!initialized_) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::drawCircle(const Vec2 ¢er, float radius, const Color &color, + float lineWidth, uint32_t segments) { + if (!initialized_) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::fillCircle(const Vec2 ¢er, float radius, const Color &color, + uint32_t segments) { + if (!initialized_) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::drawLine(const Vec2 &start, const Vec2 &end, const Color &color, + float lineWidth) { + if (!initialized_) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::drawPolygon(const Vec2 *points, size_t count, const Color &color, + float lineWidth) { + if (!initialized_ || !points || count < 3) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::fillPolygon(const Vec2 *points, size_t count, + const Color &color) { + if (!initialized_ || !points || count < 3) { + return; + } + + stats_.shapeCount++; +} + +void Renderer::beginSpriteBatch() { + if (!initialized_ || !spriteBatcher_ || inBatch_) { + return; + } + + inBatch_ = true; + spriteBatcher_->begin(projectionMatrix_ * viewMatrix_); +} + +void Renderer::endSpriteBatch() { + if (!initialized_ || !spriteBatcher_ || !inBatch_) { + return; + } + + spriteBatcher_->end(); + inBatch_ = false; + stats_.batchCount++; + stats_.drawCalls += spriteBatcher_->getDrawCallCount(); +} + +void Renderer::flush() { + if (!initialized_ || !spriteBatcher_) { + return; + } + + stats_.batchCount++; +} + +void Renderer::setSortKey(uint64_t key) { + sortKey_ = key; +} + +void Renderer::setLayer(int layer) { + layer_ = layer; +} + +void Renderer::setBlendMode(rhi::BlendState blend) { + blendState_ = blend; } void Renderer::setActiveCamera(Ptr camera) { activeCamera_ = camera; } @@ -186,88 +370,26 @@ Ptr Renderer::getActiveCamera() const { return activeCamera_ ? activeCamera_ : defaultCamera_; } -void Renderer::setViewport(int x, int y, int width, int height) { - if (context_) { - context_->setViewport(x, y, width, height); - } - if (backend_) { - backend_->setViewport(x, y, width, height); +rhi::GraphicsAPI Renderer::getAPI() const { + if (!device_) { + return rhi::GraphicsAPI::OpenGL; } + return device_->getAPI(); } -void Renderer::setScissor(int x, int y, int width, int height) { - if (context_) { - context_->setScissorRect(x, y, width, height); - } - if (backend_) { - backend_->setScissor(x, y, width, height); - } -} - -void Renderer::setScissorEnabled(bool enabled) { - if (context_) { - context_->setScissorEnabled(enabled); - } - if (backend_) { - backend_->setScissorEnabled(enabled); - } -} - -void Renderer::setVSync(bool enabled) { - if (context_) { - context_->setVSync(enabled); - } - if (backend_) { - backend_->setVSync(enabled); - } -} - -bool Renderer::isVSyncEnabled() const { - if (backend_) { - return backend_->isVSyncEnabled(); - } - if (context_) { - return context_->isVSyncEnabled(); - } - return false; -} - -rhi::RHIDevice *Renderer::getDevice() const { - if (backend_) { - return backend_->getDevice(); - } - if (context_) { - return context_->getDevice().get(); - } - return nullptr; +const rhi::DeviceCaps &Renderer::getCaps() const { + static rhi::DeviceCaps empty; + return device_ ? device_->getCaps() : empty; } const RenderStats &Renderer::getStats() const { - if (backend_) { - return backend_->getStats(); - } - if (context_) { - return context_->getStats(); - } - static RenderStats empty; - return empty; + return stats_; } void Renderer::resetStats() { - if (backend_) { - backend_->resetStats(); - } - if (context_) { - context_->resetStats(); - } - if (spriteBatcher_) { - spriteBatcher_->resetStats(); - } - if (shapeBatcher_) { - shapeBatcher_->resetStats(); - } - if (textBatcher_) { - textBatcher_->resetStats(); + stats_.reset(); + if (device_) { + device_->resetStats(); } } @@ -277,41 +399,6 @@ void Renderer::setConfig(const RendererConfig &config) { updateViewportAdapter(); } -bool Renderer::createBatchers() { - auto device = getDevice(); - if (!device) { - return false; - } - - auto devicePtr = context_ ? context_->getDevice() : nullptr; - if (!devicePtr) { - return false; - } - - SpriteBatcherConfig spriteConfig; - spriteConfig.maxBatchSize = config_.maxBatchSize; - spriteBatcher_ = makeUnique(spriteConfig); - if (!spriteBatcher_->init(devicePtr)) { - return false; - } - - ShapeBatcherConfig shapeConfig; - shapeConfig.maxBatchSize = config_.maxBatchSize / 2; - shapeBatcher_ = makeUnique(shapeConfig); - if (!shapeBatcher_->init(devicePtr)) { - return false; - } - - TextBatcherConfig textConfig; - textConfig.maxBatchSize = config_.maxBatchSize / 2; - textBatcher_ = makeUnique(textConfig); - if (!textBatcher_->init(devicePtr)) { - return false; - } - - return true; -} - void Renderer::createDefaultCamera() { float designWidth = viewportAdapter_.getDesignWidth(); float designHeight = viewportAdapter_.getDesignHeight(); @@ -326,30 +413,6 @@ void Renderer::updateViewportAdapter() { viewportAdapter_.update(width_, height_); } -void Renderer::applyCameraTransform(Camera *camera) { - if (!camera) { - return; - } - - camera->updateMatrices(); - glm::mat4 viewProj = camera->getViewProjectionMatrix(); - - if (spriteBatcher_) { - spriteBatcher_->setViewProjection(viewProj); - } - if (shapeBatcher_) { - shapeBatcher_->setViewProjection(viewProj); - } - if (textBatcher_) { - textBatcher_->setViewProjection(viewProj); - } - - if (backend_) { - backend_->setProjectionMatrix(camera->getProjectionMatrix()); - backend_->setViewMatrix(camera->getViewMatrix()); - } -} - Ptr Renderer::create(const RendererConfig &config) { return makePtr(config); } diff --git a/Extra2D/src/scene/node.cpp b/Extra2D/src/scene/node.cpp index a0af6a9..3826b37 100644 --- a/Extra2D/src/scene/node.cpp +++ b/Extra2D/src/scene/node.cpp @@ -568,9 +568,9 @@ void Node::onUpdate(float dt) { /** * @brief 渲染回调 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ -void Node::onRender(RenderBackend &renderer) { +void Node::onRender(Renderer &renderer) { if (!visible_) return; @@ -620,9 +620,9 @@ void Node::update(float dt) { onUpdate(dt); } /** * @brief 渲染节点 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ -void Node::render(RenderBackend &renderer) { +void Node::render(Renderer &renderer) { if (childrenOrderDirty_) { sortChildren(); } diff --git a/Extra2D/src/scene/scene.cpp b/Extra2D/src/scene/scene.cpp index 91fd0ae..7387723 100644 --- a/Extra2D/src/scene/scene.cpp +++ b/Extra2D/src/scene/scene.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -46,11 +46,11 @@ void Scene::setViewportSize(const Size &size) { /** * @brief 渲染场景 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 如果场景不可见则直接返回,否则开始帧渲染、渲染内容并结束帧 */ -void Scene::renderScene(RenderBackend &renderer) { +void Scene::renderScene(Renderer &renderer) { if (!isVisible()) return; @@ -61,11 +61,11 @@ void Scene::renderScene(RenderBackend &renderer) { /** * @brief 渲染场景内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 批量更新节点变换,开始精灵批处理并渲染 */ -void Scene::renderContent(RenderBackend &renderer) { +void Scene::renderContent(Renderer &renderer) { if (!isVisible()) return; diff --git a/Extra2D/src/scene/scene_manager.cpp b/Extra2D/src/scene/scene_manager.cpp index 7c725d8..0821c36 100644 --- a/Extra2D/src/scene/scene_manager.cpp +++ b/Extra2D/src/scene/scene_manager.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include @@ -565,11 +565,11 @@ void SceneManager::update(float dt) { /** * @brief 渲染当前场景 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 使用当前场景的背景色清除帧缓冲并渲染场景内容 */ -void SceneManager::render(RenderBackend &renderer) { +void SceneManager::render(Renderer &renderer) { Color clearColor = Colors::Black; if (!sceneStack_.empty()) { clearColor = sceneStack_.top()->getBackgroundColor(); diff --git a/Extra2D/src/scene/shape_node.cpp b/Extra2D/src/scene/shape_node.cpp index 14f4282..946acad 100644 --- a/Extra2D/src/scene/shape_node.cpp +++ b/Extra2D/src/scene/shape_node.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -259,13 +259,13 @@ Rect ShapeNode::getBounds() const { /** * @brief 绘制形状节点 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 根据形状类型调用相应的渲染方法进行绘制 * 注意:变换矩阵已由 Node::onRender 通过 pushTransform 应用, * 此处直接使用本地坐标即可。 */ -void ShapeNode::onDraw(RenderBackend &renderer) { +void ShapeNode::onDraw(Renderer &renderer) { if (points_.empty()) { return; } diff --git a/Extra2D/src/scene/sprite.cpp b/Extra2D/src/scene/sprite.cpp index 1190acd..54744c8 100644 --- a/Extra2D/src/scene/sprite.cpp +++ b/Extra2D/src/scene/sprite.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include @@ -122,11 +122,11 @@ Rect Sprite::getBounds() const { /** * @brief 绘制精灵 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 使用世界变换计算最终位置、缩放和旋转,然后绘制精灵 */ -void Sprite::onDraw(RenderBackend &renderer) { +void Sprite::onDraw(Renderer &renderer) { if (!texture_ || !texture_->isValid()) { return; } @@ -148,7 +148,7 @@ void Sprite::onDraw(RenderBackend &renderer) { float worldScaleY = glm::length(glm::vec2(worldTransform[1][0], worldTransform[1][1])); - // 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸 + // 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸 Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY); // Adjust source rect for flipping @@ -201,7 +201,7 @@ void Sprite::generateRenderCommand(std::vector &commands, auto anchor = getAnchor(); - // 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸 + // 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸 Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY); // 调整源矩形(翻转) diff --git a/Extra2D/src/scene/transition_box_scene.cpp b/Extra2D/src/scene/transition_box_scene.cpp index 2922faa..32de3d8 100644 --- a/Extra2D/src/scene/transition_box_scene.cpp +++ b/Extra2D/src/scene/transition_box_scene.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include @@ -49,11 +49,11 @@ void TransitionBoxScene::updateTransition(float dt) { /** * @brief 渲染过渡内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 先渲染新场景,然后绘制方块遮罩逐渐消失 */ -void TransitionBoxScene::renderContent(RenderBackend &renderer) { +void TransitionBoxScene::renderContent(Renderer &renderer) { auto &app = Application::get(); float windowWidth = static_cast(app.window()->width()); float windowHeight = static_cast(app.window()->height()); diff --git a/Extra2D/src/scene/transition_fade_scene.cpp b/Extra2D/src/scene/transition_fade_scene.cpp index 3f5d702..46d1268 100644 --- a/Extra2D/src/scene/transition_fade_scene.cpp +++ b/Extra2D/src/scene/transition_fade_scene.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ void TransitionFadeScene::updateTransition(float dt) { } } -void TransitionFadeScene::renderContent(RenderBackend &renderer) { +void TransitionFadeScene::renderContent(Renderer &renderer) { auto &app = Application::get(); float windowWidth = static_cast(app.window()->width()); float windowHeight = static_cast(app.window()->height()); diff --git a/Extra2D/src/scene/transition_flip_scene.cpp b/Extra2D/src/scene/transition_flip_scene.cpp index 3a1ab5e..2890b6c 100644 --- a/Extra2D/src/scene/transition_flip_scene.cpp +++ b/Extra2D/src/scene/transition_flip_scene.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include namespace extra2d { @@ -46,11 +46,11 @@ void TransitionFlipScene::updateTransition(float dt) { /** * @brief 渲染过渡内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 根据进度控制新旧场景的翻转角度 */ -void TransitionFlipScene::renderContent(RenderBackend &renderer) { +void TransitionFlipScene::renderContent(Renderer &renderer) { float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_ : -1.0f + (4.0f - 2.0f * progress_) * progress_; diff --git a/Extra2D/src/scene/transition_scale_scene.cpp b/Extra2D/src/scene/transition_scale_scene.cpp index a3b4248..4c27340 100644 --- a/Extra2D/src/scene/transition_scale_scene.cpp +++ b/Extra2D/src/scene/transition_scale_scene.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include namespace extra2d { @@ -42,11 +42,11 @@ void TransitionScaleScene::updateTransition(float dt) { /** * @brief 渲染过渡内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 根据进度控制新旧场景的缩放比例 */ -void TransitionScaleScene::renderContent(RenderBackend &renderer) { +void TransitionScaleScene::renderContent(Renderer &renderer) { float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_ : -1.0f + (4.0f - 2.0f * progress_) * progress_; diff --git a/Extra2D/src/scene/transition_scene.cpp b/Extra2D/src/scene/transition_scene.cpp index 825a33e..6fb6164 100644 --- a/Extra2D/src/scene/transition_scene.cpp +++ b/Extra2D/src/scene/transition_scene.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -115,20 +115,20 @@ void TransitionScene::cancel(bool immediate) { /** * @brief 渲染过渡内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 默认先渲染退出场景,再渲染进入场景 */ -void TransitionScene::renderContent(RenderBackend &renderer) { +void TransitionScene::renderContent(Renderer &renderer) { drawOutScene(renderer); drawInScene(renderer); } /** * @brief 绘制退出场景 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ -void TransitionScene::drawOutScene(RenderBackend &renderer) { +void TransitionScene::drawOutScene(Renderer &renderer) { if (outScene_) { outScene_->renderContent(renderer); } @@ -136,9 +136,9 @@ void TransitionScene::drawOutScene(RenderBackend &renderer) { /** * @brief 绘制进入场景 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 */ -void TransitionScene::drawInScene(RenderBackend &renderer) { +void TransitionScene::drawInScene(Renderer &renderer) { if (inScene_) { inScene_->renderContent(renderer); } diff --git a/Extra2D/src/scene/transition_slide_scene.cpp b/Extra2D/src/scene/transition_slide_scene.cpp index fd1c14f..d4a14b7 100644 --- a/Extra2D/src/scene/transition_slide_scene.cpp +++ b/Extra2D/src/scene/transition_slide_scene.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include namespace extra2d { @@ -45,11 +45,11 @@ void TransitionSlideScene::updateTransition(float dt) { /** * @brief 渲染过渡内容 - * @param renderer 渲染后端引用 + * @param renderer 渲染器引用 * * 根据进度控制新旧场景的滑动位置 */ -void TransitionSlideScene::renderContent(RenderBackend &renderer) { +void TransitionSlideScene::renderContent(Renderer &renderer) { float screenWidth = 800.0f; float screenHeight = 600.0f; diff --git a/Extra2D/src/services/scene_service.cpp b/Extra2D/src/services/scene_service.cpp index 854f1bd..921054a 100644 --- a/Extra2D/src/services/scene_service.cpp +++ b/Extra2D/src/services/scene_service.cpp @@ -1,4 +1,5 @@ #include +#include namespace extra2d { @@ -68,7 +69,7 @@ bool SceneService::hasScene(const std::string &name) const { return manager_.hasScene(name); } -void SceneService::render(RenderBackend &renderer) { +void SceneService::render(Renderer &renderer) { manager_.render(renderer); } diff --git a/xmake/engine.lua b/xmake/engine.lua index d3124ea..7538644 100644 --- a/xmake/engine.lua +++ b/xmake/engine.lua @@ -34,8 +34,6 @@ function define_extra2d_engine() -- 渲染后端源文件 local render_backend = get_render_backend() - -- 渲染后端工厂 - add_files("Extra2D/src/render/core/backend_factory.cpp") if render_backend == "vulkan" then add_files("Extra2D/src/render/backends/vulkan/*.cpp") add_defines("E2D_BACKEND_VULKAN")