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 IWindow;
|
||||||
class IInput;
|
class IInput;
|
||||||
class RenderBackend;
|
class Renderer;
|
||||||
class WindowModule;
|
class WindowModule;
|
||||||
class RenderModule;
|
class RenderModule;
|
||||||
class InputModule;
|
class InputModule;
|
||||||
|
|
@ -93,7 +93,7 @@ public:
|
||||||
* @brief 获取渲染器
|
* @brief 获取渲染器
|
||||||
* @return 渲染器指针
|
* @return 渲染器指针
|
||||||
*/
|
*/
|
||||||
RenderBackend *renderer();
|
Renderer *renderer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取输入
|
* @brief 获取输入
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,10 @@
|
||||||
#include <extra2d/platform/window_module.h>
|
#include <extra2d/platform/window_module.h>
|
||||||
|
|
||||||
// Render Core
|
// Render Core
|
||||||
#include <extra2d/render/core/render_backend.h>
|
|
||||||
#include <extra2d/render/core/render_command.h>
|
#include <extra2d/render/core/render_command.h>
|
||||||
#include <extra2d/render/core/render_context.h>
|
#include <extra2d/render/core/render_context.h>
|
||||||
#include <extra2d/render/core/render_queue.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/render_module.h>
|
||||||
#include <extra2d/render/core/backend_factory.h>
|
|
||||||
|
|
||||||
// Render Camera
|
// Render Camera
|
||||||
#include <extra2d/render/camera/camera.h>
|
#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 {
|
namespace rhi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OpenGL 上下文类型
|
||||||
|
*/
|
||||||
|
enum class GLContextType {
|
||||||
|
None,
|
||||||
|
GLFW,
|
||||||
|
SDL2
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief OpenGL RHI 设备实现
|
* @brief OpenGL RHI 设备实现
|
||||||
*
|
*
|
||||||
|
|
@ -176,6 +185,12 @@ private:
|
||||||
DeviceStats stats_;
|
DeviceStats stats_;
|
||||||
std::string debugName_;
|
std::string debugName_;
|
||||||
|
|
||||||
|
// OpenGL 上下文相关
|
||||||
|
GLContextType contextType_ = GLContextType::None;
|
||||||
|
void *glfwWindow_ = nullptr;
|
||||||
|
void *sdlWindow_ = nullptr;
|
||||||
|
void *glContext_ = nullptr;
|
||||||
|
|
||||||
// 当前绑定的资源
|
// 当前绑定的资源
|
||||||
Ptr<RHIPipeline> currentPipeline_;
|
Ptr<RHIPipeline> currentPipeline_;
|
||||||
Ptr<RHIShader> currentShader_;
|
Ptr<RHIShader> currentShader_;
|
||||||
|
|
@ -205,6 +220,16 @@ private:
|
||||||
void applyPipelineState(const BlendState &blend,
|
void applyPipelineState(const BlendState &blend,
|
||||||
const DepthStencilState &depthStencil,
|
const DepthStencilState &depthStencil,
|
||||||
const RasterizerState &rasterizer);
|
const RasterizerState &rasterizer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化 GLFW 上下文
|
||||||
|
*/
|
||||||
|
bool initGLFWContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化 SDL2 上下文
|
||||||
|
*/
|
||||||
|
bool initSDL2Context();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rhi
|
} // 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/color.h>
|
||||||
#include <extra2d/core/math_types.h>
|
#include <extra2d/core/math_types.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
|
||||||
#include <extra2d/render/core/render_queue.h>
|
#include <extra2d/render/core/render_queue.h>
|
||||||
#include <extra2d/render/rhi/rhi_device.h>
|
#include <extra2d/render/rhi/rhi_device.h>
|
||||||
#include <extra2d/render/rhi/rhi_types.h>
|
#include <extra2d/render/rhi/rhi_types.h>
|
||||||
|
|
@ -132,12 +131,6 @@ public:
|
||||||
*/
|
*/
|
||||||
IWindow *getWindow() const { return window_; }
|
IWindow *getWindow() const { return window_; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取统计信息
|
|
||||||
*/
|
|
||||||
const RenderStats &getStats() const { return stats_; }
|
|
||||||
void resetStats();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取配置
|
* @brief 获取配置
|
||||||
*/
|
*/
|
||||||
|
|
@ -167,7 +160,6 @@ private:
|
||||||
Ptr<rhi::RHIDevice> device_;
|
Ptr<rhi::RHIDevice> device_;
|
||||||
IWindow *window_;
|
IWindow *window_;
|
||||||
RenderQueue queue_;
|
RenderQueue queue_;
|
||||||
RenderStats stats_;
|
|
||||||
RenderContextConfig config_;
|
RenderContextConfig config_;
|
||||||
|
|
||||||
std::stack<glm::mat4> transformStack_;
|
std::stack<glm::mat4> transformStack_;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <extra2d/core/module.h>
|
#include <extra2d/core/module.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
|
||||||
#include <extra2d/render/rhi/rhi_types.h>
|
#include <extra2d/render/rhi/rhi_types.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,46 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <extra2d/core/color.h>
|
#include <extra2d/core/color.h>
|
||||||
|
#include <extra2d/core/math_types.h>
|
||||||
#include <extra2d/core/module.h>
|
#include <extra2d/core/module.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/render/batch/shape_batcher.h>
|
|
||||||
#include <extra2d/render/batch/sprite_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/camera.h>
|
||||||
#include <extra2d/render/camera/viewport_adapter.h>
|
#include <extra2d/render/camera/viewport_adapter.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/core/render_queue.h>
|
||||||
#include <extra2d/render/core/render_context.h>
|
#include <extra2d/render/rhi/rhi_device.h>
|
||||||
#include <extra2d/render/rhi/rhi_types.h>
|
#include <extra2d/render/rhi/rhi_types.h>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
class IWindow;
|
class IWindow;
|
||||||
class Scene;
|
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 渲染器配置
|
* @brief 渲染器配置
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,7 +66,7 @@ struct RendererConfig {
|
||||||
/**
|
/**
|
||||||
* @brief 高层渲染器
|
* @brief 高层渲染器
|
||||||
*
|
*
|
||||||
* 整合渲染后端、批处理器和相机系统
|
* 整合 RHI 设备、批处理器和相机系统
|
||||||
* 提供统一的渲染接口供游戏逻辑使用
|
* 提供统一的渲染接口供游戏逻辑使用
|
||||||
*/
|
*/
|
||||||
class Renderer : public Module {
|
class Renderer : public Module {
|
||||||
|
|
@ -105,6 +129,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 开始帧渲染
|
* @brief 开始帧渲染
|
||||||
|
* @param clearColor 清屏颜色
|
||||||
*/
|
*/
|
||||||
void beginFrame(const Color &clearColor = Colors::Black);
|
void beginFrame(const Color &clearColor = Colors::Black);
|
||||||
|
|
||||||
|
|
@ -127,10 +152,188 @@ public:
|
||||||
*/
|
*/
|
||||||
void renderScene(Scene *scene);
|
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_; }
|
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 设备
|
* @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 = {});
|
static Ptr<Renderer> create(const RendererConfig &config = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief 创建批处理器
|
|
||||||
*/
|
|
||||||
bool createBatchers();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建默认相机
|
* @brief 创建默认相机
|
||||||
*/
|
*/
|
||||||
|
|
@ -300,27 +450,29 @@ private:
|
||||||
*/
|
*/
|
||||||
void updateViewportAdapter();
|
void updateViewportAdapter();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 应用相机变换
|
|
||||||
*/
|
|
||||||
void applyCameraTransform(Camera *camera);
|
|
||||||
|
|
||||||
IWindow *window_;
|
IWindow *window_;
|
||||||
RendererConfig config_;
|
RendererConfig config_;
|
||||||
|
|
||||||
UniquePtr<RenderContext> context_;
|
Ptr<rhi::RHIDevice> device_;
|
||||||
UniquePtr<RenderBackend> backend_;
|
|
||||||
UniquePtr<SpriteBatcher> spriteBatcher_;
|
UniquePtr<SpriteBatcher> spriteBatcher_;
|
||||||
UniquePtr<ShapeBatcher> shapeBatcher_;
|
UniquePtr<RenderQueue> renderQueue_;
|
||||||
UniquePtr<TextBatcher> textBatcher_;
|
|
||||||
|
|
||||||
ViewportAdapter viewportAdapter_;
|
ViewportAdapter viewportAdapter_;
|
||||||
Ptr<Camera> activeCamera_;
|
Ptr<Camera> activeCamera_;
|
||||||
Ptr<Camera> defaultCamera_;
|
Ptr<Camera> defaultCamera_;
|
||||||
|
|
||||||
|
glm::mat4 projectionMatrix_;
|
||||||
|
glm::mat4 viewMatrix_;
|
||||||
|
|
||||||
int width_;
|
int width_;
|
||||||
int height_;
|
int height_;
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
|
|
||||||
|
RenderStats stats_;
|
||||||
|
uint64_t sortKey_;
|
||||||
|
int layer_;
|
||||||
|
rhi::BlendState blendState_;
|
||||||
|
bool inBatch_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include <extra2d/render/rhi/rhi_types.h>
|
#include <extra2d/render/rhi/rhi_types.h>
|
||||||
#include <glm/mat4x4.hpp>
|
#include <glm/mat4x4.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -143,19 +142,23 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建顶点缓冲区
|
* @brief 创建顶点缓冲区
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIVertexBuffer> createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
|
virtual Ptr<RHIVertexBuffer>
|
||||||
|
createVertexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
|
||||||
const void *data = nullptr) = 0;
|
const void *data = nullptr) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建索引缓冲区
|
* @brief 创建索引缓冲区
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIIndexBuffer> createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
|
virtual Ptr<RHIIndexBuffer>
|
||||||
|
createIndexBuffer(size_t size, BufferUsage usage = BufferUsage::Static,
|
||||||
const void *data = nullptr) = 0;
|
const void *data = nullptr) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建 Uniform 缓冲区
|
* @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;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 资源创建 - 纹理
|
// 资源创建 - 纹理
|
||||||
|
|
@ -169,7 +172,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建 2D 纹理
|
* @brief 创建 2D 纹理
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHITexture> createTexture2D(uint32_t width, uint32_t height, Format format,
|
virtual Ptr<RHITexture> createTexture2D(uint32_t width, uint32_t height,
|
||||||
|
Format format,
|
||||||
const void *data = nullptr) = 0;
|
const void *data = nullptr) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -180,8 +184,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建纹理视图
|
* @brief 创建纹理视图
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHITextureView> createTextureView(Ptr<RHITexture> texture,
|
virtual Ptr<RHITextureView>
|
||||||
const TextureViewDesc& desc) = 0;
|
createTextureView(Ptr<RHITexture> texture, const TextureViewDesc &desc) = 0;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 资源创建 - 着色器
|
// 资源创建 - 着色器
|
||||||
|
|
@ -195,14 +199,16 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 从源码创建着色器
|
* @brief 从源码创建着色器
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIShader> createShaderFromSource(const std::string& name,
|
virtual Ptr<RHIShader>
|
||||||
|
createShaderFromSource(const std::string &name,
|
||||||
const std::string &vertexSource,
|
const std::string &vertexSource,
|
||||||
const std::string &fragmentSource) = 0;
|
const std::string &fragmentSource) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从文件创建着色器
|
* @brief 从文件创建着色器
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIShader> createShaderFromFile(const std::string& vertexPath,
|
virtual Ptr<RHIShader>
|
||||||
|
createShaderFromFile(const std::string &vertexPath,
|
||||||
const std::string &fragmentPath) = 0;
|
const std::string &fragmentPath) = 0;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
@ -212,7 +218,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建渲染管线
|
* @brief 创建渲染管线
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc& desc, Ptr<RHIShader> shader) = 0;
|
virtual Ptr<RHIPipeline> createPipeline(const PipelineDesc &desc,
|
||||||
|
Ptr<RHIShader> shader) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 使用构建器创建渲染管线
|
* @brief 使用构建器创建渲染管线
|
||||||
|
|
@ -226,12 +233,14 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建帧缓冲
|
* @brief 创建帧缓冲
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIFramebuffer> createFramebuffer(const FramebufferDesc& desc) = 0;
|
virtual Ptr<RHIFramebuffer>
|
||||||
|
createFramebuffer(const FramebufferDesc &desc) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 使用构建器创建帧缓冲
|
* @brief 使用构建器创建帧缓冲
|
||||||
*/
|
*/
|
||||||
virtual Ptr<RHIFramebuffer> createFramebuffer(const FramebufferBuilder& builder) = 0;
|
virtual Ptr<RHIFramebuffer>
|
||||||
|
createFramebuffer(const FramebufferBuilder &builder) = 0;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 渲染状态设置
|
// 渲染状态设置
|
||||||
|
|
@ -284,7 +293,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 绑定顶点缓冲区
|
* @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 绑定索引缓冲区
|
* @brief 绑定索引缓冲区
|
||||||
|
|
@ -294,7 +304,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 绑定纹理
|
* @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 缓冲区
|
* @brief 绑定 Uniform 缓冲区
|
||||||
|
|
@ -323,14 +334,18 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 设置向量 Uniform
|
* @brief 设置向量 Uniform
|
||||||
*/
|
*/
|
||||||
virtual void setUniformVec2(const std::string& name, const glm::vec2& value) = 0;
|
virtual void setUniformVec2(const std::string &name,
|
||||||
virtual void setUniformVec3(const std::string& name, const glm::vec3& value) = 0;
|
const glm::vec2 &value) = 0;
|
||||||
virtual void setUniformVec4(const std::string& name, const glm::vec4& 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
|
* @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
|
* @brief 设置整数 Uniform
|
||||||
|
|
@ -349,7 +364,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 绘制(简化版)
|
* @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;
|
DrawCommand cmd;
|
||||||
cmd.vertexCount = vertexCount;
|
cmd.vertexCount = vertexCount;
|
||||||
cmd.firstVertex = firstVertex;
|
cmd.firstVertex = firstVertex;
|
||||||
|
|
@ -365,8 +381,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 索引绘制(简化版)
|
* @brief 索引绘制(简化版)
|
||||||
*/
|
*/
|
||||||
void drawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, int32_t vertexOffset = 0,
|
void drawIndexed(uint32_t indexCount, uint32_t firstIndex = 0,
|
||||||
uint32_t instanceCount = 1) {
|
int32_t vertexOffset = 0, uint32_t instanceCount = 1) {
|
||||||
DrawIndexedCommand cmd;
|
DrawIndexedCommand cmd;
|
||||||
cmd.indexCount = indexCount;
|
cmd.indexCount = indexCount;
|
||||||
cmd.firstIndex = firstIndex;
|
cmd.firstIndex = firstIndex;
|
||||||
|
|
@ -383,7 +399,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 索引间接绘制
|
* @brief 索引间接绘制
|
||||||
*/
|
*/
|
||||||
virtual void drawIndexedIndirect(Ptr<RHIBuffer> indirectBuffer, size_t offset) = 0;
|
virtual void drawIndexedIndirect(Ptr<RHIBuffer> indirectBuffer,
|
||||||
|
size_t offset) = 0;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 渲染命令 - 清除
|
// 渲染命令 - 清除
|
||||||
|
|
@ -407,7 +424,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 清除所有缓冲
|
* @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;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 统计与调试
|
// 统计与调试
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include <extra2d/core/math_types.h>
|
#include <extra2d/core/math_types.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/event/event_dispatcher.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/component.h>
|
||||||
#include <extra2d/scene/components/transform_component.h>
|
#include <extra2d/scene/components/transform_component.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
class Scene;
|
class Scene;
|
||||||
class RenderBackend;
|
class Renderer;
|
||||||
struct RenderCommand;
|
struct RenderCommand;
|
||||||
class RenderQueue;
|
class RenderQueue;
|
||||||
|
|
||||||
|
|
@ -450,9 +450,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染回调
|
* @brief 渲染回调
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
virtual void onRender(RenderBackend &renderer);
|
virtual void onRender(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 附加到场景时的回调
|
* @brief 附加到场景时的回调
|
||||||
|
|
@ -497,9 +497,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染节点
|
* @brief 渲染节点
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void render(RenderBackend &renderer);
|
void render(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 对子节点排序
|
* @brief 对子节点排序
|
||||||
|
|
@ -535,9 +535,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief 绘制回调(子类重写)
|
* @brief 绘制回调(子类重写)
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
virtual void onDraw(RenderBackend &renderer) {}
|
virtual void onDraw(Renderer &renderer) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 节点更新回调(子类重写)
|
* @brief 节点更新回调(子类重写)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
class RenderQueue;
|
class RenderQueue;
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 场景类 - 节点容器,管理整个场景图
|
* @brief 场景类 - 节点容器,管理整个场景图
|
||||||
|
|
@ -120,15 +121,15 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染场景
|
* @brief 渲染场景
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void renderScene(RenderBackend &renderer);
|
void renderScene(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染场景内容
|
* @brief 渲染场景内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
virtual void renderContent(RenderBackend &renderer);
|
virtual void renderContent(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新场景
|
* @brief 更新场景
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ namespace extra2d {
|
||||||
struct RenderCommand;
|
struct RenderCommand;
|
||||||
class TransitionScene;
|
class TransitionScene;
|
||||||
enum class TransitionType;
|
enum class TransitionType;
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 场景管理器 - 管理场景的生命周期和切换
|
* @brief 场景管理器 - 管理场景的生命周期和切换
|
||||||
|
|
@ -102,7 +103,7 @@ public:
|
||||||
// 更新和渲染
|
// 更新和渲染
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void render(RenderBackend &renderer);
|
void render(Renderer &renderer);
|
||||||
void collectRenderCommands(std::vector<RenderCommand> &commands);
|
void collectRenderCommands(std::vector<RenderCommand> &commands);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public:
|
||||||
Rect getBounds() const override;
|
Rect getBounds() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onDraw(RenderBackend &renderer) override;
|
void onDraw(Renderer &renderer) override;
|
||||||
void generateRenderCommand(std::vector<RenderCommand> &commands,
|
void generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
int zOrder) override;
|
int zOrder) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ public:
|
||||||
Rect getBounds() const override;
|
Rect getBounds() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onDraw(RenderBackend &renderer) override;
|
void onDraw(Renderer &renderer) override;
|
||||||
void generateRenderCommand(std::vector<RenderCommand> &commands,
|
void generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
int zOrder) override;
|
int zOrder) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 方块/马赛克过渡场景
|
// 方块/马赛克过渡场景
|
||||||
// 实现原理:
|
// 实现原理:
|
||||||
|
|
@ -25,7 +27,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onTransitionStart() override;
|
void onTransitionStart() override;
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
void updateTransition(float dt) override;
|
void updateTransition(float dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 淡入淡出过渡场景
|
// 淡入淡出过渡场景
|
||||||
// 实现原理:
|
// 实现原理:
|
||||||
|
|
@ -44,7 +46,7 @@ protected:
|
||||||
* @brief 渲染内容
|
* @brief 渲染内容
|
||||||
* 根据进度控制新旧场景的显示
|
* 根据进度控制新旧场景的显示
|
||||||
*/
|
*/
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 翻页过渡场景
|
// 翻页过渡场景
|
||||||
// 实现原理:
|
// 实现原理:
|
||||||
|
|
@ -28,7 +30,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onTransitionStart() override;
|
void onTransitionStart() override;
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
void updateTransition(float dt) override;
|
void updateTransition(float dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 缩放过渡场景
|
// 缩放过渡场景
|
||||||
// 实现原理:
|
// 实现原理:
|
||||||
|
|
@ -23,7 +25,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onTransitionStart() override;
|
void onTransitionStart() override;
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
void updateTransition(float dt) override;
|
void updateTransition(float dt) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 过渡方向
|
// 过渡方向
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -99,7 +101,7 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 渲染 - 在 TransitionScene 上渲染新旧两个子场景
|
// 渲染 - 在 TransitionScene 上渲染新旧两个子场景
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 生命周期
|
// 生命周期
|
||||||
|
|
@ -117,12 +119,12 @@ protected:
|
||||||
/**
|
/**
|
||||||
* @brief 绘制源场景(旧场景)
|
* @brief 绘制源场景(旧场景)
|
||||||
*/
|
*/
|
||||||
virtual void drawOutScene(RenderBackend &renderer);
|
virtual void drawOutScene(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制目标场景(新场景)
|
* @brief 绘制目标场景(新场景)
|
||||||
*/
|
*/
|
||||||
virtual void drawInScene(RenderBackend &renderer);
|
virtual void drawInScene(Renderer &renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新过渡进度(子类重写此方法更新动画)
|
* @brief 更新过渡进度(子类重写此方法更新动画)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 滑动过渡场景
|
// 滑动过渡场景
|
||||||
// 实现原理:
|
// 实现原理:
|
||||||
|
|
@ -26,7 +28,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onTransitionStart() override;
|
void onTransitionStart() override;
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
void updateTransition(float dt) override;
|
void updateTransition(float dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 场景服务接口
|
* @brief 场景服务接口
|
||||||
* 定义场景管理的抽象接口,便于测试和Mock
|
* 定义场景管理的抽象接口,便于测试和Mock
|
||||||
|
|
@ -30,7 +32,7 @@ public:
|
||||||
virtual bool isEmpty() const = 0;
|
virtual bool isEmpty() const = 0;
|
||||||
virtual bool hasScene(const std::string& name) 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 void collectRenderCommands(std::vector<RenderCommand>& commands) = 0;
|
||||||
|
|
||||||
virtual bool isTransitioning() const = 0;
|
virtual bool isTransitioning() const = 0;
|
||||||
|
|
@ -72,7 +74,7 @@ public:
|
||||||
bool isEmpty() const override;
|
bool isEmpty() const override;
|
||||||
bool hasScene(const std::string& name) 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;
|
void collectRenderCommands(std::vector<RenderCommand>& commands) override;
|
||||||
|
|
||||||
bool isTransitioning() const override;
|
bool isTransitioning() const override;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <extra2d/platform/iwindow.h>
|
#include <extra2d/platform/iwindow.h>
|
||||||
#include <extra2d/platform/window_module.h>
|
#include <extra2d/platform/window_module.h>
|
||||||
#include <extra2d/render/camera/viewport_adapter.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/core/render_module.h>
|
||||||
#include <extra2d/render/renderer.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <extra2d/services/camera_service.h>
|
#include <extra2d/services/camera_service.h>
|
||||||
|
|
@ -209,8 +208,8 @@ void Application::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
|
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
|
||||||
if (sceneService && renderer->getBackend()) {
|
if (sceneService) {
|
||||||
sceneService->render(*renderer->getBackend());
|
sceneService->render(*renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
winMod->win()->swap();
|
winMod->win()->swap();
|
||||||
|
|
@ -221,9 +220,9 @@ IWindow *Application::window() {
|
||||||
return winMod ? winMod->win() : nullptr;
|
return winMod ? winMod->win() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderBackend *Application::renderer() {
|
Renderer *Application::renderer() {
|
||||||
auto *renderMod = get<RenderModule>();
|
auto *renderMod = get<RenderModule>();
|
||||||
return renderMod ? (renderMod->getRenderer() ? renderMod->getRenderer()->getBackend() : nullptr) : nullptr;
|
return renderMod ? renderMod->getRenderer() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IInput *Application::input() {
|
IInput *Application::input() {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <extra2d/platform/keys.h>
|
#include <extra2d/platform/keys.h>
|
||||||
#include <extra2d/services/event_service.h>
|
#include <extra2d/services/event_service.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -19,10 +18,6 @@ bool GLFWWindow::create(const std::string &title, int width, int height,
|
||||||
return false;
|
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_DOUBLEBUFFER, GLFW_TRUE);
|
||||||
glfwWindowHint(GLFW_DEPTH_BITS, 24);
|
glfwWindowHint(GLFW_DEPTH_BITS, 24);
|
||||||
glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
||||||
|
|
@ -65,17 +60,6 @@ bool GLFWWindow::create(const std::string &title, int width, int height,
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
vsync_ = vsync;
|
||||||
|
|
||||||
glfwGetWindowSize(glfwWindow_, &width_, &height_);
|
glfwGetWindowSize(glfwWindow_, &width_, &height_);
|
||||||
|
|
@ -194,11 +178,8 @@ void GLFWWindow::setFullscreen(bool fs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setVSync(bool vsync) {
|
void GLFWWindow::setVSync(bool vsync) {
|
||||||
if (glfwWindow_) {
|
|
||||||
glfwSwapInterval(vsync ? 1 : 0);
|
|
||||||
vsync_ = vsync;
|
vsync_ = vsync;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void GLFWWindow::setVisible(bool visible) {
|
void GLFWWindow::setVisible(bool visible) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <extra2d/platform/keys.h>
|
#include <extra2d/platform/keys.h>
|
||||||
#include <extra2d/services/event_service.h>
|
#include <extra2d/services/event_service.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -24,20 +23,12 @@ bool SDL2Window::create(const std::string &title, int width, int height,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
|
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
#endif
|
#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,
|
sdlWindow_ = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_WINDOWPOS_CENTERED, width, height, flags);
|
SDL_WINDOWPOS_CENTERED, width, height, flags);
|
||||||
|
|
||||||
|
|
@ -47,27 +38,6 @@ bool SDL2Window::create(const std::string &title, int width, int height,
|
||||||
return false;
|
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_);
|
SDL_GetWindowSize(sdlWindow_, &width_, &height_);
|
||||||
fullscreen_ = (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
|
fullscreen_ = (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
|
||||||
vsync_ = vsync;
|
vsync_ = vsync;
|
||||||
|
|
@ -81,7 +51,6 @@ bool SDL2Window::create(const std::string &title, int width, int height,
|
||||||
input_->init();
|
input_->init();
|
||||||
|
|
||||||
E2D_LOG_INFO("SDL2 窗口创建成功: {}x{}", width_, height_);
|
E2D_LOG_INFO("SDL2 窗口创建成功: {}x{}", width_, height_);
|
||||||
E2D_LOG_INFO(" 平台: OpenGL ES 3.2");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,11 +64,6 @@ void SDL2Window::destroy() {
|
||||||
deinitCursors();
|
deinitCursors();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (glContext_) {
|
|
||||||
SDL_GL_DeleteContext(glContext_);
|
|
||||||
glContext_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sdlWindow_) {
|
if (sdlWindow_) {
|
||||||
SDL_DestroyWindow(sdlWindow_);
|
SDL_DestroyWindow(sdlWindow_);
|
||||||
sdlWindow_ = nullptr;
|
sdlWindow_ = nullptr;
|
||||||
|
|
@ -123,9 +87,6 @@ void SDL2Window::poll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL2Window::swap() {
|
void SDL2Window::swap() {
|
||||||
if (sdlWindow_ && glContext_) {
|
|
||||||
SDL_GL_SwapWindow(sdlWindow_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL2Window::shouldClose() const { return shouldClose_; }
|
bool SDL2Window::shouldClose() const { return shouldClose_; }
|
||||||
|
|
@ -169,11 +130,8 @@ void SDL2Window::setFullscreen(bool fs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL2Window::setVSync(bool vsync) {
|
void SDL2Window::setVSync(bool vsync) {
|
||||||
if (glContext_) {
|
|
||||||
SDL_GL_SetSwapInterval(vsync ? 1 : 0);
|
|
||||||
vsync_ = vsync;
|
vsync_ = vsync;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SDL2Window::setVisible(bool visible) {
|
void SDL2Window::setVisible(bool visible) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
|
|
@ -313,10 +271,8 @@ void SDL2Window::deinitCursors() {
|
||||||
void SDL2Window::updateContentScale() {
|
void SDL2Window::updateContentScale() {
|
||||||
if (sdlWindow_) {
|
if (sdlWindow_) {
|
||||||
SDL_GetWindowSize(sdlWindow_, &width_, &height_);
|
SDL_GetWindowSize(sdlWindow_, &width_, &height_);
|
||||||
int dw, dh;
|
scaleX_ = 1.0f;
|
||||||
SDL_GL_GetDrawableSize(sdlWindow_, &dw, &dh);
|
scaleY_ = 1.0f;
|
||||||
scaleX_ = dw > 0 ? static_cast<float>(dw) / width_ : 1.0f;
|
|
||||||
scaleY_ = dh > 0 ? static_cast<float>(dh) / height_ : 1.0f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,6 @@ public:
|
||||||
*/
|
*/
|
||||||
SDL_Window* sdlWindow() const { return sdlWindow_; }
|
SDL_Window* sdlWindow() const { return sdlWindow_; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取 OpenGL 上下文
|
|
||||||
*/
|
|
||||||
SDL_GLContext glContext() const { return glContext_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initSDL();
|
bool initSDL();
|
||||||
void deinitSDL();
|
void deinitSDL();
|
||||||
|
|
@ -75,7 +70,6 @@ private:
|
||||||
Key sdlScancodeToKey(int scancode);
|
Key sdlScancodeToKey(int scancode);
|
||||||
|
|
||||||
SDL_Window* sdlWindow_ = nullptr;
|
SDL_Window* sdlWindow_ = nullptr;
|
||||||
SDL_GLContext glContext_ = nullptr;
|
|
||||||
SDL_Cursor* sdlCursors_[7] = {};
|
SDL_Cursor* sdlCursors_[7] = {};
|
||||||
int currentCursor_ = 0;
|
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/render/backends/opengl/gl_context.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <extra2d/platform/iwindow.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 <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
@ -28,10 +37,35 @@ bool GLRHIDevice::init(IWindow* window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
window_ = window;
|
window_ = window;
|
||||||
|
if (!window_) {
|
||||||
|
E2D_LOG_ERROR("窗口不能为空");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化 OpenGL 上下文
|
// 尝试识别窗口类型并创建 OpenGL 上下文
|
||||||
if (!GLContext::get().init()) {
|
void* nativeHandle = window_->native();
|
||||||
E2D_LOG_ERROR("初始化 OpenGL 上下文失败");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,12 +96,108 @@ void GLRHIDevice::shutdown() {
|
||||||
currentShader_.reset();
|
currentShader_.reset();
|
||||||
currentFramebuffer_.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();
|
GLContext::get().shutdown();
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
|
contextType_ = GLContextType::None;
|
||||||
|
glfwWindow_ = nullptr;
|
||||||
|
sdlWindow_ = nullptr;
|
||||||
|
glContext_ = nullptr;
|
||||||
|
|
||||||
E2D_LOG_INFO("OpenGL RHI 设备已关闭");
|
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() {
|
void GLRHIDevice::initCaps() {
|
||||||
caps_.api = GraphicsAPI::OpenGL;
|
caps_.api = GraphicsAPI::OpenGL;
|
||||||
caps_.apiVersion = GLContext::get().getVersionString();
|
caps_.apiVersion = GLContext::get().getVersionString();
|
||||||
|
|
@ -124,16 +254,30 @@ void GLRHIDevice::endFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRHIDevice::present() {
|
void GLRHIDevice::present() {
|
||||||
if (window_) {
|
#ifdef E2D_BACKEND_GLFW
|
||||||
window_->swap();
|
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) {
|
void GLRHIDevice::setVSync(bool enabled) {
|
||||||
vsyncEnabled_ = enabled;
|
vsyncEnabled_ = enabled;
|
||||||
if (window_) {
|
#ifdef E2D_BACKEND_GLFW
|
||||||
window_->setVSync(enabled);
|
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) {
|
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),
|
: device_(nullptr),
|
||||||
window_(nullptr),
|
window_(nullptr),
|
||||||
queue_(),
|
queue_(),
|
||||||
stats_(),
|
|
||||||
config_(),
|
config_(),
|
||||||
currentBlend_(rhi::BlendState::alphaBlend()),
|
currentBlend_(rhi::BlendState::alphaBlend()),
|
||||||
viewport_(),
|
viewport_(),
|
||||||
|
|
@ -23,7 +22,6 @@ RenderContext::RenderContext(const RenderContextConfig& config)
|
||||||
: device_(nullptr),
|
: device_(nullptr),
|
||||||
window_(nullptr),
|
window_(nullptr),
|
||||||
queue_(),
|
queue_(),
|
||||||
stats_(),
|
|
||||||
config_(config),
|
config_(config),
|
||||||
currentBlend_(rhi::BlendState::alphaBlend()),
|
currentBlend_(rhi::BlendState::alphaBlend()),
|
||||||
viewport_(),
|
viewport_(),
|
||||||
|
|
@ -100,7 +98,6 @@ void RenderContext::beginFrame() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats_.reset();
|
|
||||||
device_->beginFrame();
|
device_->beginFrame();
|
||||||
device_->resetStats();
|
device_->resetStats();
|
||||||
|
|
||||||
|
|
@ -244,13 +241,6 @@ void RenderContext::flushQueue() {
|
||||||
const auto& commands = queue_.getCommands();
|
const auto& commands = queue_.getCommands();
|
||||||
const RenderQueueStats& queueStats = queue_.getStats();
|
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();
|
queue_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,11 +272,4 @@ void RenderContext::initDefaultState() {
|
||||||
scissorEnabled_ = false;
|
scissorEnabled_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderContext::resetStats() {
|
|
||||||
stats_.reset();
|
|
||||||
if (device_) {
|
|
||||||
device_->resetStats();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
#include <extra2d/render/renderer.h>
|
#include <extra2d/render/renderer.h>
|
||||||
|
|
||||||
#include <extra2d/platform/iwindow.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/resources/shader_manager.h>
|
||||||
#include <extra2d/scene/scene.h>
|
#include <extra2d/scene/scene.h>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
Renderer::Renderer()
|
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)
|
Renderer::Renderer(const RendererConfig &config)
|
||||||
: window_(nullptr), config_(config), width_(0), height_(0),
|
: window_(nullptr), config_(config), width_(0), height_(0), initialized_(false),
|
||||||
initialized_(false) {}
|
projectionMatrix_(1.0f), viewMatrix_(1.0f), stats_(),
|
||||||
|
sortKey_(0), layer_(0), blendState_(rhi::BlendState::alphaBlend()),
|
||||||
|
inBatch_(false) {}
|
||||||
|
|
||||||
Renderer::~Renderer() { shutdown(); }
|
Renderer::~Renderer() { shutdown(); }
|
||||||
|
|
||||||
|
|
@ -38,36 +43,24 @@ bool Renderer::init(IWindow *window, const RendererConfig &config) {
|
||||||
viewportAdapter_.setConfig(config.viewportConfig);
|
viewportAdapter_.setConfig(config.viewportConfig);
|
||||||
viewportAdapter_.update(width_, height_);
|
viewportAdapter_.update(width_, height_);
|
||||||
|
|
||||||
RenderBackendConfig backendConfig;
|
device_ = rhi::RHIDevice::create(config.api);
|
||||||
backendConfig.api = config.api;
|
if (!device_ || !device_->init(window)) {
|
||||||
backendConfig.vsync = config.vsync;
|
|
||||||
backendConfig.maxBatchSize = config.maxBatchSize;
|
|
||||||
backendConfig.enableDebug = config.enableDebug;
|
|
||||||
|
|
||||||
backend_ = BackendFactory::createBackendForAPI(config.api);
|
|
||||||
if (!backend_ || !backend_->init(window, backendConfig)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderContextConfig contextConfig;
|
spriteBatcher_ = makeUnique<SpriteBatcher>();
|
||||||
contextConfig.maxBatchSize = config.maxBatchSize;
|
SpriteBatcherConfig batcherConfig;
|
||||||
contextConfig.preferredAPI = config.api;
|
batcherConfig.maxBatchSize = config.maxBatchSize;
|
||||||
|
if (!spriteBatcher_->init(device_)) {
|
||||||
context_ = makeUnique<RenderContext>(contextConfig);
|
|
||||||
if (!context_->init(window, config.api)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& shaderManager = ShaderManager::getInstance();
|
renderQueue_ = makeUnique<RenderQueue>();
|
||||||
if (!shaderManager.isInitialized()) {
|
|
||||||
if (!shaderManager.init(context_->getDevice(), "shaders")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!createBatchers()) {
|
projectionMatrix_ = glm::ortho(0.0f, static_cast<float>(width_),
|
||||||
return false;
|
static_cast<float>(height_), 0.0f,
|
||||||
}
|
-1.0f, 1.0f);
|
||||||
|
viewMatrix_ = glm::mat4(1.0f);
|
||||||
|
|
||||||
createDefaultCamera();
|
createDefaultCamera();
|
||||||
|
|
||||||
|
|
@ -80,11 +73,19 @@ void Renderer::shutdown() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
textBatcher_.reset();
|
if (spriteBatcher_) {
|
||||||
shapeBatcher_.reset();
|
spriteBatcher_->shutdown();
|
||||||
spriteBatcher_.reset();
|
spriteBatcher_.reset();
|
||||||
context_.reset();
|
}
|
||||||
backend_.reset();
|
|
||||||
|
if (renderQueue_) {
|
||||||
|
renderQueue_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_) {
|
||||||
|
device_->shutdown();
|
||||||
|
device_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
activeCamera_.reset();
|
activeCamera_.reset();
|
||||||
defaultCamera_.reset();
|
defaultCamera_.reset();
|
||||||
|
|
@ -96,88 +97,271 @@ void Renderer::shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::beginFrame(const Color &clearColor) {
|
void Renderer::beginFrame(const Color &clearColor) {
|
||||||
if (!initialized_) {
|
if (!initialized_ || !device_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backend_) {
|
stats_.reset();
|
||||||
backend_->beginFrame(clearColor);
|
device_->beginFrame();
|
||||||
}
|
device_->resetStats();
|
||||||
|
|
||||||
if (context_) {
|
rhi::ColorValue cv(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||||
context_->beginFrame();
|
device_->clearColor(cv);
|
||||||
context_->clear(clearColor);
|
|
||||||
}
|
device_->setViewport(rhi::Viewport(0.0f, 0.0f,
|
||||||
|
static_cast<float>(width_),
|
||||||
|
static_cast<float>(height_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::endFrame() {
|
void Renderer::endFrame() {
|
||||||
if (!initialized_) {
|
if (!initialized_ || !device_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spriteBatcher_) {
|
if (inBatch_) {
|
||||||
spriteBatcher_->end();
|
endSpriteBatch();
|
||||||
}
|
|
||||||
if (shapeBatcher_) {
|
|
||||||
shapeBatcher_->end();
|
|
||||||
}
|
|
||||||
if (textBatcher_) {
|
|
||||||
textBatcher_->end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context_) {
|
device_->endFrame();
|
||||||
context_->endFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_) {
|
|
||||||
backend_->endFrame();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::present() {
|
void Renderer::present() {
|
||||||
if (!initialized_) {
|
if (!initialized_ || !device_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backend_) {
|
device_->present();
|
||||||
backend_->present();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context_) {
|
|
||||||
context_->present();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderScene(Scene *scene) {
|
void Renderer::renderScene(Scene *scene) {
|
||||||
if (!initialized_ || !scene) {
|
if (!initialized_ || !scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Camera *camera = activeCamera_ ? activeCamera_.get() : defaultCamera_.get();
|
|
||||||
if (!camera) {
|
|
||||||
camera = scene->getActiveCamera();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderScene(scene, camera);
|
void Renderer::setViewport(int x, int y, int width, int height) {
|
||||||
}
|
if (!device_) {
|
||||||
|
|
||||||
void Renderer::renderScene(Scene *scene, Camera *camera) {
|
|
||||||
if (!initialized_ || !scene) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!camera) {
|
device_->setViewport(rhi::Viewport(
|
||||||
camera = defaultCamera_.get();
|
static_cast<float>(x),
|
||||||
|
static_cast<float>(y),
|
||||||
|
static_cast<float>(width),
|
||||||
|
static_cast<float>(height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (camera) {
|
void Renderer::setScissor(int x, int y, int width, int height) {
|
||||||
camera->setViewportAdapter(&viewportAdapter_);
|
if (!device_) {
|
||||||
camera->applyViewportAdapter();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyCameraTransform(camera);
|
device_->setScissorRect(rhi::ScissorRect(x, y,
|
||||||
|
static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height)));
|
||||||
|
}
|
||||||
|
|
||||||
scene->renderScene(*backend_);
|
void Renderer::setScissorEnabled(bool enabled) {
|
||||||
|
if (!device_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_->setScissorEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
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; }
|
void Renderer::setActiveCamera(Ptr<Camera> camera) { activeCamera_ = camera; }
|
||||||
|
|
@ -186,88 +370,26 @@ Ptr<Camera> Renderer::getActiveCamera() const {
|
||||||
return activeCamera_ ? activeCamera_ : defaultCamera_;
|
return activeCamera_ ? activeCamera_ : defaultCamera_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setViewport(int x, int y, int width, int height) {
|
rhi::GraphicsAPI Renderer::getAPI() const {
|
||||||
if (context_) {
|
if (!device_) {
|
||||||
context_->setViewport(x, y, width, height);
|
return rhi::GraphicsAPI::OpenGL;
|
||||||
}
|
|
||||||
if (backend_) {
|
|
||||||
backend_->setViewport(x, y, width, height);
|
|
||||||
}
|
}
|
||||||
|
return device_->getAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setScissor(int x, int y, int width, int height) {
|
const rhi::DeviceCaps &Renderer::getCaps() const {
|
||||||
if (context_) {
|
static rhi::DeviceCaps empty;
|
||||||
context_->setScissorRect(x, y, width, height);
|
return device_ ? device_->getCaps() : empty;
|
||||||
}
|
|
||||||
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 RenderStats &Renderer::getStats() const {
|
const RenderStats &Renderer::getStats() const {
|
||||||
if (backend_) {
|
return stats_;
|
||||||
return backend_->getStats();
|
|
||||||
}
|
|
||||||
if (context_) {
|
|
||||||
return context_->getStats();
|
|
||||||
}
|
|
||||||
static RenderStats empty;
|
|
||||||
return empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::resetStats() {
|
void Renderer::resetStats() {
|
||||||
if (backend_) {
|
stats_.reset();
|
||||||
backend_->resetStats();
|
if (device_) {
|
||||||
}
|
device_->resetStats();
|
||||||
if (context_) {
|
|
||||||
context_->resetStats();
|
|
||||||
}
|
|
||||||
if (spriteBatcher_) {
|
|
||||||
spriteBatcher_->resetStats();
|
|
||||||
}
|
|
||||||
if (shapeBatcher_) {
|
|
||||||
shapeBatcher_->resetStats();
|
|
||||||
}
|
|
||||||
if (textBatcher_) {
|
|
||||||
textBatcher_->resetStats();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,41 +399,6 @@ void Renderer::setConfig(const RendererConfig &config) {
|
||||||
updateViewportAdapter();
|
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() {
|
void Renderer::createDefaultCamera() {
|
||||||
float designWidth = viewportAdapter_.getDesignWidth();
|
float designWidth = viewportAdapter_.getDesignWidth();
|
||||||
float designHeight = viewportAdapter_.getDesignHeight();
|
float designHeight = viewportAdapter_.getDesignHeight();
|
||||||
|
|
@ -326,30 +413,6 @@ void Renderer::updateViewportAdapter() {
|
||||||
viewportAdapter_.update(width_, height_);
|
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) {
|
Ptr<Renderer> Renderer::create(const RendererConfig &config) {
|
||||||
return makePtr<Renderer>(config);
|
return makePtr<Renderer>(config);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -568,9 +568,9 @@ void Node::onUpdate(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染回调
|
* @brief 渲染回调
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void Node::onRender(RenderBackend &renderer) {
|
void Node::onRender(Renderer &renderer) {
|
||||||
if (!visible_)
|
if (!visible_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -620,9 +620,9 @@ void Node::update(float dt) { onUpdate(dt); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染节点
|
* @brief 渲染节点
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void Node::render(RenderBackend &renderer) {
|
void Node::render(Renderer &renderer) {
|
||||||
if (childrenOrderDirty_) {
|
if (childrenOrderDirty_) {
|
||||||
sortChildren();
|
sortChildren();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <extra2d/core/service_locator.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/render/core/render_command.h>
|
||||||
#include <extra2d/render/core/render_queue.h>
|
#include <extra2d/render/core/render_queue.h>
|
||||||
#include <extra2d/scene/scene.h>
|
#include <extra2d/scene/scene.h>
|
||||||
|
|
@ -46,11 +46,11 @@ void Scene::setViewportSize(const Size &size) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染场景
|
* @brief 渲染场景
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 如果场景不可见则直接返回,否则开始帧渲染、渲染内容并结束帧
|
* 如果场景不可见则直接返回,否则开始帧渲染、渲染内容并结束帧
|
||||||
*/
|
*/
|
||||||
void Scene::renderScene(RenderBackend &renderer) {
|
void Scene::renderScene(Renderer &renderer) {
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -61,11 +61,11 @@ void Scene::renderScene(RenderBackend &renderer) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染场景内容
|
* @brief 渲染场景内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 批量更新节点变换,开始精灵批处理并渲染
|
* 批量更新节点变换,开始精灵批处理并渲染
|
||||||
*/
|
*/
|
||||||
void Scene::renderContent(RenderBackend &renderer) {
|
void Scene::renderContent(Renderer &renderer) {
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <extra2d/app/application.h>
|
#include <extra2d/app/application.h>
|
||||||
#include <extra2d/core/service_locator.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/render/core/render_command.h>
|
||||||
#include <extra2d/platform/iinput.h>
|
#include <extra2d/platform/iinput.h>
|
||||||
#include <extra2d/scene/scene_manager.h>
|
#include <extra2d/scene/scene_manager.h>
|
||||||
|
|
@ -565,11 +565,11 @@ void SceneManager::update(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染当前场景
|
* @brief 渲染当前场景
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 使用当前场景的背景色清除帧缓冲并渲染场景内容
|
* 使用当前场景的背景色清除帧缓冲并渲染场景内容
|
||||||
*/
|
*/
|
||||||
void SceneManager::render(RenderBackend &renderer) {
|
void SceneManager::render(Renderer &renderer) {
|
||||||
Color clearColor = Colors::Black;
|
Color clearColor = Colors::Black;
|
||||||
if (!sceneStack_.empty()) {
|
if (!sceneStack_.empty()) {
|
||||||
clearColor = sceneStack_.top()->getBackgroundColor();
|
clearColor = sceneStack_.top()->getBackgroundColor();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <extra2d/render/core/render_command.h>
|
#include <extra2d/render/core/render_command.h>
|
||||||
#include <extra2d/scene/shape_node.h>
|
#include <extra2d/scene/shape_node.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
@ -259,13 +259,13 @@ Rect ShapeNode::getBounds() const {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制形状节点
|
* @brief 绘制形状节点
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 根据形状类型调用相应的渲染方法进行绘制
|
* 根据形状类型调用相应的渲染方法进行绘制
|
||||||
* 注意:变换矩阵已由 Node::onRender 通过 pushTransform 应用,
|
* 注意:变换矩阵已由 Node::onRender 通过 pushTransform 应用,
|
||||||
* 此处直接使用本地坐标即可。
|
* 此处直接使用本地坐标即可。
|
||||||
*/
|
*/
|
||||||
void ShapeNode::onDraw(RenderBackend &renderer) {
|
void ShapeNode::onDraw(Renderer &renderer) {
|
||||||
if (points_.empty()) {
|
if (points_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <extra2d/render/core/render_command.h>
|
#include <extra2d/render/core/render_command.h>
|
||||||
#include <extra2d/scene/sprite.h>
|
#include <extra2d/scene/sprite.h>
|
||||||
|
|
||||||
|
|
@ -122,11 +122,11 @@ Rect Sprite::getBounds() const {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制精灵
|
* @brief 绘制精灵
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 使用世界变换计算最终位置、缩放和旋转,然后绘制精灵
|
* 使用世界变换计算最终位置、缩放和旋转,然后绘制精灵
|
||||||
*/
|
*/
|
||||||
void Sprite::onDraw(RenderBackend &renderer) {
|
void Sprite::onDraw(Renderer &renderer) {
|
||||||
if (!texture_ || !texture_->isValid()) {
|
if (!texture_ || !texture_->isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ void Sprite::onDraw(RenderBackend &renderer) {
|
||||||
float worldScaleY =
|
float worldScaleY =
|
||||||
glm::length(glm::vec2(worldTransform[1][0], worldTransform[1][1]));
|
glm::length(glm::vec2(worldTransform[1][0], worldTransform[1][1]));
|
||||||
|
|
||||||
// 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸
|
// 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸
|
||||||
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
|
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
|
||||||
|
|
||||||
// Adjust source rect for flipping
|
// Adjust source rect for flipping
|
||||||
|
|
@ -201,7 +201,7 @@ void Sprite::generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
|
|
||||||
auto anchor = getAnchor();
|
auto anchor = getAnchor();
|
||||||
|
|
||||||
// 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸
|
// 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸
|
||||||
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
|
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
|
||||||
|
|
||||||
// 调整源矩形(翻转)
|
// 调整源矩形(翻转)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <extra2d/scene/transition_box_scene.h>
|
#include <extra2d/scene/transition_box_scene.h>
|
||||||
#include <extra2d/app/application.h>
|
#include <extra2d/app/application.h>
|
||||||
#include <extra2d/core/color.h>
|
#include <extra2d/core/color.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <extra2d/platform/iwindow.h>
|
#include <extra2d/platform/iwindow.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
@ -49,11 +49,11 @@ void TransitionBoxScene::updateTransition(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染过渡内容
|
* @brief 渲染过渡内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 先渲染新场景,然后绘制方块遮罩逐渐消失
|
* 先渲染新场景,然后绘制方块遮罩逐渐消失
|
||||||
*/
|
*/
|
||||||
void TransitionBoxScene::renderContent(RenderBackend &renderer) {
|
void TransitionBoxScene::renderContent(Renderer &renderer) {
|
||||||
auto &app = Application::get();
|
auto &app = Application::get();
|
||||||
float windowWidth = static_cast<float>(app.window()->width());
|
float windowWidth = static_cast<float>(app.window()->width());
|
||||||
float windowHeight = static_cast<float>(app.window()->height());
|
float windowHeight = static_cast<float>(app.window()->height());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <extra2d/app/application.h>
|
#include <extra2d/app/application.h>
|
||||||
#include <extra2d/core/service_locator.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/platform/iwindow.h>
|
||||||
#include <extra2d/scene/transition_fade_scene.h>
|
#include <extra2d/scene/transition_fade_scene.h>
|
||||||
#include <extra2d/services/logger_service.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();
|
auto &app = Application::get();
|
||||||
float windowWidth = static_cast<float>(app.window()->width());
|
float windowWidth = static_cast<float>(app.window()->width());
|
||||||
float windowHeight = static_cast<float>(app.window()->height());
|
float windowHeight = static_cast<float>(app.window()->height());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <extra2d/scene/transition_flip_scene.h>
|
#include <extra2d/scene/transition_flip_scene.h>
|
||||||
#include <extra2d/core/math_types.h>
|
#include <extra2d/core/math_types.h>
|
||||||
#include <extra2d/render/camera/camera.h>
|
#include <extra2d/render/camera/camera.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -46,11 +46,11 @@ void TransitionFlipScene::updateTransition(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染过渡内容
|
* @brief 渲染过渡内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的翻转角度
|
* 根据进度控制新旧场景的翻转角度
|
||||||
*/
|
*/
|
||||||
void TransitionFlipScene::renderContent(RenderBackend &renderer) {
|
void TransitionFlipScene::renderContent(Renderer &renderer) {
|
||||||
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
||||||
: -1.0f + (4.0f - 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/scene/transition_scale_scene.h>
|
||||||
#include <extra2d/render/camera/camera.h>
|
#include <extra2d/render/camera/camera.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -42,11 +42,11 @@ void TransitionScaleScene::updateTransition(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染过渡内容
|
* @brief 渲染过渡内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的缩放比例
|
* 根据进度控制新旧场景的缩放比例
|
||||||
*/
|
*/
|
||||||
void TransitionScaleScene::renderContent(RenderBackend &renderer) {
|
void TransitionScaleScene::renderContent(Renderer &renderer) {
|
||||||
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
||||||
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <extra2d/core/service_locator.h>
|
#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/scene/transition_scene.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
|
|
||||||
|
|
@ -115,20 +115,20 @@ void TransitionScene::cancel(bool immediate) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染过渡内容
|
* @brief 渲染过渡内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 默认先渲染退出场景,再渲染进入场景
|
* 默认先渲染退出场景,再渲染进入场景
|
||||||
*/
|
*/
|
||||||
void TransitionScene::renderContent(RenderBackend &renderer) {
|
void TransitionScene::renderContent(Renderer &renderer) {
|
||||||
drawOutScene(renderer);
|
drawOutScene(renderer);
|
||||||
drawInScene(renderer);
|
drawInScene(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制退出场景
|
* @brief 绘制退出场景
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void TransitionScene::drawOutScene(RenderBackend &renderer) {
|
void TransitionScene::drawOutScene(Renderer &renderer) {
|
||||||
if (outScene_) {
|
if (outScene_) {
|
||||||
outScene_->renderContent(renderer);
|
outScene_->renderContent(renderer);
|
||||||
}
|
}
|
||||||
|
|
@ -136,9 +136,9 @@ void TransitionScene::drawOutScene(RenderBackend &renderer) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制进入场景
|
* @brief 绘制进入场景
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*/
|
*/
|
||||||
void TransitionScene::drawInScene(RenderBackend &renderer) {
|
void TransitionScene::drawInScene(Renderer &renderer) {
|
||||||
if (inScene_) {
|
if (inScene_) {
|
||||||
inScene_->renderContent(renderer);
|
inScene_->renderContent(renderer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <extra2d/scene/transition_slide_scene.h>
|
#include <extra2d/scene/transition_slide_scene.h>
|
||||||
#include <extra2d/render/camera/camera.h>
|
#include <extra2d/render/camera/camera.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/renderer.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -45,11 +45,11 @@ void TransitionSlideScene::updateTransition(float dt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染过渡内容
|
* @brief 渲染过渡内容
|
||||||
* @param renderer 渲染后端引用
|
* @param renderer 渲染器引用
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的滑动位置
|
* 根据进度控制新旧场景的滑动位置
|
||||||
*/
|
*/
|
||||||
void TransitionSlideScene::renderContent(RenderBackend &renderer) {
|
void TransitionSlideScene::renderContent(Renderer &renderer) {
|
||||||
float screenWidth = 800.0f;
|
float screenWidth = 800.0f;
|
||||||
float screenHeight = 600.0f;
|
float screenHeight = 600.0f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <extra2d/services/scene_service.h>
|
#include <extra2d/services/scene_service.h>
|
||||||
|
#include <extra2d/render/renderer.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -68,7 +69,7 @@ bool SceneService::hasScene(const std::string &name) const {
|
||||||
return manager_.hasScene(name);
|
return manager_.hasScene(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneService::render(RenderBackend &renderer) {
|
void SceneService::render(Renderer &renderer) {
|
||||||
manager_.render(renderer);
|
manager_.render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ function define_extra2d_engine()
|
||||||
|
|
||||||
-- 渲染后端源文件
|
-- 渲染后端源文件
|
||||||
local render_backend = get_render_backend()
|
local render_backend = get_render_backend()
|
||||||
-- 渲染后端工厂
|
|
||||||
add_files("Extra2D/src/render/core/backend_factory.cpp")
|
|
||||||
if render_backend == "vulkan" then
|
if render_backend == "vulkan" then
|
||||||
add_files("Extra2D/src/render/backends/vulkan/*.cpp")
|
add_files("Extra2D/src/render/backends/vulkan/*.cpp")
|
||||||
add_defines("E2D_BACKEND_VULKAN")
|
add_defines("E2D_BACKEND_VULKAN")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue