refactor(render): 移除RenderBackend并重构渲染系统
将RenderBackend相关代码移除,重构渲染系统使用Renderer类 更新所有相关引用和接口,移除backend_factory和render_backend 调整SDL2和GLFW窗口实现,不再直接处理OpenGL上下文 优化GLRHIDevice以支持多种窗口后端创建OpenGL上下文
This commit is contained in:
parent
d681f63905
commit
0999644a71
|
|
@ -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 获取输入
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 ¢er, float radius, const Color &color,
|
||||
float lineWidth = 1.0f, uint32_t segments = 32) override;
|
||||
|
||||
/**
|
||||
* @brief 绘制填充圆形
|
||||
*/
|
||||
void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||
uint32_t segments = 32) override;
|
||||
|
||||
/**
|
||||
* @brief 绘制线段
|
||||
*/
|
||||
void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||
float lineWidth = 1.0f) override;
|
||||
|
||||
/**
|
||||
* @brief 绘制多边形
|
||||
*/
|
||||
void drawPolygon(const Vec2 *points, size_t count, const Color &color,
|
||||
float lineWidth = 1.0f) override;
|
||||
|
||||
/**
|
||||
* @brief 绘制填充多边形
|
||||
*/
|
||||
void fillPolygon(const Vec2 *points, size_t count,
|
||||
const Color &color) override;
|
||||
|
||||
// ========================================================================
|
||||
// 批处理控制
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 开始精灵批处理
|
||||
*/
|
||||
void beginSpriteBatch() override;
|
||||
|
||||
/**
|
||||
* @brief 结束精灵批处理
|
||||
*/
|
||||
void endSpriteBatch() override;
|
||||
|
||||
/**
|
||||
* @brief 刷新当前批次
|
||||
*/
|
||||
void flush() override;
|
||||
|
||||
/**
|
||||
* @brief 设置渲染排序键
|
||||
*/
|
||||
void setSortKey(uint64_t key) override;
|
||||
|
||||
/**
|
||||
* @brief 设置渲染层
|
||||
*/
|
||||
void setLayer(int layer) override;
|
||||
|
||||
/**
|
||||
* @brief 设置混合模式
|
||||
*/
|
||||
void setBlendMode(rhi::BlendState blend) override;
|
||||
|
||||
// ========================================================================
|
||||
// 访问器
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 获取 RHI 设备
|
||||
*/
|
||||
rhi::RHIDevice *getDevice() const override;
|
||||
|
||||
/**
|
||||
* @brief 获取窗口宽度
|
||||
*/
|
||||
int getWidth() const override;
|
||||
|
||||
/**
|
||||
* @brief 获取窗口高度
|
||||
*/
|
||||
int getHeight() const override;
|
||||
|
||||
/**
|
||||
* @brief 获取渲染统计
|
||||
*/
|
||||
const RenderStats &getStats() const override;
|
||||
|
||||
/**
|
||||
* @brief 重置渲染统计
|
||||
*/
|
||||
void resetStats() override;
|
||||
|
||||
/**
|
||||
* @brief 获取图形 API 类型
|
||||
*/
|
||||
rhi::GraphicsAPI getAPI() const override;
|
||||
|
||||
/**
|
||||
* @brief 获取设备能力
|
||||
*/
|
||||
const rhi::DeviceCaps &getCaps() const override;
|
||||
|
||||
private:
|
||||
bool initialized_ = false;
|
||||
IWindow *window_ = nullptr;
|
||||
RenderBackendConfig config_;
|
||||
RenderStats stats_;
|
||||
|
||||
Ptr<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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 渲染后端工厂
|
||||
*
|
||||
* 管理渲染后端的注册和创建
|
||||
* 支持多后端(OpenGL、Vulkan、DirectX 等)
|
||||
*/
|
||||
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
|
||||
|
|
@ -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 ¢er, float radius, const Color &color,
|
||||
float lineWidth = 1.0f, uint32_t segments = 32) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绘制填充圆形
|
||||
*/
|
||||
virtual void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||
uint32_t segments = 32) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绘制线段
|
||||
*/
|
||||
virtual void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||
float lineWidth = 1.0f) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绘制多边形
|
||||
*/
|
||||
virtual void drawPolygon(const Vec2 *points, size_t count, const Color &color,
|
||||
float lineWidth = 1.0f) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绘制填充多边形
|
||||
*/
|
||||
virtual void fillPolygon(const Vec2 *points, size_t count,
|
||||
const Color &color) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 批处理控制
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 开始精灵批处理
|
||||
*/
|
||||
virtual void beginSpriteBatch() = 0;
|
||||
|
||||
/**
|
||||
* @brief 结束精灵批处理
|
||||
*/
|
||||
virtual void endSpriteBatch() = 0;
|
||||
|
||||
/**
|
||||
* @brief 刷新当前批次
|
||||
*/
|
||||
virtual void flush() = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置渲染排序键
|
||||
*/
|
||||
virtual void setSortKey(uint64_t key) = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置渲染层
|
||||
*/
|
||||
virtual void setLayer(int layer) = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置混合模式
|
||||
*/
|
||||
virtual void setBlendMode(rhi::BlendState blend) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 访问器
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 获取 RHI 设备
|
||||
*/
|
||||
virtual rhi::RHIDevice *getDevice() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取窗口宽度
|
||||
*/
|
||||
virtual int getWidth() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取窗口高度
|
||||
*/
|
||||
virtual int getHeight() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取渲染统计
|
||||
*/
|
||||
virtual const RenderStats &getStats() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 重置渲染统计
|
||||
*/
|
||||
virtual void resetStats() = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取图形 API 类型
|
||||
*/
|
||||
virtual rhi::GraphicsAPI getAPI() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取设备能力
|
||||
*/
|
||||
virtual const rhi::DeviceCaps &getCaps() const = 0;
|
||||
};
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ¢er, float radius, const Color &color,
|
||||
float lineWidth = 1.0f, uint32_t segments = 32);
|
||||
|
||||
/**
|
||||
* @brief 绘制填充圆形
|
||||
*/
|
||||
void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||
uint32_t segments = 32);
|
||||
|
||||
/**
|
||||
* @brief 绘制线段
|
||||
*/
|
||||
void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||
float lineWidth = 1.0f);
|
||||
|
||||
/**
|
||||
* @brief 绘制多边形
|
||||
*/
|
||||
void drawPolygon(const Vec2 *points, size_t count, const Color &color,
|
||||
float lineWidth = 1.0f);
|
||||
|
||||
/**
|
||||
* @brief 绘制填充多边形
|
||||
*/
|
||||
void fillPolygon(const Vec2 *points, size_t count,
|
||||
const Color &color);
|
||||
|
||||
// ========================================================================
|
||||
// 批处理控制
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 开始精灵批处理
|
||||
*/
|
||||
void beginSpriteBatch();
|
||||
|
||||
/**
|
||||
* @brief 结束精灵批处理
|
||||
*/
|
||||
void endSpriteBatch();
|
||||
|
||||
/**
|
||||
* @brief 刷新当前批次
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* @brief 设置渲染排序键
|
||||
*/
|
||||
void setSortKey(uint64_t key);
|
||||
|
||||
/**
|
||||
* @brief 设置渲染层
|
||||
*/
|
||||
void setLayer(int layer);
|
||||
|
||||
/**
|
||||
* @brief 设置混合模式
|
||||
*/
|
||||
void setBlendMode(rhi::BlendState blend);
|
||||
|
||||
// ========================================================================
|
||||
// 相机系统
|
||||
|
|
@ -162,71 +365,23 @@ public:
|
|||
const ViewportAdapter &getViewportAdapter() const { return viewportAdapter_; }
|
||||
|
||||
// ========================================================================
|
||||
// 渲染状态
|
||||
// RHI 设备访问
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 设置视口
|
||||
*/
|
||||
void setViewport(int x, int y, int width, int height);
|
||||
|
||||
/**
|
||||
* @brief 设置裁剪区域
|
||||
*/
|
||||
void setScissor(int x, int y, int width, int height);
|
||||
|
||||
/**
|
||||
* @brief 启用/禁用裁剪测试
|
||||
*/
|
||||
void setScissorEnabled(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief 设置垂直同步
|
||||
*/
|
||||
void setVSync(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief 获取垂直同步状态
|
||||
*/
|
||||
bool isVSyncEnabled() const;
|
||||
|
||||
// ========================================================================
|
||||
// 批处理器访问
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 获取精灵批处理器
|
||||
*/
|
||||
SpriteBatcher *getSpriteBatcher() const { return spriteBatcher_.get(); }
|
||||
|
||||
/**
|
||||
* @brief 获取形状批处理器
|
||||
*/
|
||||
ShapeBatcher *getShapeBatcher() const { return shapeBatcher_.get(); }
|
||||
|
||||
/**
|
||||
* @brief 获取文本批处理器
|
||||
*/
|
||||
TextBatcher *getTextBatcher() const { return textBatcher_.get(); }
|
||||
|
||||
// ========================================================================
|
||||
// 渲染上下文
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief 获取渲染上下文
|
||||
*/
|
||||
RenderContext *getContext() const { return context_.get(); }
|
||||
|
||||
/**
|
||||
* @brief 获取渲染后端
|
||||
*/
|
||||
RenderBackend *getBackend() const { return backend_.get(); }
|
||||
|
||||
/**
|
||||
* @brief 获取 RHI 设备
|
||||
*/
|
||||
rhi::RHIDevice *getDevice() const;
|
||||
rhi::RHIDevice *getDevice() const { return device_.get(); }
|
||||
|
||||
/**
|
||||
* @brief 获取图形 API 类型
|
||||
*/
|
||||
rhi::GraphicsAPI getAPI() const;
|
||||
|
||||
/**
|
||||
* @brief 获取设备能力
|
||||
*/
|
||||
const rhi::DeviceCaps &getCaps() const;
|
||||
|
||||
// ========================================================================
|
||||
// 统计信息
|
||||
|
|
@ -285,11 +440,6 @@ public:
|
|||
static Ptr<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
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include <extra2d/render/rhi/rhi_types.h>
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
|
|
@ -75,7 +74,7 @@ public:
|
|||
* @param window 窗口接口
|
||||
* @return 成功返回 true
|
||||
*/
|
||||
virtual bool init(IWindow* window) = 0;
|
||||
virtual bool init(IWindow *window) = 0;
|
||||
|
||||
/**
|
||||
* @brief 关闭设备
|
||||
|
|
@ -95,7 +94,7 @@ public:
|
|||
/**
|
||||
* @brief 获取设备能力
|
||||
*/
|
||||
virtual const DeviceCaps& getCaps() const = 0;
|
||||
virtual const DeviceCaps &getCaps() const = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 帧管理
|
||||
|
|
@ -138,24 +137,28 @@ public:
|
|||
/**
|
||||
* @brief 创建缓冲区
|
||||
*/
|
||||
virtual Ptr<RHIBuffer> createBuffer(const BufferDesc& desc) = 0;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
virtual Ptr<RHIUniformBuffer>
|
||||
createUniformBuffer(size_t size,
|
||||
BufferUsage usage = BufferUsage::Dynamic) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 资源创建 - 纹理
|
||||
|
|
@ -164,24 +167,25 @@ public:
|
|||
/**
|
||||
* @brief 创建纹理
|
||||
*/
|
||||
virtual Ptr<RHITexture> createTexture(const TextureDesc& desc) = 0;
|
||||
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;
|
||||
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;
|
||||
virtual Ptr<RHISampler> createSampler(const SamplerDesc &desc) = 0;
|
||||
|
||||
/**
|
||||
* @brief 创建纹理视图
|
||||
*/
|
||||
virtual Ptr<RHITextureView> createTextureView(Ptr<RHITexture> texture,
|
||||
const TextureViewDesc& desc) = 0;
|
||||
virtual Ptr<RHITextureView>
|
||||
createTextureView(Ptr<RHITexture> texture, const TextureViewDesc &desc) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 资源创建 - 着色器
|
||||
|
|
@ -190,20 +194,22 @@ public:
|
|||
/**
|
||||
* @brief 创建着色器
|
||||
*/
|
||||
virtual Ptr<RHIShader> createShader(const ShaderDesc& desc) = 0;
|
||||
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;
|
||||
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;
|
||||
virtual Ptr<RHIShader>
|
||||
createShaderFromFile(const std::string &vertexPath,
|
||||
const std::string &fragmentPath) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 资源创建 - 管线
|
||||
|
|
@ -212,12 +218,13 @@ public:
|
|||
/**
|
||||
* @brief 创建渲染管线
|
||||
*/
|
||||
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc& desc, Ptr<RHIShader> shader) = 0;
|
||||
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc &desc,
|
||||
Ptr<RHIShader> shader) = 0;
|
||||
|
||||
/**
|
||||
* @brief 使用构建器创建渲染管线
|
||||
*/
|
||||
virtual Ptr<RHIPipeline> createPipeline(const PipelineBuilder& builder) = 0;
|
||||
virtual Ptr<RHIPipeline> createPipeline(const PipelineBuilder &builder) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 资源创建 - 帧缓冲
|
||||
|
|
@ -226,12 +233,14 @@ public:
|
|||
/**
|
||||
* @brief 创建帧缓冲
|
||||
*/
|
||||
virtual Ptr<RHIFramebuffer> createFramebuffer(const FramebufferDesc& desc) = 0;
|
||||
virtual Ptr<RHIFramebuffer>
|
||||
createFramebuffer(const FramebufferDesc &desc) = 0;
|
||||
|
||||
/**
|
||||
* @brief 使用构建器创建帧缓冲
|
||||
*/
|
||||
virtual Ptr<RHIFramebuffer> createFramebuffer(const FramebufferBuilder& builder) = 0;
|
||||
virtual Ptr<RHIFramebuffer>
|
||||
createFramebuffer(const FramebufferBuilder &builder) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 渲染状态设置
|
||||
|
|
@ -240,7 +249,7 @@ public:
|
|||
/**
|
||||
* @brief 设置视口
|
||||
*/
|
||||
virtual void setViewport(const Viewport& viewport) = 0;
|
||||
virtual void setViewport(const Viewport &viewport) = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置视口(简化版)
|
||||
|
|
@ -253,7 +262,7 @@ public:
|
|||
/**
|
||||
* @brief 设置裁剪矩形
|
||||
*/
|
||||
virtual void setScissorRect(const ScissorRect& rect) = 0;
|
||||
virtual void setScissorRect(const ScissorRect &rect) = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置裁剪矩形(简化版)
|
||||
|
|
@ -284,7 +293,8 @@ public:
|
|||
/**
|
||||
* @brief 绑定顶点缓冲区
|
||||
*/
|
||||
virtual void setVertexBuffer(uint32_t slot, Ptr<RHIBuffer> buffer, uint32_t offset = 0) = 0;
|
||||
virtual void setVertexBuffer(uint32_t slot, Ptr<RHIBuffer> buffer,
|
||||
uint32_t offset = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绑定索引缓冲区
|
||||
|
|
@ -294,7 +304,8 @@ public:
|
|||
/**
|
||||
* @brief 绑定纹理
|
||||
*/
|
||||
virtual void setTexture(uint32_t slot, Ptr<RHITexture> texture, Ptr<RHISampler> sampler = nullptr) = 0;
|
||||
virtual void setTexture(uint32_t slot, Ptr<RHITexture> texture,
|
||||
Ptr<RHISampler> sampler = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绑定 Uniform 缓冲区
|
||||
|
|
@ -318,24 +329,28 @@ public:
|
|||
/**
|
||||
* @brief 设置浮点 Uniform
|
||||
*/
|
||||
virtual void setUniformFloat(const std::string& name, float value) = 0;
|
||||
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;
|
||||
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;
|
||||
virtual void setUniformMat4(const std::string &name,
|
||||
const glm::mat4 &value) = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置整数 Uniform
|
||||
*/
|
||||
virtual void setUniformInt(const std::string& name, int value) = 0;
|
||||
virtual void setUniformInt(const std::string &name, int value) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 渲染命令 - 绘制
|
||||
|
|
@ -344,12 +359,13 @@ public:
|
|||
/**
|
||||
* @brief 绘制
|
||||
*/
|
||||
virtual void draw(const DrawCommand& cmd) = 0;
|
||||
virtual void draw(const DrawCommand &cmd) = 0;
|
||||
|
||||
/**
|
||||
* @brief 绘制(简化版)
|
||||
*/
|
||||
void draw(uint32_t vertexCount, uint32_t firstVertex = 0, uint32_t instanceCount = 1) {
|
||||
void draw(uint32_t vertexCount, uint32_t firstVertex = 0,
|
||||
uint32_t instanceCount = 1) {
|
||||
DrawCommand cmd;
|
||||
cmd.vertexCount = vertexCount;
|
||||
cmd.firstVertex = firstVertex;
|
||||
|
|
@ -360,13 +376,13 @@ public:
|
|||
/**
|
||||
* @brief 索引绘制
|
||||
*/
|
||||
virtual void drawIndexed(const DrawIndexedCommand& cmd) = 0;
|
||||
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) {
|
||||
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;
|
||||
|
|
@ -383,7 +399,8 @@ public:
|
|||
/**
|
||||
* @brief 索引间接绘制
|
||||
*/
|
||||
virtual void drawIndexedIndirect(Ptr<RHIBuffer> indirectBuffer, size_t offset) = 0;
|
||||
virtual void drawIndexedIndirect(Ptr<RHIBuffer> indirectBuffer,
|
||||
size_t offset) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 渲染命令 - 清除
|
||||
|
|
@ -392,7 +409,7 @@ public:
|
|||
/**
|
||||
* @brief 清除颜色缓冲
|
||||
*/
|
||||
virtual void clearColor(const ColorValue& color) = 0;
|
||||
virtual void clearColor(const ColorValue &color) = 0;
|
||||
|
||||
/**
|
||||
* @brief 清除深度缓冲
|
||||
|
|
@ -407,7 +424,8 @@ public:
|
|||
/**
|
||||
* @brief 清除所有缓冲
|
||||
*/
|
||||
virtual void clear(const ColorValue& color, float depth = 1.0f, uint8_t stencil = 0) = 0;
|
||||
virtual void clear(const ColorValue &color, float depth = 1.0f,
|
||||
uint8_t stencil = 0) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 统计与调试
|
||||
|
|
@ -416,7 +434,7 @@ public:
|
|||
/**
|
||||
* @brief 获取统计信息
|
||||
*/
|
||||
virtual const DeviceStats& getStats() const = 0;
|
||||
virtual const DeviceStats &getStats() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 重置统计信息
|
||||
|
|
@ -431,12 +449,12 @@ public:
|
|||
/**
|
||||
* @brief 获取调试名称
|
||||
*/
|
||||
virtual const std::string& getDebugName() const = 0;
|
||||
virtual const std::string &getDebugName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 设置调试名称
|
||||
*/
|
||||
virtual void setDebugName(const std::string& name) = 0;
|
||||
virtual void setDebugName(const std::string &name) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// 静态工厂方法
|
||||
|
|
@ -467,11 +485,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
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_;
|
||||
|
|
|
|||
|
|
@ -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 节点更新回调(子类重写)
|
||||
|
|
|
|||
|
|
@ -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 更新场景
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 更新过渡进度(子类重写此方法更新动画)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
void GLFWWindow::setVisible(bool visible) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ¢er, float radius, const Color &color,
|
||||
float lineWidth, uint32_t segments) {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
stats_.drawCalls++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 绘制填充圆形
|
||||
*/
|
||||
void GLRenderBackend::fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||
uint32_t segments) {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
stats_.drawCalls++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 绘制线段
|
||||
*/
|
||||
void GLRenderBackend::drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||
float lineWidth) {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
stats_.drawCalls++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 绘制多边形
|
||||
*/
|
||||
void GLRenderBackend::drawPolygon(const Vec2 *points, size_t count, const Color &color,
|
||||
float lineWidth) {
|
||||
if (!isValid() || !points || count < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
stats_.drawCalls++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 绘制填充多边形
|
||||
*/
|
||||
void GLRenderBackend::fillPolygon(const Vec2 *points, size_t count, const Color &color) {
|
||||
if (!isValid() || !points || count < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
stats_.drawCalls++;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 批处理控制
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @brief 开始精灵批处理
|
||||
*/
|
||||
void GLRenderBackend::beginSpriteBatch() {
|
||||
inBatch_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 结束精灵批处理
|
||||
*/
|
||||
void GLRenderBackend::endSpriteBatch() {
|
||||
if (!inBatch_) {
|
||||
return;
|
||||
}
|
||||
|
||||
flush();
|
||||
inBatch_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 刷新当前批次
|
||||
*/
|
||||
void GLRenderBackend::flush() {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.batchCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置渲染排序键
|
||||
*/
|
||||
void GLRenderBackend::setSortKey(uint64_t key) {
|
||||
sortKey_ = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置渲染层
|
||||
*/
|
||||
void GLRenderBackend::setLayer(int layer) {
|
||||
layer_ = layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置混合模式
|
||||
*/
|
||||
void GLRenderBackend::setBlendMode(rhi::BlendState blend) {
|
||||
blendState_ = blend;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 访问器
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @brief 获取 RHI 设备
|
||||
*/
|
||||
rhi::RHIDevice *GLRenderBackend::getDevice() const {
|
||||
return device_.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取窗口宽度
|
||||
*/
|
||||
int GLRenderBackend::getWidth() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取窗口高度
|
||||
*/
|
||||
int GLRenderBackend::getHeight() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取渲染统计
|
||||
*/
|
||||
const RenderStats &GLRenderBackend::getStats() const {
|
||||
return stats_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重置渲染统计
|
||||
*/
|
||||
void GLRenderBackend::resetStats() {
|
||||
stats_.reset();
|
||||
if (device_) {
|
||||
device_->resetStats();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取图形 API 类型
|
||||
*/
|
||||
rhi::GraphicsAPI GLRenderBackend::getAPI() const {
|
||||
return rhi::GraphicsAPI::OpenGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取设备能力
|
||||
*/
|
||||
const rhi::DeviceCaps &GLRenderBackend::getCaps() const {
|
||||
static rhi::DeviceCaps empty;
|
||||
return device_ ? device_->getCaps() : empty;
|
||||
}
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
if (spriteBatcher_) {
|
||||
spriteBatcher_->shutdown();
|
||||
spriteBatcher_.reset();
|
||||
context_.reset();
|
||||
backend_.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 ¢er, float radius, const Color &color,
|
||||
float lineWidth, uint32_t segments) {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
}
|
||||
|
||||
void Renderer::fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||
uint32_t segments) {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
}
|
||||
|
||||
void Renderer::drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||
float lineWidth) {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
}
|
||||
|
||||
void Renderer::drawPolygon(const Vec2 *points, size_t count, const Color &color,
|
||||
float lineWidth) {
|
||||
if (!initialized_ || !points || count < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
}
|
||||
|
||||
void Renderer::fillPolygon(const Vec2 *points, size_t count,
|
||||
const Color &color) {
|
||||
if (!initialized_ || !points || count < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.shapeCount++;
|
||||
}
|
||||
|
||||
void Renderer::beginSpriteBatch() {
|
||||
if (!initialized_ || !spriteBatcher_ || inBatch_) {
|
||||
return;
|
||||
}
|
||||
|
||||
inBatch_ = true;
|
||||
spriteBatcher_->begin(projectionMatrix_ * viewMatrix_);
|
||||
}
|
||||
|
||||
void Renderer::endSpriteBatch() {
|
||||
if (!initialized_ || !spriteBatcher_ || !inBatch_) {
|
||||
return;
|
||||
}
|
||||
|
||||
spriteBatcher_->end();
|
||||
inBatch_ = false;
|
||||
stats_.batchCount++;
|
||||
stats_.drawCalls += spriteBatcher_->getDrawCallCount();
|
||||
}
|
||||
|
||||
void Renderer::flush() {
|
||||
if (!initialized_ || !spriteBatcher_) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats_.batchCount++;
|
||||
}
|
||||
|
||||
void Renderer::setSortKey(uint64_t key) {
|
||||
sortKey_ = key;
|
||||
}
|
||||
|
||||
void Renderer::setLayer(int layer) {
|
||||
layer_ = layer;
|
||||
}
|
||||
|
||||
void Renderer::setBlendMode(rhi::BlendState blend) {
|
||||
blendState_ = blend;
|
||||
}
|
||||
|
||||
void Renderer::setActiveCamera(Ptr<Camera> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// 调整源矩形(翻转)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue