refactor(render): 移除RenderBackend并重构渲染系统

将RenderBackend相关代码移除,重构渲染系统使用Renderer类
更新所有相关引用和接口,移除backend_factory和render_backend
调整SDL2和GLFW窗口实现,不再直接处理OpenGL上下文
优化GLRHIDevice以支持多种窗口后端创建OpenGL上下文
This commit is contained in:
ChestnutYueyue 2026-02-20 03:35:14 +08:00
parent d681f63905
commit 0999644a71
44 changed files with 1224 additions and 2497 deletions

View File

@ -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

View File

@ -22,13 +22,10 @@
#include <extra2d/platform/window_module.h>
// Render Core
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/core/render_command.h>
#include <extra2d/render/core/render_context.h>
#include <extra2d/render/core/render_queue.h>
#include <extra2d/render/core/render_stats.h>
#include <extra2d/render/core/render_module.h>
#include <extra2d/render/core/backend_factory.h>
// Render Camera
#include <extra2d/render/camera/camera.h>

View File

@ -1,302 +0,0 @@
#pragma once
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/rhi/rhi_device.h>
#include <extra2d/render/backends/opengl/gl_rhi_device.h>
#include <glm/mat4x4.hpp>
#include <stack>
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<rhi::RHITexture> 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<rhi::RHITexture> texture,
const glm::mat4 &transform,
const Rect &srcRect = Rect(0, 0, 1, 1),
const Color &color = Colors::White) override;
/**
* @brief
*/
void draw9Slice(Ptr<rhi::RHITexture> 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 &center, float radius, const Color &color,
float lineWidth = 1.0f, uint32_t segments = 32) override;
/**
* @brief
*/
void fillCircle(const Vec2 &center, 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<rhi::RHIDevice> 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

View File

@ -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<RHIPipeline> currentPipeline_;
Ptr<RHIShader> 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

View File

@ -1,182 +0,0 @@
#pragma once
#include <extra2d/core/types.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/rhi/rhi_types.h>
#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace extra2d {
/**
* @brief
*
*
* OpenGLVulkanDirectX
*/
class BackendFactory {
public:
/**
* @brief
*/
using BackendFn = std::function<UniquePtr<RenderBackend>()>;
/**
* @brief
*/
struct BackendInfo {
std::string name;
BackendFn createFn;
std::vector<std::string> 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<std::string>& 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<RenderBackend> createBackend(const std::string& name);
/**
* @brief
*
*
* @return nullptr
*/
static UniquePtr<RenderBackend> createDefaultBackend();
/**
* @brief
* @param windowBackend
* @return nullptr
*/
static UniquePtr<RenderBackend> createBackendForWindow(const std::string& windowBackend);
/**
* @brief API
* @param api API
* @return nullptr
*/
static UniquePtr<RenderBackend> createBackendForAPI(rhi::GraphicsAPI api);
/**
* @brief
* @param name
*/
static bool hasBackend(const std::string& name);
/**
* @brief
*/
static std::vector<std::string> getBackendNames();
/**
* @brief
* @param name
* @return nullptr
*/
static const BackendInfo* getBackendInfo(const std::string& name);
/**
* @brief
*/
static std::vector<BackendInfo> getAllBackendInfos();
/**
* @brief
* @param windowBackend
*/
static std::vector<std::string> 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<std::string, BackendInfo>& getRegistry();
static std::mutex& getMutex();
static std::string& getDefaultName();
};
/**
* @brief
*
*
*/
class BackendRegistrar {
public:
BackendRegistrar(const std::string& name,
BackendFactory::BackendFn backend,
const std::vector<std::string>& 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<BackendClass>(); \
}, \
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<BackendClass>(); \
}, \
windowBackends, api, desc, prio)
} // namespace extra2d

View File

@ -1,324 +0,0 @@
#pragma once
#include <extra2d/core/color.h>
#include <extra2d/core/math_types.h>
#include <extra2d/core/types.h>
#include <extra2d/render/rhi/rhi_device.h>
#include <extra2d/render/rhi/rhi_types.h>
#include <glm/mat4x4.hpp>
#include <string>
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<rhi::RHITexture> 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<rhi::RHITexture> texture,
const glm::mat4 &transform,
const Rect &srcRect = Rect(0, 0, 1, 1),
const Color &color = Colors::White) = 0;
/**
* @brief
*/
virtual void draw9Slice(Ptr<rhi::RHITexture> 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 &center, float radius, const Color &color,
float lineWidth = 1.0f, uint32_t segments = 32) = 0;
/**
* @brief
*/
virtual void fillCircle(const Vec2 &center, 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

View File

@ -3,7 +3,6 @@
#include <extra2d/core/color.h>
#include <extra2d/core/math_types.h>
#include <extra2d/core/types.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/core/render_queue.h>
#include <extra2d/render/rhi/rhi_device.h>
#include <extra2d/render/rhi/rhi_types.h>
@ -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<rhi::RHIDevice> device_;
IWindow *window_;
RenderQueue queue_;
RenderStats stats_;
RenderContextConfig config_;
std::stack<glm::mat4> transformStack_;

View File

@ -2,7 +2,6 @@
#include <extra2d/core/module.h>
#include <extra2d/core/types.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/rhi/rhi_types.h>
#include <functional>

View File

@ -1,22 +1,46 @@
#pragma once
#include <extra2d/core/color.h>
#include <extra2d/core/math_types.h>
#include <extra2d/core/module.h>
#include <extra2d/core/types.h>
#include <extra2d/render/batch/shape_batcher.h>
#include <extra2d/render/batch/sprite_batcher.h>
#include <extra2d/render/batch/text_batcher.h>
#include <extra2d/render/camera/camera.h>
#include <extra2d/render/camera/viewport_adapter.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/core/render_context.h>
#include <extra2d/render/core/render_queue.h>
#include <extra2d/render/rhi/rhi_device.h>
#include <extra2d/render/rhi/rhi_types.h>
#include <glm/mat4x4.hpp>
#include <string>
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<rhi::RHITexture> 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<rhi::RHITexture> texture,
const glm::mat4 &transform,
const Rect &srcRect = Rect(0, 0, 1, 1),
const Color &color = Colors::White);
/**
* @brief
*/
void draw9Slice(Ptr<rhi::RHITexture> 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 &center, float radius, const Color &color,
float lineWidth = 1.0f, uint32_t segments = 32);
/**
* @brief
*/
void fillCircle(const Vec2 &center, 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<Renderer> 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<RenderContext> context_;
UniquePtr<RenderBackend> backend_;
Ptr<rhi::RHIDevice> device_;
UniquePtr<SpriteBatcher> spriteBatcher_;
UniquePtr<ShapeBatcher> shapeBatcher_;
UniquePtr<TextBatcher> textBatcher_;
UniquePtr<RenderQueue> renderQueue_;
ViewportAdapter viewportAdapter_;
Ptr<Camera> activeCamera_;
Ptr<Camera> 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

View File

@ -9,7 +9,6 @@
#include <extra2d/render/rhi/rhi_types.h>
#include <glm/mat4x4.hpp>
#include <string>
#include <vector>
namespace extra2d {
@ -21,39 +20,39 @@ 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;
};
/**
@ -64,390 +63,409 @@ struct DeviceStats {
*/
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<RHIBuffer> createBuffer(const BufferDesc& desc) = 0;
/**
* @brief
*/
virtual Ptr<RHIVertexBuffer> createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
const void* data = nullptr) = 0;
/**
* @brief
*/
virtual Ptr<RHIIndexBuffer> createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
const void* data = nullptr) = 0;
/**
* @brief Uniform
*/
virtual Ptr<RHIUniformBuffer> createUniformBuffer(size_t size, BufferUsage usage = BufferUsage::Dynamic) = 0;
// ========================================================================
// 资源创建 - 纹理
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHITexture> createTexture(const TextureDesc& desc) = 0;
/**
* @brief 2D
*/
virtual Ptr<RHITexture> createTexture2D(uint32_t width, uint32_t height, Format format,
const void* data = nullptr) = 0;
/**
* @brief
*/
virtual Ptr<RHISampler> createSampler(const SamplerDesc& desc) = 0;
/**
* @brief
*/
virtual Ptr<RHITextureView> createTextureView(Ptr<RHITexture> texture,
const TextureViewDesc& desc) = 0;
// ========================================================================
// 资源创建 - 着色器
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHIShader> createShader(const ShaderDesc& desc) = 0;
/**
* @brief
*/
virtual Ptr<RHIShader> createShaderFromSource(const std::string& name,
const std::string& vertexSource,
const std::string& fragmentSource) = 0;
/**
* @brief
*/
virtual Ptr<RHIShader> createShaderFromFile(const std::string& vertexPath,
const std::string& fragmentPath) = 0;
// ========================================================================
// 资源创建 - 管线
// ========================================================================
/**
* @brief 线
*/
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc& desc, Ptr<RHIShader> shader) = 0;
/**
* @brief 使线
*/
virtual Ptr<RHIPipeline> createPipeline(const PipelineBuilder& builder) = 0;
// ========================================================================
// 资源创建 - 帧缓冲
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHIFramebuffer> createFramebuffer(const FramebufferDesc& desc) = 0;
/**
* @brief 使
*/
virtual Ptr<RHIFramebuffer> 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<RHIPipeline> pipeline) = 0;
/**
* @brief
*/
virtual void setShader(Ptr<RHIShader> shader) = 0;
/**
* @brief
*/
virtual void setVertexBuffer(uint32_t slot, Ptr<RHIBuffer> buffer, uint32_t offset = 0) = 0;
/**
* @brief
*/
virtual void setIndexBuffer(Ptr<RHIBuffer> buffer, IndexFormat format) = 0;
/**
* @brief
*/
virtual void setTexture(uint32_t slot, Ptr<RHITexture> texture, Ptr<RHISampler> sampler = nullptr) = 0;
/**
* @brief Uniform
*/
virtual void setUniformBuffer(uint32_t slot, Ptr<RHIBuffer> buffer) = 0;
/**
* @brief
*/
virtual void setFramebuffer(Ptr<RHIFramebuffer> 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<RHIBuffer> indirectBuffer, size_t offset) = 0;
/**
* @brief
*/
virtual void drawIndexedIndirect(Ptr<RHIBuffer> 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<RHIDevice> 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<RHIBuffer> createBuffer(const BufferDesc &desc) = 0;
/**
* @brief
*/
virtual Ptr<RHIVertexBuffer>
createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
const void *data = nullptr) = 0;
/**
* @brief
*/
virtual Ptr<RHIIndexBuffer>
createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
const void *data = nullptr) = 0;
/**
* @brief Uniform
*/
virtual Ptr<RHIUniformBuffer>
createUniformBuffer(size_t size,
BufferUsage usage = BufferUsage::Dynamic) = 0;
// ========================================================================
// 资源创建 - 纹理
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHITexture> createTexture(const TextureDesc &desc) = 0;
/**
* @brief 2D
*/
virtual Ptr<RHITexture> createTexture2D(uint32_t width, uint32_t height,
Format format,
const void *data = nullptr) = 0;
/**
* @brief
*/
virtual Ptr<RHISampler> createSampler(const SamplerDesc &desc) = 0;
/**
* @brief
*/
virtual Ptr<RHITextureView>
createTextureView(Ptr<RHITexture> texture, const TextureViewDesc &desc) = 0;
// ========================================================================
// 资源创建 - 着色器
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHIShader> createShader(const ShaderDesc &desc) = 0;
/**
* @brief
*/
virtual Ptr<RHIShader>
createShaderFromSource(const std::string &name,
const std::string &vertexSource,
const std::string &fragmentSource) = 0;
/**
* @brief
*/
virtual Ptr<RHIShader>
createShaderFromFile(const std::string &vertexPath,
const std::string &fragmentPath) = 0;
// ========================================================================
// 资源创建 - 管线
// ========================================================================
/**
* @brief 线
*/
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc &desc,
Ptr<RHIShader> shader) = 0;
/**
* @brief 使线
*/
virtual Ptr<RHIPipeline> createPipeline(const PipelineBuilder &builder) = 0;
// ========================================================================
// 资源创建 - 帧缓冲
// ========================================================================
/**
* @brief
*/
virtual Ptr<RHIFramebuffer>
createFramebuffer(const FramebufferDesc &desc) = 0;
/**
* @brief 使
*/
virtual Ptr<RHIFramebuffer>
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<RHIPipeline> pipeline) = 0;
/**
* @brief
*/
virtual void setShader(Ptr<RHIShader> shader) = 0;
/**
* @brief
*/
virtual void setVertexBuffer(uint32_t slot, Ptr<RHIBuffer> buffer,
uint32_t offset = 0) = 0;
/**
* @brief
*/
virtual void setIndexBuffer(Ptr<RHIBuffer> buffer, IndexFormat format) = 0;
/**
* @brief
*/
virtual void setTexture(uint32_t slot, Ptr<RHITexture> texture,
Ptr<RHISampler> sampler = nullptr) = 0;
/**
* @brief Uniform
*/
virtual void setUniformBuffer(uint32_t slot, Ptr<RHIBuffer> buffer) = 0;
/**
* @brief
*/
virtual void setFramebuffer(Ptr<RHIFramebuffer> 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<RHIBuffer> indirectBuffer, size_t offset) = 0;
/**
* @brief
*/
virtual void drawIndexedIndirect(Ptr<RHIBuffer> 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<RHIDevice> create(GraphicsAPI api);
};
/**
@ -455,26 +473,26 @@ public:
*/
class RHIDeviceScope {
public:
explicit RHIDeviceScope(Ptr<RHIDevice> device) : device_(device) {
if (device_) {
device_->beginFrame();
}
explicit RHIDeviceScope(Ptr<RHIDevice> 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<RHIDevice> device_;
Ptr<RHIDevice> device_;
};
} // namespace rhi

View File

@ -4,7 +4,7 @@
#include <extra2d/core/math_types.h>
#include <extra2d/core/types.h>
#include <extra2d/event/event_dispatcher.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/scene/component.h>
#include <extra2d/scene/components/transform_component.h>
#include <memory>
@ -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

View File

@ -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

View File

@ -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<RenderCommand> &commands);
// ------------------------------------------------------------------------

View File

@ -84,7 +84,7 @@ public:
Rect getBounds() const override;
protected:
void onDraw(RenderBackend &renderer) override;
void onDraw(Renderer &renderer) override;
void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) override;

View File

@ -40,7 +40,7 @@ public:
Rect getBounds() const override;
protected:
void onDraw(RenderBackend &renderer) override;
void onDraw(Renderer &renderer) override;
void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) override;

View File

@ -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:

View File

@ -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:
/**

View File

@ -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:

View File

@ -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;
};

View File

@ -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

View File

@ -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:

View File

@ -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<RenderCommand>& 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<RenderCommand>& commands) override;
bool isTransitioning() const override;

View File

@ -5,7 +5,6 @@
#include <extra2d/platform/iwindow.h>
#include <extra2d/platform/window_module.h>
#include <extra2d/render/camera/viewport_adapter.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/core/render_module.h>
#include <extra2d/render/renderer.h>
#include <extra2d/services/camera_service.h>
@ -209,8 +208,8 @@ void Application::render() {
}
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
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<RenderModule>();
return renderMod ? (renderMod->getRenderer() ? renderMod->getRenderer()->getBackend() : nullptr) : nullptr;
return renderMod ? renderMod->getRenderer() : nullptr;
}
IInput *Application::input() {

View File

@ -5,7 +5,6 @@
#include <extra2d/platform/keys.h>
#include <extra2d/services/event_service.h>
#include <extra2d/services/logger_service.h>
#include <glad/glad.h>
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) {

View File

@ -5,7 +5,6 @@
#include <extra2d/platform/keys.h>
#include <extra2d/services/event_service.h>
#include <extra2d/services/logger_service.h>
#include <glad/glad.h>
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<float>(dw) / width_ : 1.0f;
scaleY_ = dh > 0 ? static_cast<float>(dh) / height_ : 1.0f;
scaleX_ = 1.0f;
scaleY_ = 1.0f;
}
}

View File

@ -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;

View File

@ -1,521 +0,0 @@
#include <extra2d/render/backends/opengl/gl_render_backend.h>
#include <extra2d/platform/iwindow.h>
#include <glm/gtc/matrix_transform.hpp>
#include <cmath>
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<float>(width_),
static_cast<float>(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<float>(width_),
static_cast<float>(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<float>(x),
static_cast<float>(y),
static_cast<float>(width),
static_cast<float>(height)));
}
/**
* @brief
*/
void GLRenderBackend::setScissor(int x, int y, int width, int height) {
if (!isValid()) {
return;
}
device_->setScissorRect(rhi::ScissorRect(x, y,
static_cast<uint32_t>(width),
static_cast<uint32_t>(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<rhi::RHITexture> 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<rhi::RHITexture> texture,
const glm::mat4 &transform,
const Rect &srcRect, const Color &color) {
if (!isValid() || !texture) {
return;
}
stats_.spriteCount++;
stats_.drawCalls++;
}
/**
* @brief
*/
void GLRenderBackend::draw9Slice(Ptr<rhi::RHITexture> 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<uint32_t>(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<uint32_t>(text.length());
stats_.drawCalls++;
}
/**
* @brief
*/
Vec2 GLRenderBackend::measureText(const std::string &text, float fontSize) {
float width = static_cast<float>(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<float>(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 &center, float radius, const Color &color,
float lineWidth, uint32_t segments) {
if (!isValid()) {
return;
}
stats_.shapeCount++;
stats_.drawCalls++;
}
/**
* @brief
*/
void GLRenderBackend::fillCircle(const Vec2 &center, 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

View File

@ -6,6 +6,15 @@
#include <extra2d/render/backends/opengl/gl_context.h>
#include <extra2d/services/logger_service.h>
#include <extra2d/platform/iwindow.h>
#ifdef E2D_BACKEND_GLFW
#include <GLFW/glfw3.h>
#endif
#ifdef E2D_BACKEND_SDL2
#include <SDL.h>
#endif
#include <fstream>
#include <sstream>
@ -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<SDL_GLContext>(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<GLFWwindow*>(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<SDL_Window*>(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*>(glfwWindow_));
}
#endif
#ifdef E2D_BACKEND_SDL2
if (contextType_ == GLContextType::SDL2 && sdlWindow_) {
SDL_GL_SwapWindow(static_cast<SDL_Window*>(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) {

View File

@ -1,262 +0,0 @@
#include <extra2d/render/core/backend_factory.h>
#include <extra2d/render/backends/opengl/gl_render_backend.h>
#include <algorithm>
namespace extra2d {
std::unordered_map<std::string, BackendFactory::BackendInfo>& BackendFactory::getRegistry() {
static std::unordered_map<std::string, BackendInfo> 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<std::string>& windowBackends,
rhi::GraphicsAPI api,
const std::string& description,
int priority) {
std::lock_guard<std::mutex> 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<std::mutex> lock(getMutex());
getRegistry().erase(name);
}
/**
* @brief
*/
UniquePtr<RenderBackend> BackendFactory::createBackend(const std::string& name) {
std::lock_guard<std::mutex> 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<RenderBackend> BackendFactory::createDefaultBackend() {
std::lock_guard<std::mutex> lock(getMutex());
auto& registry = getRegistry();
if (registry.empty()) {
return makeUnique<GLRenderBackend>();
}
std::string defaultName = getDefaultName();
auto it = registry.find(defaultName);
if (it != registry.end() && it->second.createFn) {
return it->second.createFn();
}
std::vector<BackendInfo*> 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<GLRenderBackend>();
}
/**
* @brief
*/
UniquePtr<RenderBackend> BackendFactory::createBackendForWindow(const std::string& windowBackend) {
std::lock_guard<std::mutex> lock(getMutex());
auto& registry = getRegistry();
std::vector<BackendInfo*> 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<GLRenderBackend>();
}
/**
* @brief API
*/
UniquePtr<RenderBackend> BackendFactory::createBackendForAPI(rhi::GraphicsAPI api) {
std::lock_guard<std::mutex> lock(getMutex());
auto& registry = getRegistry();
std::vector<BackendInfo*> 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<GLRenderBackend>();
}
return nullptr;
}
/**
* @brief
*/
bool BackendFactory::hasBackend(const std::string& name) {
std::lock_guard<std::mutex> lock(getMutex());
return getRegistry().find(name) != getRegistry().end();
}
/**
* @brief
*/
std::vector<std::string> BackendFactory::getBackendNames() {
std::lock_guard<std::mutex> lock(getMutex());
std::vector<std::string> 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<std::mutex> lock(getMutex());
auto& registry = getRegistry();
auto it = registry.find(name);
if (it != registry.end()) {
return &it->second;
}
return nullptr;
}
/**
* @brief
*/
std::vector<BackendFactory::BackendInfo> BackendFactory::getAllBackendInfos() {
std::lock_guard<std::mutex> lock(getMutex());
std::vector<BackendInfo> infos;
for (const auto& pair : getRegistry()) {
infos.push_back(pair.second);
}
return infos;
}
/**
* @brief
*/
std::vector<std::string> BackendFactory::getCompatibleBackends(const std::string& windowBackend) {
std::lock_guard<std::mutex> lock(getMutex());
std::vector<std::string> 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<std::mutex> 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<RenderBackend> {
return makeUnique<GLRenderBackend>();
},
{"sdl2", "glfw"},
rhi::GraphicsAPI::OpenGL,
"OpenGL 4.5 Core Profile",
100
);
}
} // namespace extra2d

View File

@ -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

View File

@ -1,19 +1,24 @@
#include <extra2d/render/renderer.h>
#include <extra2d/platform/iwindow.h>
#include <extra2d/render/core/backend_factory.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/resources/shader_manager.h>
#include <extra2d/scene/scene.h>
#include <glm/gtc/matrix_transform.hpp>
#include <cmath>
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<RenderContext>(contextConfig);
if (!context_->init(window, config.api)) {
spriteBatcher_ = makeUnique<SpriteBatcher>();
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<RenderQueue>();
if (!createBatchers()) {
return false;
}
projectionMatrix_ = glm::ortho(0.0f, static_cast<float>(width_),
static_cast<float>(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<float>(width_),
static_cast<float>(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<float>(x),
static_cast<float>(y),
static_cast<float>(width),
static_cast<float>(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<uint32_t>(width),
static_cast<uint32_t>(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<rhi::RHITexture> 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<rhi::RHITexture> 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<rhi::RHITexture> 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<uint32_t>(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<uint32_t>(text.length());
}
Vec2 Renderer::measureText(const std::string &text, float fontSize) {
float width = static_cast<float>(text.length()) * fontSize * 0.6f;
return Vec2(width, fontSize);
}
Vec2 Renderer::measureText(const std::u32string &text, float fontSize) {
float width = static_cast<float>(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 &center, float radius, const Color &color,
float lineWidth, uint32_t segments) {
if (!initialized_) {
return;
}
stats_.shapeCount++;
}
void Renderer::fillCircle(const Vec2 &center, 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> camera) { activeCamera_ = camera; }
@ -186,88 +370,26 @@ Ptr<Camera> 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<SpriteBatcher>(spriteConfig);
if (!spriteBatcher_->init(devicePtr)) {
return false;
}
ShapeBatcherConfig shapeConfig;
shapeConfig.maxBatchSize = config_.maxBatchSize / 2;
shapeBatcher_ = makeUnique<ShapeBatcher>(shapeConfig);
if (!shapeBatcher_->init(devicePtr)) {
return false;
}
TextBatcherConfig textConfig;
textConfig.maxBatchSize = config_.maxBatchSize / 2;
textBatcher_ = makeUnique<TextBatcher>(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> Renderer::create(const RendererConfig &config) {
return makePtr<Renderer>(config);
}

View File

@ -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();
}

View File

@ -1,5 +1,5 @@
#include <extra2d/core/service_locator.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/render/core/render_command.h>
#include <extra2d/render/core/render_queue.h>
#include <extra2d/scene/scene.h>
@ -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;

View File

@ -1,7 +1,7 @@
#include <algorithm>
#include <extra2d/app/application.h>
#include <extra2d/core/service_locator.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/render/core/render_command.h>
#include <extra2d/platform/iinput.h>
#include <extra2d/scene/scene_manager.h>
@ -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();

View File

@ -1,6 +1,6 @@
#include <algorithm>
#include <cmath>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/render/core/render_command.h>
#include <extra2d/scene/shape_node.h>
#include <limits>
@ -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;
}

View File

@ -1,6 +1,6 @@
#include <algorithm>
#include <cmath>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/render/core/render_command.h>
#include <extra2d/scene/sprite.h>
@ -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<RenderCommand> &commands,
auto anchor = getAnchor();
// 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸
// 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
// 调整源矩形(翻转)

View File

@ -1,7 +1,7 @@
#include <extra2d/scene/transition_box_scene.h>
#include <extra2d/app/application.h>
#include <extra2d/core/color.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/platform/iwindow.h>
#include <algorithm>
#include <glm/gtc/matrix_transform.hpp>
@ -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<float>(app.window()->width());
float windowHeight = static_cast<float>(app.window()->height());

View File

@ -1,6 +1,6 @@
#include <extra2d/app/application.h>
#include <extra2d/core/service_locator.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/platform/iwindow.h>
#include <extra2d/scene/transition_fade_scene.h>
#include <extra2d/services/logger_service.h>
@ -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<float>(app.window()->width());
float windowHeight = static_cast<float>(app.window()->height());

View File

@ -1,7 +1,7 @@
#include <extra2d/scene/transition_flip_scene.h>
#include <extra2d/core/math_types.h>
#include <extra2d/render/camera/camera.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
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_;

View File

@ -1,6 +1,6 @@
#include <extra2d/scene/transition_scale_scene.h>
#include <extra2d/render/camera/camera.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <algorithm>
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_;

View File

@ -1,5 +1,5 @@
#include <extra2d/core/service_locator.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <extra2d/scene/transition_scene.h>
#include <extra2d/services/logger_service.h>
@ -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);
}

View File

@ -1,6 +1,6 @@
#include <extra2d/scene/transition_slide_scene.h>
#include <extra2d/render/camera/camera.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/render/renderer.h>
#include <algorithm>
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;

View File

@ -1,4 +1,5 @@
#include <extra2d/services/scene_service.h>
#include <extra2d/render/renderer.h>
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);
}

View File

@ -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")