refactor(渲染器): 将RenderBackend重命名为Renderer并重构相关代码
重构渲染器接口命名,将RenderBackend统一更名为Renderer,同时更新所有相关文件和文档引用。此变更旨在提供更简洁清晰的接口命名,并保持代码一致性。 - 重命名RenderBackend类为Renderer - 更新所有相关文件中的类型引用和文档 - 保持原有功能不变,仅进行命名和结构调整 - 修复因重命名导致的编译错误和警告
This commit is contained in:
parent
b34df8bdd1
commit
9e911db53c
|
|
@ -9,7 +9,7 @@
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
class GLFWWindow;
|
class GLFWWindow;
|
||||||
class RenderBackend;
|
class Renderer;
|
||||||
class WindowModule;
|
class WindowModule;
|
||||||
class RenderModule;
|
class RenderModule;
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ public:
|
||||||
* @brief 获取渲染器
|
* @brief 获取渲染器
|
||||||
* @return 渲染器指针
|
* @return 渲染器指针
|
||||||
*/
|
*/
|
||||||
RenderBackend *renderer();
|
Renderer *renderer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 进入场景
|
* @brief 进入场景
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@
|
||||||
// Graphics
|
// Graphics
|
||||||
#include <extra2d/graphics/camera/camera.h>
|
#include <extra2d/graphics/camera/camera.h>
|
||||||
#include <extra2d/graphics/camera/viewport_adapter.h>
|
#include <extra2d/graphics/camera/viewport_adapter.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_module.h>
|
#include <extra2d/graphics/core/render_module.h>
|
||||||
#include <extra2d/graphics/core/render_target.h>
|
#include <extra2d/graphics/core/render_target.h>
|
||||||
#include <extra2d/graphics/memory/vram_manager.h>
|
#include <extra2d/graphics/memory/vram_manager.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/graphics/shader/shader_manager.h>
|
#include <extra2d/graphics/shader/shader_manager.h>
|
||||||
#include <extra2d/graphics/texture/font.h>
|
#include <extra2d/graphics/texture/font.h>
|
||||||
#include <extra2d/graphics/texture/texture.h>
|
#include <extra2d/graphics/texture/texture.h>
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <extra2d/core/color.h>
|
|
||||||
#include <extra2d/core/math_types.h>
|
|
||||||
#include <extra2d/core/types.h>
|
|
||||||
#include <extra2d/graphics/resources/pipeline.h>
|
|
||||||
#include <glm/mat4x4.hpp>
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
// 前向声明
|
|
||||||
class GLFWWindow;
|
|
||||||
class Texture;
|
|
||||||
class FontAtlas;
|
|
||||||
class Shader;
|
|
||||||
|
|
||||||
// BlendMode 定义在 pipeline.h 中
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 渲染后端抽象接口
|
|
||||||
// ============================================================================
|
|
||||||
class RenderBackend {
|
|
||||||
public:
|
|
||||||
virtual ~RenderBackend() = default;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 生命周期
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual bool init(GLFWWindow* window) = 0;
|
|
||||||
virtual void shutdown() = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 帧管理
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void beginFrame(const Color &clearColor) = 0;
|
|
||||||
virtual void endFrame() = 0;
|
|
||||||
virtual void setViewport(int x, int y, int width, int height) = 0;
|
|
||||||
virtual void setVSync(bool enabled) = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 状态设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void setBlendMode(BlendMode mode) = 0;
|
|
||||||
virtual void setViewProjection(const glm::mat4 &matrix) = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 变换矩阵栈
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void pushTransform(const glm::mat4 &transform) = 0;
|
|
||||||
virtual void popTransform() = 0;
|
|
||||||
virtual glm::mat4 getCurrentTransform() const = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 纹理
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual Ptr<Texture> createTexture(int width, int height,
|
|
||||||
const uint8_t *pixels, int channels) = 0;
|
|
||||||
virtual Ptr<Texture> loadTexture(const std::string &filepath) = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 精灵批渲染
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* @brief 开始手动精灵批处理(高级用法)
|
|
||||||
* @note 一般情况下不需要调用,drawSprite/drawText 会自动管理批处理
|
|
||||||
*/
|
|
||||||
virtual void beginSpriteBatch() = 0;
|
|
||||||
virtual void drawSprite(const Texture &texture, const Rect &destRect,
|
|
||||||
const Rect &srcRect, const Color &tint,
|
|
||||||
float rotation, const Vec2 &anchor) = 0;
|
|
||||||
virtual void drawSprite(const Texture &texture, const Vec2 &position,
|
|
||||||
const Color &tint) = 0;
|
|
||||||
virtual void endSpriteBatch() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 立即提交当前批处理
|
|
||||||
* @note 手动控制批处理提交时机,一般情况下不需要调用
|
|
||||||
*/
|
|
||||||
virtual void flush() = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 形状渲染
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
|
||||||
float width = 1.0f) = 0;
|
|
||||||
virtual void drawRect(const Rect &rect, const Color &color,
|
|
||||||
float width = 1.0f) = 0;
|
|
||||||
virtual void fillRect(const Rect &rect, const Color &color) = 0;
|
|
||||||
virtual void drawCircle(const Vec2 ¢er, float radius, const Color &color,
|
|
||||||
int segments = 32, float width = 1.0f) = 0;
|
|
||||||
virtual void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
|
||||||
int segments = 32) = 0;
|
|
||||||
virtual void drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
|
||||||
const Color &color, float width = 1.0f) = 0;
|
|
||||||
virtual void fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
|
||||||
const Color &color) = 0;
|
|
||||||
virtual void drawPolygon(const std::vector<Vec2> &points, const Color &color,
|
|
||||||
float width = 1.0f) = 0;
|
|
||||||
virtual void fillPolygon(const std::vector<Vec2> &points,
|
|
||||||
const Color &color) = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 文字渲染
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual Ptr<FontAtlas> createFontAtlas(const std::string &filepath,
|
|
||||||
int fontSize, bool useSDF = false) = 0;
|
|
||||||
virtual void drawText(const FontAtlas &font, const std::string &text,
|
|
||||||
const Vec2 &position, const Color &color) = 0;
|
|
||||||
virtual void drawText(const FontAtlas &font, const std::string &text, float x,
|
|
||||||
float y, const Color &color) = 0;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 统计信息
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
struct Stats {
|
|
||||||
uint32_t drawCalls = 0;
|
|
||||||
uint32_t triangleCount = 0;
|
|
||||||
uint32_t textureBinds = 0;
|
|
||||||
uint32_t shaderBinds = 0;
|
|
||||||
};
|
|
||||||
virtual Stats getStats() const = 0;
|
|
||||||
virtual void resetStats() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <extra2d/core/module.h>
|
#include <extra2d/core/module.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/platform/window_module.h>
|
#include <extra2d/platform/window_module.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
@ -12,67 +12,62 @@ namespace extra2d {
|
||||||
* @brief 渲染模块配置结构
|
* @brief 渲染模块配置结构
|
||||||
*/
|
*/
|
||||||
struct RenderCfg {
|
struct RenderCfg {
|
||||||
int targetFPS;
|
int targetFPS;
|
||||||
bool vsync;
|
bool vsync;
|
||||||
int multisamples;
|
int multisamples;
|
||||||
int priority;
|
int priority;
|
||||||
|
|
||||||
RenderCfg()
|
RenderCfg() : targetFPS(60), vsync(true), multisamples(0), priority(10) {}
|
||||||
: targetFPS(60)
|
|
||||||
, vsync(true)
|
|
||||||
, multisamples(0)
|
|
||||||
, priority(10)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 渲染模块
|
* @brief 渲染模块
|
||||||
* 管理 OpenGL 渲染后端
|
* 管理 OpenGL 渲染器
|
||||||
*/
|
*/
|
||||||
class RenderModule : public Module {
|
class RenderModule : public Module {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief 构造函数(Lambda 配置)
|
* @brief 构造函数(Lambda 配置)
|
||||||
* @param configFn 配置函数
|
* @param configFn 配置函数
|
||||||
*/
|
*/
|
||||||
explicit RenderModule(std::function<void(RenderCfg&)> configFn);
|
explicit RenderModule(std::function<void(RenderCfg &)> configFn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 析构函数
|
* @brief 析构函数
|
||||||
*/
|
*/
|
||||||
~RenderModule() override;
|
~RenderModule() override;
|
||||||
|
|
||||||
bool init() override;
|
bool init() override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
bool ok() const override { return initialized_; }
|
bool ok() const override { return initialized_; }
|
||||||
const char* name() const override { return "render"; }
|
const char *name() const override { return "render"; }
|
||||||
int priority() const override { return cfg_.priority; }
|
int priority() const override { return cfg_.priority; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取依赖
|
* @brief 获取依赖
|
||||||
* @return 依赖模块类型列表
|
* @return 依赖模块类型列表
|
||||||
*/
|
*/
|
||||||
std::vector<std::type_index> deps() const override {
|
std::vector<std::type_index> deps() const override {
|
||||||
return {std::type_index(typeid(WindowModule))};
|
return {std::type_index(typeid(WindowModule))};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 是否允许并行初始化
|
* @brief 是否允许并行初始化
|
||||||
* RenderModule 需要 OpenGL 上下文,必须在主线程初始化
|
* RenderModule 需要 OpenGL 上下文,必须在主线程初始化
|
||||||
* @return 不允许并行初始化返回 false
|
* @return 不允许并行初始化返回 false
|
||||||
*/
|
*/
|
||||||
bool allowParallelInit() const override { return false; }
|
bool allowParallelInit() const override { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取渲染器
|
* @brief 获取渲染器
|
||||||
* @return 渲染后端指针
|
* @return 渲染器指针
|
||||||
*/
|
*/
|
||||||
RenderBackend* renderer() const { return renderer_.get(); }
|
Renderer *renderer() const { return renderer_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderCfg cfg_;
|
RenderCfg cfg_;
|
||||||
UniquePtr<RenderBackend> renderer_;
|
UniquePtr<Renderer> renderer_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,132 +1,111 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
#include <extra2d/core/color.h>
|
||||||
|
#include <extra2d/core/math_types.h>
|
||||||
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/graphics/opengl/gl_buffer.h>
|
#include <extra2d/graphics/opengl/gl_buffer.h>
|
||||||
#include <extra2d/graphics/opengl/gl_framebuffer.h>
|
#include <extra2d/graphics/opengl/gl_framebuffer.h>
|
||||||
#include <extra2d/graphics/opengl/gl_pipeline.h>
|
#include <extra2d/graphics/opengl/gl_pipeline.h>
|
||||||
#include <extra2d/graphics/opengl/gl_sprite_batch.h>
|
#include <extra2d/graphics/opengl/gl_sprite_batch.h>
|
||||||
|
#include <extra2d/graphics/resources/pipeline.h>
|
||||||
#include <extra2d/graphics/shader/shader_interface.h>
|
#include <extra2d/graphics/shader/shader_interface.h>
|
||||||
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
// 前向声明
|
|
||||||
class GLFWWindow;
|
class GLFWWindow;
|
||||||
class GLContext;
|
class GLContext;
|
||||||
class GLFramebuffer;
|
class GLFramebuffer;
|
||||||
|
class FontAtlas;
|
||||||
|
|
||||||
// ============================================================================
|
/**
|
||||||
// OpenGL 渲染器实现
|
* @brief 渲染统计信息
|
||||||
// ============================================================================
|
*/
|
||||||
class GLRenderer : public RenderBackend {
|
struct RenderStats {
|
||||||
|
uint32_t drawCalls = 0;
|
||||||
|
uint32_t triangleCount = 0;
|
||||||
|
uint32_t textureBinds = 0;
|
||||||
|
uint32_t shaderBinds = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OpenGL 渲染器实现
|
||||||
|
*/
|
||||||
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
GLRenderer();
|
Renderer();
|
||||||
~GLRenderer() override;
|
~Renderer();
|
||||||
|
|
||||||
// RenderBackend 接口实现
|
bool init(GLFWWindow *window);
|
||||||
bool init(GLFWWindow *window) override;
|
void shutdown();
|
||||||
void shutdown() override;
|
|
||||||
|
|
||||||
void beginFrame(const Color &clearColor) override;
|
void beginFrame(const Color &clearColor);
|
||||||
void endFrame() override;
|
void endFrame();
|
||||||
void setViewport(int x, int y, int width, int height) override;
|
void setViewport(int x, int y, int width, int height);
|
||||||
void setVSync(bool enabled) override;
|
void setVSync(bool enabled);
|
||||||
|
|
||||||
void setBlendMode(BlendMode mode) override;
|
void setBlendMode(BlendMode mode);
|
||||||
void setViewProjection(const glm::mat4 &matrix) override;
|
void setViewProjection(const glm::mat4 &matrix);
|
||||||
|
|
||||||
// 变换矩阵栈
|
void pushTransform(const glm::mat4 &transform);
|
||||||
void pushTransform(const glm::mat4 &transform) override;
|
void popTransform();
|
||||||
void popTransform() override;
|
glm::mat4 getCurrentTransform() const;
|
||||||
glm::mat4 getCurrentTransform() const override;
|
|
||||||
|
|
||||||
Ptr<Texture> createTexture(int width, int height, const uint8_t *pixels,
|
Ptr<Texture> createTexture(int width, int height, const uint8_t *pixels,
|
||||||
int channels) override;
|
int channels);
|
||||||
Ptr<Texture> loadTexture(const std::string &filepath) override;
|
Ptr<Texture> loadTexture(const std::string &filepath);
|
||||||
|
|
||||||
void beginSpriteBatch() override;
|
void beginSpriteBatch();
|
||||||
void drawSprite(const Texture &texture, const Rect &destRect,
|
void drawSprite(const Texture &texture, const Rect &destRect,
|
||||||
const Rect &srcRect, const Color &tint, float rotation,
|
const Rect &srcRect, const Color &tint, float rotation,
|
||||||
const Vec2 &anchor) override;
|
const Vec2 &anchor);
|
||||||
void drawSprite(const Texture &texture, const Vec2 &position,
|
void drawSprite(const Texture &texture, const Vec2 &position,
|
||||||
const Color &tint) override;
|
const Color &tint);
|
||||||
void endSpriteBatch() override;
|
void endSpriteBatch();
|
||||||
void flush() override;
|
void flush();
|
||||||
|
|
||||||
void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
void drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||||
float width) override;
|
float width = 1.0f);
|
||||||
void drawRect(const Rect &rect, const Color &color, float width) override;
|
void drawRect(const Rect &rect, const Color &color, float width = 1.0f);
|
||||||
void fillRect(const Rect &rect, const Color &color) override;
|
void fillRect(const Rect &rect, const Color &color);
|
||||||
void drawCircle(const Vec2 ¢er, float radius, const Color &color,
|
void drawCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||||
int segments, float width) override;
|
int segments = 32, float width = 1.0f);
|
||||||
void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
void fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||||
int segments) override;
|
int segments = 32);
|
||||||
void drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
void drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
const Color &color, float width) override;
|
const Color &color, float width = 1.0f);
|
||||||
void fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
void fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
const Color &color) override;
|
const Color &color);
|
||||||
void drawPolygon(const std::vector<Vec2> &points, const Color &color,
|
void drawPolygon(const std::vector<Vec2> &points, const Color &color,
|
||||||
float width) override;
|
float width = 1.0f);
|
||||||
void fillPolygon(const std::vector<Vec2> &points,
|
void fillPolygon(const std::vector<Vec2> &points, const Color &color);
|
||||||
const Color &color) override;
|
|
||||||
|
|
||||||
Ptr<FontAtlas> createFontAtlas(const std::string &filepath, int fontSize,
|
Ptr<FontAtlas> createFontAtlas(const std::string &filepath, int fontSize,
|
||||||
bool useSDF = false) override;
|
bool useSDF = false);
|
||||||
void drawText(const FontAtlas &font, const std::string &text,
|
void drawText(const FontAtlas &font, const std::string &text,
|
||||||
const Vec2 &position, const Color &color) override;
|
const Vec2 &position, const Color &color);
|
||||||
void drawText(const FontAtlas &font, const std::string &text, float x,
|
void drawText(const FontAtlas &font, const std::string &text, float x,
|
||||||
float y, const Color &color) override;
|
float y, const Color &color);
|
||||||
|
|
||||||
Stats getStats() const override { return stats_; }
|
RenderStats getStats() const { return stats_; }
|
||||||
void resetStats() override;
|
void resetStats();
|
||||||
|
|
||||||
// GLFramebuffer 相关方法
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 创建帧缓冲对象
|
|
||||||
* @param desc 帧缓冲描述
|
|
||||||
* @return 创建的帧缓冲智能指针
|
|
||||||
*/
|
|
||||||
Ptr<GLFramebuffer> createFramebuffer(const FramebufferDesc &desc);
|
Ptr<GLFramebuffer> createFramebuffer(const FramebufferDesc &desc);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 绑定帧缓冲(作为渲染目标)
|
|
||||||
* @param framebuffer 帧缓冲对象指针,传入 nullptr 则绑定默认帧缓冲
|
|
||||||
*/
|
|
||||||
void bindFramebuffer(GLFramebuffer *framebuffer);
|
void bindFramebuffer(GLFramebuffer *framebuffer);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 解绑帧缓冲(恢复到默认帧缓冲)
|
|
||||||
*/
|
|
||||||
void unbindFramebuffer();
|
void unbindFramebuffer();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取默认帧缓冲
|
|
||||||
* @return 默认帧缓冲智能指针
|
|
||||||
*/
|
|
||||||
Ptr<GLFramebuffer> getDefaultFramebuffer() const;
|
Ptr<GLFramebuffer> getDefaultFramebuffer() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 清除当前绑定的帧缓冲
|
|
||||||
* @param color 清除颜色
|
|
||||||
* @param clearColor 是否清除颜色缓冲
|
|
||||||
* @param clearDepth 是否清除深度缓冲
|
|
||||||
* @param clearStencil 是否清除模板缓冲
|
|
||||||
*/
|
|
||||||
void clearFramebuffer(const Color &color, bool clearColor = true,
|
void clearFramebuffer(const Color &color, bool clearColor = true,
|
||||||
bool clearDepth = true, bool clearStencil = false);
|
bool clearDepth = true, bool clearStencil = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 形状批处理常量
|
|
||||||
static constexpr size_t MAX_CIRCLE_SEGMENTS = 128;
|
static constexpr size_t MAX_CIRCLE_SEGMENTS = 128;
|
||||||
static constexpr size_t MAX_SHAPE_VERTICES = 8192; // 最大形状顶点数
|
static constexpr size_t MAX_SHAPE_VERTICES = 8192;
|
||||||
static constexpr size_t MAX_LINE_VERTICES = 16384; // 最大线条顶点数
|
static constexpr size_t MAX_LINE_VERTICES = 16384;
|
||||||
|
|
||||||
// 形状顶点结构(包含颜色)
|
|
||||||
struct ShapeVertex {
|
struct ShapeVertex {
|
||||||
float x, y;
|
float x, y;
|
||||||
float r, g, b, a;
|
float r, g, b, a;
|
||||||
|
|
@ -135,45 +114,40 @@ private:
|
||||||
GLFWWindow *window_;
|
GLFWWindow *window_;
|
||||||
GLSpriteBatch spriteBatch_;
|
GLSpriteBatch spriteBatch_;
|
||||||
Ptr<IShader> shapeShader_;
|
Ptr<IShader> shapeShader_;
|
||||||
Ptr<IShader> sdfFontShader_; // SDF字体专用着色器
|
Ptr<IShader> sdfFontShader_;
|
||||||
|
|
||||||
GLuint shapeVao_; // 形状 VAO(手动管理,用于顶点属性配置)
|
GLuint shapeVao_;
|
||||||
GLBuffer shapeBuffer_; // 形状 VBO(使用 GLBuffer 管理)
|
GLBuffer shapeBuffer_;
|
||||||
GLuint lineVao_; // 线条 VAO(手动管理,用于顶点属性配置)
|
GLuint lineVao_;
|
||||||
GLBuffer lineBuffer_; // 线条 VBO(使用 GLBuffer 管理)
|
GLBuffer lineBuffer_;
|
||||||
|
|
||||||
glm::mat4 viewProjection_;
|
glm::mat4 viewProjection_;
|
||||||
std::vector<glm::mat4> transformStack_;
|
std::vector<glm::mat4> transformStack_;
|
||||||
Stats stats_;
|
RenderStats stats_;
|
||||||
bool vsync_;
|
bool vsync_;
|
||||||
|
|
||||||
// 形状批处理缓冲区(预分配,避免每帧内存分配)
|
|
||||||
std::array<ShapeVertex, MAX_SHAPE_VERTICES> shapeVertexCache_;
|
std::array<ShapeVertex, MAX_SHAPE_VERTICES> shapeVertexCache_;
|
||||||
size_t shapeVertexCount_ = 0;
|
size_t shapeVertexCount_ = 0;
|
||||||
GLenum currentShapeMode_ = GL_TRIANGLES;
|
GLenum currentShapeMode_ = GL_TRIANGLES;
|
||||||
|
|
||||||
// 线条批处理缓冲区
|
|
||||||
std::array<ShapeVertex, MAX_LINE_VERTICES> lineVertexCache_;
|
std::array<ShapeVertex, MAX_LINE_VERTICES> lineVertexCache_;
|
||||||
size_t lineVertexCount_ = 0;
|
size_t lineVertexCount_ = 0;
|
||||||
float currentLineWidth_ = 1.0f;
|
float currentLineWidth_ = 1.0f;
|
||||||
|
|
||||||
// OpenGL 管线状态管理
|
|
||||||
GLPipeline pipeline_;
|
GLPipeline pipeline_;
|
||||||
|
|
||||||
// 自动批处理状态
|
bool batchActive_ = false;
|
||||||
bool batchActive_ = false; // 批处理是否激活
|
bool autoBatchEnabled_ = true;
|
||||||
bool autoBatchEnabled_ = true; // 是否启用自动批处理
|
const Texture *currentBatchTexture_ = nullptr;
|
||||||
const Texture *currentBatchTexture_ = nullptr; // 当前批处理的纹理
|
std::vector<SpriteData> pendingSprites_;
|
||||||
std::vector<SpriteData> pendingSprites_; // 待提交的精灵
|
static constexpr size_t MAX_BATCH_SPRITES = 1000;
|
||||||
static constexpr size_t MAX_BATCH_SPRITES = 1000; // 最大批处理精灵数
|
|
||||||
|
|
||||||
// 帧缓冲管理
|
mutable Ptr<GLFramebuffer> defaultFramebuffer_;
|
||||||
mutable Ptr<GLFramebuffer> defaultFramebuffer_; // 默认帧缓冲(延迟创建)
|
GLFramebuffer *currentFramebuffer_ = nullptr;
|
||||||
GLFramebuffer *currentFramebuffer_ = nullptr; // 当前绑定的帧缓冲
|
|
||||||
|
|
||||||
void initShapeRendering();
|
void initShapeRendering();
|
||||||
void ensureBatchActive(); // 确保批处理已激活
|
void ensureBatchActive();
|
||||||
void submitPendingSprites(); // 提交待处理的精灵
|
void submitPendingSprites();
|
||||||
void flushShapeBatch();
|
void flushShapeBatch();
|
||||||
void flushLineBatch();
|
void flushLineBatch();
|
||||||
void addShapeVertex(float x, float y, const Color &color);
|
void addShapeVertex(float x, float y, const Color &color);
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
// 前向声明
|
|
||||||
class Scene;
|
class Scene;
|
||||||
class RenderBackend;
|
class Renderer;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 纹理加载选项
|
// 纹理加载选项
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,15 @@
|
||||||
#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/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
// 前向声明
|
|
||||||
class Scene;
|
class Scene;
|
||||||
class RenderBackend;
|
class Renderer;
|
||||||
struct RenderCommand;
|
struct RenderCommand;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -137,7 +136,7 @@ public:
|
||||||
virtual void onEnter();
|
virtual void onEnter();
|
||||||
virtual void onExit();
|
virtual void onExit();
|
||||||
virtual void onUpdate(float dt);
|
virtual void onUpdate(float dt);
|
||||||
virtual void onRender(RenderBackend &renderer);
|
virtual void onRender(Renderer &renderer);
|
||||||
virtual void onAttachToScene(Scene *scene);
|
virtual void onAttachToScene(Scene *scene);
|
||||||
virtual void onDetachFromScene();
|
virtual void onDetachFromScene();
|
||||||
|
|
||||||
|
|
@ -155,7 +154,7 @@ public:
|
||||||
// 内部方法
|
// 内部方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void render(RenderBackend &renderer);
|
void render(Renderer &renderer);
|
||||||
void sortChildren();
|
void sortChildren();
|
||||||
|
|
||||||
bool isRunning() const { return running_; }
|
bool isRunning() const { return running_; }
|
||||||
|
|
@ -167,7 +166,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 子类重写
|
// 子类重写
|
||||||
virtual void onDraw(RenderBackend &renderer) {}
|
virtual void onDraw(Renderer &renderer) {}
|
||||||
virtual void onUpdateNode(float dt) {}
|
virtual void onUpdateNode(float dt) {}
|
||||||
virtual void generateRenderCommand(std::vector<RenderCommand> &commands,
|
virtual void generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
int zOrder) {};
|
int zOrder) {};
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 渲染和更新
|
// 渲染和更新
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void renderScene(RenderBackend &renderer);
|
void renderScene(Renderer &renderer);
|
||||||
virtual void renderContent(RenderBackend &renderer);
|
virtual void renderContent(Renderer &renderer);
|
||||||
void updateScene(float dt);
|
void updateScene(float dt);
|
||||||
void collectRenderCommands(std::vector<RenderCommand> &commands,
|
void collectRenderCommands(std::vector<RenderCommand> &commands,
|
||||||
int parentZOrder = 0) override;
|
int parentZOrder = 0) override;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 静态创建方法
|
// 静态创建方法
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,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);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -143,7 +143,8 @@ private:
|
||||||
* @param inScene 目标场景
|
* @param inScene 目标场景
|
||||||
* @return 过渡场景智能指针
|
* @return 过渡场景智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<TransitionScene> createTransitionScene(TransitionType type, float duration,
|
Ptr<TransitionScene> createTransitionScene(TransitionType type,
|
||||||
|
float duration,
|
||||||
Ptr<Scene> inScene);
|
Ptr<Scene> inScene);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,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;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ protected:
|
||||||
* @brief 渲染内容
|
* @brief 渲染内容
|
||||||
* 根据进度控制新旧场景的显示
|
* 根据进度控制新旧场景的显示
|
||||||
*/
|
*/
|
||||||
void renderContent(RenderBackend &renderer) override;
|
void renderContent(Renderer &renderer) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
@ -52,8 +52,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void hideOutShowIn();
|
void hideOutShowIn();
|
||||||
|
|
||||||
Color maskColor_; // 遮罩颜色
|
Color maskColor_; // 遮罩颜色
|
||||||
bool hasSwitched_ = false; // 是否已经切换场景
|
bool hasSwitched_ = false; // 是否已经切换场景
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -28,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:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,9 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 设置过渡完成回调
|
* @brief 设置过渡完成回调
|
||||||
*/
|
*/
|
||||||
void setFinishCallback(FinishCallback callback) { finishCallback_ = callback; }
|
void setFinishCallback(FinishCallback callback) {
|
||||||
|
finishCallback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取过渡持续时间
|
* @brief 获取过渡持续时间
|
||||||
|
|
@ -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 更新过渡进度(子类重写此方法更新动画)
|
||||||
|
|
@ -136,11 +138,11 @@ protected:
|
||||||
bool isFinished_ = false;
|
bool isFinished_ = false;
|
||||||
bool isCancelled_ = false;
|
bool isCancelled_ = false;
|
||||||
|
|
||||||
Ptr<Scene> inScene_; // 要进入的场景
|
Ptr<Scene> inScene_; // 要进入的场景
|
||||||
Ptr<Scene> outScene_; // 要退出的场景
|
Ptr<Scene> outScene_; // 要退出的场景
|
||||||
|
|
||||||
FinishCallback finishCallback_;
|
FinishCallback finishCallback_;
|
||||||
FinishCallback cancelCallback_; // 取消回调
|
FinishCallback cancelCallback_; // 取消回调
|
||||||
|
|
||||||
friend class SceneManager;
|
friend class SceneManager;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,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:
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <extra2d/core/service_interface.h>
|
#include <extra2d/core/service_interface.h>
|
||||||
#include <extra2d/core/service_locator.h>
|
#include <extra2d/core/service_locator.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/scene/scene_manager.h>
|
#include <extra2d/scene/scene_manager.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -12,33 +13,34 @@ namespace extra2d {
|
||||||
*/
|
*/
|
||||||
class ISceneService : public IService {
|
class ISceneService : public IService {
|
||||||
public:
|
public:
|
||||||
virtual ~ISceneService() = default;
|
virtual ~ISceneService() = default;
|
||||||
|
|
||||||
virtual void runWithScene(Ptr<Scene> scene) = 0;
|
virtual void runWithScene(Ptr<Scene> scene) = 0;
|
||||||
virtual void replaceScene(Ptr<Scene> scene) = 0;
|
virtual void replaceScene(Ptr<Scene> scene) = 0;
|
||||||
virtual void pushScene(Ptr<Scene> scene) = 0;
|
virtual void pushScene(Ptr<Scene> scene) = 0;
|
||||||
virtual void popScene() = 0;
|
virtual void popScene() = 0;
|
||||||
virtual void popToRootScene() = 0;
|
virtual void popToRootScene() = 0;
|
||||||
virtual void popToScene(const std::string& name) = 0;
|
virtual void popToScene(const std::string &name) = 0;
|
||||||
|
|
||||||
virtual Ptr<Scene> getCurrentScene() const = 0;
|
virtual Ptr<Scene> getCurrentScene() const = 0;
|
||||||
virtual Ptr<Scene> getPreviousScene() const = 0;
|
virtual Ptr<Scene> getPreviousScene() const = 0;
|
||||||
virtual Ptr<Scene> getRootScene() const = 0;
|
virtual Ptr<Scene> getRootScene() const = 0;
|
||||||
virtual Ptr<Scene> getSceneByName(const std::string& name) const = 0;
|
virtual Ptr<Scene> getSceneByName(const std::string &name) const = 0;
|
||||||
|
|
||||||
virtual size_t getSceneCount() const = 0;
|
virtual size_t getSceneCount() const = 0;
|
||||||
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;
|
||||||
virtual void setTransitionCallback(SceneManager::TransitionCallback callback) = 0;
|
virtual void
|
||||||
|
setTransitionCallback(SceneManager::TransitionCallback callback) = 0;
|
||||||
|
|
||||||
virtual void end() = 0;
|
virtual void end() = 0;
|
||||||
virtual void purgeCachedScenes() = 0;
|
virtual void purgeCachedScenes() = 0;
|
||||||
virtual void enterScene(Ptr<Scene> scene) = 0;
|
virtual void enterScene(Ptr<Scene> scene) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -47,49 +49,50 @@ public:
|
||||||
*/
|
*/
|
||||||
class SceneService : public ISceneService {
|
class SceneService : public ISceneService {
|
||||||
public:
|
public:
|
||||||
SceneService();
|
SceneService();
|
||||||
~SceneService() override = default;
|
~SceneService() override = default;
|
||||||
|
|
||||||
ServiceInfo getServiceInfo() const override;
|
ServiceInfo getServiceInfo() const override;
|
||||||
|
|
||||||
bool initialize() override;
|
bool initialize() override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
void update(float deltaTime) override;
|
void update(float deltaTime) override;
|
||||||
|
|
||||||
void runWithScene(Ptr<Scene> scene) override;
|
void runWithScene(Ptr<Scene> scene) override;
|
||||||
void replaceScene(Ptr<Scene> scene) override;
|
void replaceScene(Ptr<Scene> scene) override;
|
||||||
void pushScene(Ptr<Scene> scene) override;
|
void pushScene(Ptr<Scene> scene) override;
|
||||||
void popScene() override;
|
void popScene() override;
|
||||||
void popToRootScene() override;
|
void popToRootScene() override;
|
||||||
void popToScene(const std::string& name) override;
|
void popToScene(const std::string &name) override;
|
||||||
|
|
||||||
Ptr<Scene> getCurrentScene() const override;
|
Ptr<Scene> getCurrentScene() const override;
|
||||||
Ptr<Scene> getPreviousScene() const override;
|
Ptr<Scene> getPreviousScene() const override;
|
||||||
Ptr<Scene> getRootScene() const override;
|
Ptr<Scene> getRootScene() const override;
|
||||||
Ptr<Scene> getSceneByName(const std::string& name) const override;
|
Ptr<Scene> getSceneByName(const std::string &name) const override;
|
||||||
|
|
||||||
size_t getSceneCount() const override;
|
size_t getSceneCount() const override;
|
||||||
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;
|
||||||
void setTransitionCallback(SceneManager::TransitionCallback callback) override;
|
void
|
||||||
|
setTransitionCallback(SceneManager::TransitionCallback callback) override;
|
||||||
|
|
||||||
void end() override;
|
void end() override;
|
||||||
void purgeCachedScenes() override;
|
void purgeCachedScenes() override;
|
||||||
void enterScene(Ptr<Scene> scene) override;
|
void enterScene(Ptr<Scene> scene) override;
|
||||||
|
|
||||||
SceneManager& getManager() { return manager_; }
|
SceneManager &getManager() { return manager_; }
|
||||||
const SceneManager& getManager() const { return manager_; }
|
const SceneManager &getManager() const { return manager_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SceneManager manager_;
|
SceneManager manager_;
|
||||||
|
|
||||||
// 服务注册元数据
|
// 服务注册元数据
|
||||||
E2D_AUTO_REGISTER_SERVICE(ISceneService, SceneService);
|
E2D_AUTO_REGISTER_SERVICE(ISceneService, SceneService);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <extra2d/app/application.h>
|
#include <extra2d/app/application.h>
|
||||||
#include <extra2d/core/registry.h>
|
#include <extra2d/core/registry.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_module.h>
|
#include <extra2d/graphics/core/render_module.h>
|
||||||
#include <extra2d/graphics/memory/vram_manager.h>
|
#include <extra2d/graphics/memory/vram_manager.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/platform/glfw/glfw_window.h>
|
#include <extra2d/platform/glfw/glfw_window.h>
|
||||||
#include <extra2d/platform/window_module.h>
|
#include <extra2d/platform/window_module.h>
|
||||||
#include <extra2d/services/camera_service.h>
|
#include <extra2d/services/camera_service.h>
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
#include <extra2d/services/scene_service.h>
|
#include <extra2d/services/scene_service.h>
|
||||||
#include <extra2d/services/timer_service.h>
|
#include <extra2d/services/timer_service.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
static double getTimeSeconds() {
|
static double getTimeSeconds() {
|
||||||
|
|
@ -179,9 +178,7 @@ void Application::mainLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::update() {
|
void Application::update() { ServiceLocator::instance().updateAll(deltaTime_); }
|
||||||
ServiceLocator::instance().updateAll(deltaTime_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::render() {
|
void Application::render() {
|
||||||
auto *renderMod = get<RenderModule>();
|
auto *renderMod = get<RenderModule>();
|
||||||
|
|
@ -218,7 +215,7 @@ GLFWWindow *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->renderer() : nullptr;
|
return renderMod ? renderMod->renderer() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ bool RenderModule::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
E2D_LOG_INFO("正在创建 OpenGL 渲染后端");
|
E2D_LOG_INFO("正在创建 OpenGL 渲染后端");
|
||||||
renderer_ = makeUnique<GLRenderer>();
|
renderer_ = makeUnique<Renderer>();
|
||||||
|
|
||||||
if (!renderer_) {
|
if (!renderer_) {
|
||||||
E2D_LOG_ERROR("创建渲染后端失败");
|
E2D_LOG_ERROR("创建渲染后端失败");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
// VBO 初始大小(用于 VRAM 跟踪)
|
// VBO 初始大小(用于 VRAM 跟踪)
|
||||||
|
|
@ -22,7 +21,7 @@ static constexpr size_t SHAPE_VBO_SIZE = 1024 * sizeof(float);
|
||||||
/**
|
/**
|
||||||
* @brief 构造函数,初始化OpenGL渲染器成员变量
|
* @brief 构造函数,初始化OpenGL渲染器成员变量
|
||||||
*/
|
*/
|
||||||
GLRenderer::GLRenderer()
|
Renderer::Renderer()
|
||||||
: window_(nullptr), shapeVao_(0), lineVao_(0), vsync_(true),
|
: window_(nullptr), shapeVao_(0), lineVao_(0), vsync_(true),
|
||||||
shapeVertexCount_(0), currentShapeMode_(GL_TRIANGLES),
|
shapeVertexCount_(0), currentShapeMode_(GL_TRIANGLES),
|
||||||
lineVertexCount_(0), currentLineWidth_(1.0f) {
|
lineVertexCount_(0), currentLineWidth_(1.0f) {
|
||||||
|
|
@ -38,14 +37,14 @@ GLRenderer::GLRenderer()
|
||||||
/**
|
/**
|
||||||
* @brief 析构函数,调用shutdown释放资源
|
* @brief 析构函数,调用shutdown释放资源
|
||||||
*/
|
*/
|
||||||
GLRenderer::~GLRenderer() { shutdown(); }
|
Renderer::~Renderer() { shutdown(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化OpenGL渲染器
|
* @brief 初始化OpenGL渲染器
|
||||||
* @param window 窗口指针
|
* @param window 窗口指针
|
||||||
* @return 初始化成功返回true,失败返回false
|
* @return 初始化成功返回true,失败返回false
|
||||||
*/
|
*/
|
||||||
bool GLRenderer::init(GLFWWindow *window) {
|
bool Renderer::init(GLFWWindow *window) {
|
||||||
window_ = window;
|
window_ = window;
|
||||||
|
|
||||||
// 初始化 OpenGL 上下文(Switch 平台已通过 SDL2 + EGL 初始化,GLContext
|
// 初始化 OpenGL 上下文(Switch 平台已通过 SDL2 + EGL 初始化,GLContext
|
||||||
|
|
@ -89,7 +88,7 @@ bool GLRenderer::init(GLFWWindow *window) {
|
||||||
/**
|
/**
|
||||||
* @brief 关闭渲染器,释放所有GPU资源
|
* @brief 关闭渲染器,释放所有GPU资源
|
||||||
*/
|
*/
|
||||||
void GLRenderer::shutdown() {
|
void Renderer::shutdown() {
|
||||||
// 标记 GPU 上下文为无效
|
// 标记 GPU 上下文为无效
|
||||||
// 这会在销毁 OpenGL 上下文之前通知所有 GPU 资源
|
// 这会在销毁 OpenGL 上下文之前通知所有 GPU 资源
|
||||||
GPUContext::get().markInvalid();
|
GPUContext::get().markInvalid();
|
||||||
|
|
@ -118,7 +117,7 @@ void GLRenderer::shutdown() {
|
||||||
* @brief 开始新帧,清除颜色缓冲区并重置统计信息
|
* @brief 开始新帧,清除颜色缓冲区并重置统计信息
|
||||||
* @param clearColor 清屏颜色
|
* @param clearColor 清屏颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::beginFrame(const Color &clearColor) {
|
void Renderer::beginFrame(const Color &clearColor) {
|
||||||
// 应用管线状态
|
// 应用管线状态
|
||||||
pipeline_.applyAllStates();
|
pipeline_.applyAllStates();
|
||||||
|
|
||||||
|
|
@ -130,7 +129,7 @@ void GLRenderer::beginFrame(const Color &clearColor) {
|
||||||
/**
|
/**
|
||||||
* @brief 结束当前帧,刷新所有待处理的渲染批次
|
* @brief 结束当前帧,刷新所有待处理的渲染批次
|
||||||
*/
|
*/
|
||||||
void GLRenderer::endFrame() {
|
void Renderer::endFrame() {
|
||||||
// 刷新所有待处理的精灵批次(自动批处理)
|
// 刷新所有待处理的精灵批次(自动批处理)
|
||||||
if (autoBatchEnabled_ && batchActive_) {
|
if (autoBatchEnabled_ && batchActive_) {
|
||||||
flush();
|
flush();
|
||||||
|
|
@ -148,7 +147,7 @@ void GLRenderer::endFrame() {
|
||||||
* @param width 视口宽度
|
* @param width 视口宽度
|
||||||
* @param height 视口高度
|
* @param height 视口高度
|
||||||
*/
|
*/
|
||||||
void GLRenderer::setViewport(int x, int y, int width, int height) {
|
void Renderer::setViewport(int x, int y, int width, int height) {
|
||||||
// 使用 GLPipeline 管理视口状态
|
// 使用 GLPipeline 管理视口状态
|
||||||
pipeline_.setViewport(x, y, width, height);
|
pipeline_.setViewport(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +156,7 @@ void GLRenderer::setViewport(int x, int y, int width, int height) {
|
||||||
* @brief 设置垂直同步
|
* @brief 设置垂直同步
|
||||||
* @param enabled true启用垂直同步,false禁用
|
* @param enabled true启用垂直同步,false禁用
|
||||||
*/
|
*/
|
||||||
void GLRenderer::setVSync(bool enabled) {
|
void Renderer::setVSync(bool enabled) {
|
||||||
vsync_ = enabled;
|
vsync_ = enabled;
|
||||||
// 通过窗口接口设置垂直同步
|
// 通过窗口接口设置垂直同步
|
||||||
if (window_) {
|
if (window_) {
|
||||||
|
|
@ -169,7 +168,7 @@ void GLRenderer::setVSync(bool enabled) {
|
||||||
* @brief 设置混合模式
|
* @brief 设置混合模式
|
||||||
* @param mode 混合模式枚举值
|
* @param mode 混合模式枚举值
|
||||||
*/
|
*/
|
||||||
void GLRenderer::setBlendMode(BlendMode mode) {
|
void Renderer::setBlendMode(BlendMode mode) {
|
||||||
// 使用 GLPipeline 管理混合状态
|
// 使用 GLPipeline 管理混合状态
|
||||||
pipeline_.setBlendMode(mode);
|
pipeline_.setBlendMode(mode);
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +177,7 @@ void GLRenderer::setBlendMode(BlendMode mode) {
|
||||||
* @brief 设置视图投影矩阵
|
* @brief 设置视图投影矩阵
|
||||||
* @param matrix 4x4视图投影矩阵
|
* @param matrix 4x4视图投影矩阵
|
||||||
*/
|
*/
|
||||||
void GLRenderer::setViewProjection(const glm::mat4 &matrix) {
|
void Renderer::setViewProjection(const glm::mat4 &matrix) {
|
||||||
viewProjection_ = matrix;
|
viewProjection_ = matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,7 +185,7 @@ void GLRenderer::setViewProjection(const glm::mat4 &matrix) {
|
||||||
* @brief 压入变换矩阵到变换栈
|
* @brief 压入变换矩阵到变换栈
|
||||||
* @param transform 变换矩阵
|
* @param transform 变换矩阵
|
||||||
*/
|
*/
|
||||||
void GLRenderer::pushTransform(const glm::mat4 &transform) {
|
void Renderer::pushTransform(const glm::mat4 &transform) {
|
||||||
if (transformStack_.empty()) {
|
if (transformStack_.empty()) {
|
||||||
transformStack_.push_back(transform);
|
transformStack_.push_back(transform);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -197,7 +196,7 @@ void GLRenderer::pushTransform(const glm::mat4 &transform) {
|
||||||
/**
|
/**
|
||||||
* @brief 从变换栈弹出顶部变换矩阵
|
* @brief 从变换栈弹出顶部变换矩阵
|
||||||
*/
|
*/
|
||||||
void GLRenderer::popTransform() {
|
void Renderer::popTransform() {
|
||||||
if (!transformStack_.empty()) {
|
if (!transformStack_.empty()) {
|
||||||
transformStack_.pop_back();
|
transformStack_.pop_back();
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +206,7 @@ void GLRenderer::popTransform() {
|
||||||
* @brief 获取当前累积的变换矩阵
|
* @brief 获取当前累积的变换矩阵
|
||||||
* @return 当前变换矩阵,如果栈为空则返回单位矩阵
|
* @return 当前变换矩阵,如果栈为空则返回单位矩阵
|
||||||
*/
|
*/
|
||||||
glm::mat4 GLRenderer::getCurrentTransform() const {
|
glm::mat4 Renderer::getCurrentTransform() const {
|
||||||
if (transformStack_.empty()) {
|
if (transformStack_.empty()) {
|
||||||
return glm::mat4(1.0f);
|
return glm::mat4(1.0f);
|
||||||
}
|
}
|
||||||
|
|
@ -222,8 +221,8 @@ glm::mat4 GLRenderer::getCurrentTransform() const {
|
||||||
* @param channels 颜色通道数
|
* @param channels 颜色通道数
|
||||||
* @return 创建的纹理智能指针
|
* @return 创建的纹理智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<Texture> GLRenderer::createTexture(int width, int height,
|
Ptr<Texture> Renderer::createTexture(int width, int height,
|
||||||
const uint8_t *pixels, int channels) {
|
const uint8_t *pixels, int channels) {
|
||||||
return makePtr<GLTexture>(width, height, pixels, channels);
|
return makePtr<GLTexture>(width, height, pixels, channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,14 +231,14 @@ Ptr<Texture> GLRenderer::createTexture(int width, int height,
|
||||||
* @param filepath 纹理文件路径
|
* @param filepath 纹理文件路径
|
||||||
* @return 加载的纹理智能指针
|
* @return 加载的纹理智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<Texture> GLRenderer::loadTexture(const std::string &filepath) {
|
Ptr<Texture> Renderer::loadTexture(const std::string &filepath) {
|
||||||
return makePtr<GLTexture>(filepath);
|
return makePtr<GLTexture>(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 确保批处理已激活(自动批处理内部使用)
|
* @brief 确保批处理已激活(自动批处理内部使用)
|
||||||
*/
|
*/
|
||||||
void GLRenderer::ensureBatchActive() {
|
void Renderer::ensureBatchActive() {
|
||||||
if (!batchActive_) {
|
if (!batchActive_) {
|
||||||
spriteBatch_.begin(viewProjection_);
|
spriteBatch_.begin(viewProjection_);
|
||||||
batchActive_ = true;
|
batchActive_ = true;
|
||||||
|
|
@ -251,7 +250,7 @@ void GLRenderer::ensureBatchActive() {
|
||||||
/**
|
/**
|
||||||
* @brief 提交待处理的精灵(自动批处理内部使用)
|
* @brief 提交待处理的精灵(自动批处理内部使用)
|
||||||
*/
|
*/
|
||||||
void GLRenderer::submitPendingSprites() {
|
void Renderer::submitPendingSprites() {
|
||||||
if (pendingSprites_.empty()) {
|
if (pendingSprites_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +265,7 @@ void GLRenderer::submitPendingSprites() {
|
||||||
* @brief 开始手动精灵批处理(高级用法)
|
* @brief 开始手动精灵批处理(高级用法)
|
||||||
* @note 一般情况下不需要调用,drawSprite/drawText 会自动管理批处理
|
* @note 一般情况下不需要调用,drawSprite/drawText 会自动管理批处理
|
||||||
*/
|
*/
|
||||||
void GLRenderer::beginSpriteBatch() {
|
void Renderer::beginSpriteBatch() {
|
||||||
// 如果自动批处理已激活,先提交
|
// 如果自动批处理已激活,先提交
|
||||||
if (autoBatchEnabled_ && batchActive_) {
|
if (autoBatchEnabled_ && batchActive_) {
|
||||||
flush();
|
flush();
|
||||||
|
|
@ -286,9 +285,9 @@ void GLRenderer::beginSpriteBatch() {
|
||||||
* @param rotation 旋转角度(度)
|
* @param rotation 旋转角度(度)
|
||||||
* @param anchor 锚点位置(0-1范围)
|
* @param anchor 锚点位置(0-1范围)
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawSprite(const Texture &texture, const Rect &destRect,
|
void Renderer::drawSprite(const Texture &texture, const Rect &destRect,
|
||||||
const Rect &srcRect, const Color &tint,
|
const Rect &srcRect, const Color &tint,
|
||||||
float rotation, const Vec2 &anchor) {
|
float rotation, const Vec2 &anchor) {
|
||||||
// 自动批处理模式
|
// 自动批处理模式
|
||||||
if (autoBatchEnabled_) {
|
if (autoBatchEnabled_) {
|
||||||
ensureBatchActive();
|
ensureBatchActive();
|
||||||
|
|
@ -356,8 +355,8 @@ void GLRenderer::drawSprite(const Texture &texture, const Rect &destRect,
|
||||||
* @param position 绘制位置
|
* @param position 绘制位置
|
||||||
* @param tint 着色颜色
|
* @param tint 着色颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawSprite(const Texture &texture, const Vec2 &position,
|
void Renderer::drawSprite(const Texture &texture, const Vec2 &position,
|
||||||
const Color &tint) {
|
const Color &tint) {
|
||||||
Rect destRect(position.x, position.y, static_cast<float>(texture.getWidth()),
|
Rect destRect(position.x, position.y, static_cast<float>(texture.getWidth()),
|
||||||
static_cast<float>(texture.getHeight()));
|
static_cast<float>(texture.getHeight()));
|
||||||
Rect srcRect(0, 0, static_cast<float>(texture.getWidth()),
|
Rect srcRect(0, 0, static_cast<float>(texture.getWidth()),
|
||||||
|
|
@ -369,7 +368,7 @@ void GLRenderer::drawSprite(const Texture &texture, const Vec2 &position,
|
||||||
* @brief 结束手动精灵批处理并提交绘制
|
* @brief 结束手动精灵批处理并提交绘制
|
||||||
* @note 一般情况下不需要调用
|
* @note 一般情况下不需要调用
|
||||||
*/
|
*/
|
||||||
void GLRenderer::endSpriteBatch() {
|
void Renderer::endSpriteBatch() {
|
||||||
if (autoBatchEnabled_) {
|
if (autoBatchEnabled_) {
|
||||||
// 自动模式下,只是标记批处理结束
|
// 自动模式下,只是标记批处理结束
|
||||||
flush();
|
flush();
|
||||||
|
|
@ -386,7 +385,7 @@ void GLRenderer::endSpriteBatch() {
|
||||||
* @brief 立即提交当前批处理
|
* @brief 立即提交当前批处理
|
||||||
* @note 手动控制批处理提交时机,一般情况下不需要调用
|
* @note 手动控制批处理提交时机,一般情况下不需要调用
|
||||||
*/
|
*/
|
||||||
void GLRenderer::flush() {
|
void Renderer::flush() {
|
||||||
if (autoBatchEnabled_ && batchActive_) {
|
if (autoBatchEnabled_ && batchActive_) {
|
||||||
submitPendingSprites();
|
submitPendingSprites();
|
||||||
spriteBatch_.end();
|
spriteBatch_.end();
|
||||||
|
|
@ -403,8 +402,8 @@ void GLRenderer::flush() {
|
||||||
* @param color 线条颜色
|
* @param color 线条颜色
|
||||||
* @param width 线条宽度
|
* @param width 线条宽度
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawLine(const Vec2 &start, const Vec2 &end,
|
void Renderer::drawLine(const Vec2 &start, const Vec2 &end, const Color &color,
|
||||||
const Color &color, float width) {
|
float width) {
|
||||||
// 如果线宽改变,需要先刷新线条批次
|
// 如果线宽改变,需要先刷新线条批次
|
||||||
if (width != currentLineWidth_) {
|
if (width != currentLineWidth_) {
|
||||||
flushLineBatch();
|
flushLineBatch();
|
||||||
|
|
@ -416,7 +415,7 @@ void GLRenderer::drawLine(const Vec2 &start, const Vec2 &end,
|
||||||
addLineVertex(end.x, end.y, color);
|
addLineVertex(end.x, end.y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRenderer::drawRect(const Rect &rect, const Color &color, float width) {
|
void Renderer::drawRect(const Rect &rect, const Color &color, float width) {
|
||||||
// 如果线宽改变,需要先刷新线条批次
|
// 如果线宽改变,需要先刷新线条批次
|
||||||
if (width != currentLineWidth_) {
|
if (width != currentLineWidth_) {
|
||||||
flushLineBatch();
|
flushLineBatch();
|
||||||
|
|
@ -448,7 +447,7 @@ void GLRenderer::drawRect(const Rect &rect, const Color &color, float width) {
|
||||||
* @param rect 矩形区域
|
* @param rect 矩形区域
|
||||||
* @param color 填充颜色
|
* @param color 填充颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::fillRect(const Rect &rect, const Color &color) {
|
void Renderer::fillRect(const Rect &rect, const Color &color) {
|
||||||
// 提交当前批次(如果模式不同)
|
// 提交当前批次(如果模式不同)
|
||||||
submitShapeBatch(GL_TRIANGLES);
|
submitShapeBatch(GL_TRIANGLES);
|
||||||
|
|
||||||
|
|
@ -477,8 +476,8 @@ void GLRenderer::fillRect(const Rect &rect, const Color &color) {
|
||||||
* @param segments 分段数
|
* @param segments 分段数
|
||||||
* @param width 线条宽度
|
* @param width 线条宽度
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawCircle(const Vec2 ¢er, float radius,
|
void Renderer::drawCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||||
const Color &color, int segments, float width) {
|
int segments, float width) {
|
||||||
// 限制段数不超过缓存大小
|
// 限制段数不超过缓存大小
|
||||||
if (segments > static_cast<int>(MAX_CIRCLE_SEGMENTS)) {
|
if (segments > static_cast<int>(MAX_CIRCLE_SEGMENTS)) {
|
||||||
segments = static_cast<int>(MAX_CIRCLE_SEGMENTS);
|
segments = static_cast<int>(MAX_CIRCLE_SEGMENTS);
|
||||||
|
|
@ -511,8 +510,8 @@ void GLRenderer::drawCircle(const Vec2 ¢er, float radius,
|
||||||
* @param color 填充颜色
|
* @param color 填充颜色
|
||||||
* @param segments 分段数
|
* @param segments 分段数
|
||||||
*/
|
*/
|
||||||
void GLRenderer::fillCircle(const Vec2 ¢er, float radius,
|
void Renderer::fillCircle(const Vec2 ¢er, float radius, const Color &color,
|
||||||
const Color &color, int segments) {
|
int segments) {
|
||||||
// 限制段数不超过缓存大小
|
// 限制段数不超过缓存大小
|
||||||
if (segments > static_cast<int>(MAX_CIRCLE_SEGMENTS)) {
|
if (segments > static_cast<int>(MAX_CIRCLE_SEGMENTS)) {
|
||||||
segments = static_cast<int>(MAX_CIRCLE_SEGMENTS);
|
segments = static_cast<int>(MAX_CIRCLE_SEGMENTS);
|
||||||
|
|
@ -546,8 +545,8 @@ void GLRenderer::fillCircle(const Vec2 ¢er, float radius,
|
||||||
* @param color 边框颜色
|
* @param color 边框颜色
|
||||||
* @param width 线条宽度
|
* @param width 线条宽度
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
void Renderer::drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
const Color &color, float width) {
|
const Color &color, float width) {
|
||||||
drawLine(p1, p2, color, width);
|
drawLine(p1, p2, color, width);
|
||||||
drawLine(p2, p3, color, width);
|
drawLine(p2, p3, color, width);
|
||||||
drawLine(p3, p1, color, width);
|
drawLine(p3, p1, color, width);
|
||||||
|
|
@ -560,8 +559,8 @@ void GLRenderer::drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
* @param p3 第三个顶点
|
* @param p3 第三个顶点
|
||||||
* @param color 填充颜色
|
* @param color 填充颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
void Renderer::fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
const Color &color) {
|
const Color &color) {
|
||||||
submitShapeBatch(GL_TRIANGLES);
|
submitShapeBatch(GL_TRIANGLES);
|
||||||
|
|
||||||
addShapeVertex(p1.x, p1.y, color);
|
addShapeVertex(p1.x, p1.y, color);
|
||||||
|
|
@ -575,8 +574,8 @@ void GLRenderer::fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3,
|
||||||
* @param color 边框颜色
|
* @param color 边框颜色
|
||||||
* @param width 线条宽度
|
* @param width 线条宽度
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawPolygon(const std::vector<Vec2> &points,
|
void Renderer::drawPolygon(const std::vector<Vec2> &points, const Color &color,
|
||||||
const Color &color, float width) {
|
float width) {
|
||||||
if (points.size() < 2)
|
if (points.size() < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -600,8 +599,8 @@ void GLRenderer::drawPolygon(const std::vector<Vec2> &points,
|
||||||
* @param points 顶点数组
|
* @param points 顶点数组
|
||||||
* @param color 填充颜色
|
* @param color 填充颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::fillPolygon(const std::vector<Vec2> &points,
|
void Renderer::fillPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color) {
|
const Color &color) {
|
||||||
if (points.size() < 3)
|
if (points.size() < 3)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -623,8 +622,8 @@ void GLRenderer::fillPolygon(const std::vector<Vec2> &points,
|
||||||
* @param useSDF 是否使用SDF渲染
|
* @param useSDF 是否使用SDF渲染
|
||||||
* @return 创建的字体图集智能指针
|
* @return 创建的字体图集智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath,
|
Ptr<FontAtlas> Renderer::createFontAtlas(const std::string &filepath,
|
||||||
int fontSize, bool useSDF) {
|
int fontSize, bool useSDF) {
|
||||||
return makePtr<GLFontAtlas>(filepath, fontSize, useSDF);
|
return makePtr<GLFontAtlas>(filepath, fontSize, useSDF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -635,8 +634,8 @@ Ptr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath,
|
||||||
* @param position 绘制位置
|
* @param position 绘制位置
|
||||||
* @param color 文本颜色
|
* @param color 文本颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
void Renderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
const Vec2 &position, const Color &color) {
|
const Vec2 &position, const Color &color) {
|
||||||
drawText(font, text, position.x, position.y, color);
|
drawText(font, text, position.x, position.y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -648,8 +647,8 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
* @param y Y坐标
|
* @param y Y坐标
|
||||||
* @param color 文本颜色
|
* @param color 文本颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
void Renderer::drawText(const FontAtlas &font, const std::string &text, float x,
|
||||||
float x, float y, const Color &color) {
|
float y, const Color &color) {
|
||||||
float cursorX = x;
|
float cursorX = x;
|
||||||
float cursorY = y;
|
float cursorY = y;
|
||||||
float baselineY = cursorY + font.getAscent();
|
float baselineY = cursorY + font.getAscent();
|
||||||
|
|
@ -789,12 +788,12 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
/**
|
/**
|
||||||
* @brief 重置渲染统计信息
|
* @brief 重置渲染统计信息
|
||||||
*/
|
*/
|
||||||
void GLRenderer::resetStats() { stats_ = Stats{}; }
|
void Renderer::resetStats() { stats_ = RenderStats{}; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化形状渲染所需的OpenGL资源(VAO、VBO、着色器)
|
* @brief 初始化形状渲染所需的OpenGL资源(VAO、VBO、着色器)
|
||||||
*/
|
*/
|
||||||
void GLRenderer::initShapeRendering() {
|
void Renderer::initShapeRendering() {
|
||||||
// 从ShaderManager获取形状着色器
|
// 从ShaderManager获取形状着色器
|
||||||
shapeShader_ = ShaderManager::getInstance().getBuiltin("shape");
|
shapeShader_ = ShaderManager::getInstance().getBuiltin("shape");
|
||||||
if (!shapeShader_) {
|
if (!shapeShader_) {
|
||||||
|
|
@ -871,7 +870,7 @@ void GLRenderer::initShapeRendering() {
|
||||||
* @param y Y坐标
|
* @param y Y坐标
|
||||||
* @param color 顶点颜色
|
* @param color 顶点颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::addShapeVertex(float x, float y, const Color &color) {
|
void Renderer::addShapeVertex(float x, float y, const Color &color) {
|
||||||
if (shapeVertexCount_ >= MAX_SHAPE_VERTICES) {
|
if (shapeVertexCount_ >= MAX_SHAPE_VERTICES) {
|
||||||
flushShapeBatch();
|
flushShapeBatch();
|
||||||
}
|
}
|
||||||
|
|
@ -896,7 +895,7 @@ void GLRenderer::addShapeVertex(float x, float y, const Color &color) {
|
||||||
* @param y Y坐标
|
* @param y Y坐标
|
||||||
* @param color 顶点颜色
|
* @param color 顶点颜色
|
||||||
*/
|
*/
|
||||||
void GLRenderer::addLineVertex(float x, float y, const Color &color) {
|
void Renderer::addLineVertex(float x, float y, const Color &color) {
|
||||||
if (lineVertexCount_ >= MAX_LINE_VERTICES) {
|
if (lineVertexCount_ >= MAX_LINE_VERTICES) {
|
||||||
flushLineBatch();
|
flushLineBatch();
|
||||||
}
|
}
|
||||||
|
|
@ -919,7 +918,7 @@ void GLRenderer::addLineVertex(float x, float y, const Color &color) {
|
||||||
* @brief 提交形状批次(如果需要切换绘制模式)
|
* @brief 提交形状批次(如果需要切换绘制模式)
|
||||||
* @param mode OpenGL绘制模式
|
* @param mode OpenGL绘制模式
|
||||||
*/
|
*/
|
||||||
void GLRenderer::submitShapeBatch(GLenum mode) {
|
void Renderer::submitShapeBatch(GLenum mode) {
|
||||||
if (shapeVertexCount_ == 0)
|
if (shapeVertexCount_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -933,7 +932,7 @@ void GLRenderer::submitShapeBatch(GLenum mode) {
|
||||||
/**
|
/**
|
||||||
* @brief 刷新形状批次,执行实际的OpenGL绘制调用
|
* @brief 刷新形状批次,执行实际的OpenGL绘制调用
|
||||||
*/
|
*/
|
||||||
void GLRenderer::flushShapeBatch() {
|
void Renderer::flushShapeBatch() {
|
||||||
if (shapeVertexCount_ == 0)
|
if (shapeVertexCount_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -966,7 +965,7 @@ void GLRenderer::flushShapeBatch() {
|
||||||
/**
|
/**
|
||||||
* @brief 刷新线条批次,执行实际的OpenGL绘制调用
|
* @brief 刷新线条批次,执行实际的OpenGL绘制调用
|
||||||
*/
|
*/
|
||||||
void GLRenderer::flushLineBatch() {
|
void Renderer::flushLineBatch() {
|
||||||
if (lineVertexCount_ == 0)
|
if (lineVertexCount_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1004,7 +1003,7 @@ void GLRenderer::flushLineBatch() {
|
||||||
* @param desc 帧缓冲描述
|
* @param desc 帧缓冲描述
|
||||||
* @return 创建的帧缓冲智能指针
|
* @return 创建的帧缓冲智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<GLFramebuffer> GLRenderer::createFramebuffer(const FramebufferDesc &desc) {
|
Ptr<GLFramebuffer> Renderer::createFramebuffer(const FramebufferDesc &desc) {
|
||||||
auto framebuffer = makePtr<GLFramebuffer>();
|
auto framebuffer = makePtr<GLFramebuffer>();
|
||||||
if (!framebuffer->init(desc)) {
|
if (!framebuffer->init(desc)) {
|
||||||
E2D_LOG_ERROR("创建帧缓冲区失败");
|
E2D_LOG_ERROR("创建帧缓冲区失败");
|
||||||
|
|
@ -1017,7 +1016,7 @@ Ptr<GLFramebuffer> GLRenderer::createFramebuffer(const FramebufferDesc &desc) {
|
||||||
* @brief 绑定帧缓冲(作为渲染目标)
|
* @brief 绑定帧缓冲(作为渲染目标)
|
||||||
* @param framebuffer 帧缓冲对象指针,传入 nullptr 则绑定默认帧缓冲
|
* @param framebuffer 帧缓冲对象指针,传入 nullptr 则绑定默认帧缓冲
|
||||||
*/
|
*/
|
||||||
void GLRenderer::bindFramebuffer(GLFramebuffer *framebuffer) {
|
void Renderer::bindFramebuffer(GLFramebuffer *framebuffer) {
|
||||||
// 先刷新所有待处理的渲染批次
|
// 先刷新所有待处理的渲染批次
|
||||||
flush();
|
flush();
|
||||||
flushShapeBatch();
|
flushShapeBatch();
|
||||||
|
|
@ -1039,13 +1038,13 @@ void GLRenderer::bindFramebuffer(GLFramebuffer *framebuffer) {
|
||||||
/**
|
/**
|
||||||
* @brief 解绑帧缓冲(恢复到默认帧缓冲)
|
* @brief 解绑帧缓冲(恢复到默认帧缓冲)
|
||||||
*/
|
*/
|
||||||
void GLRenderer::unbindFramebuffer() { bindFramebuffer(nullptr); }
|
void Renderer::unbindFramebuffer() { bindFramebuffer(nullptr); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取默认帧缓冲
|
* @brief 获取默认帧缓冲
|
||||||
* @return 默认帧缓冲智能指针
|
* @return 默认帧缓冲智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<GLFramebuffer> GLRenderer::getDefaultFramebuffer() const {
|
Ptr<GLFramebuffer> Renderer::getDefaultFramebuffer() const {
|
||||||
if (!defaultFramebuffer_) {
|
if (!defaultFramebuffer_) {
|
||||||
// 延迟创建默认帧缓冲对象(代表系统默认帧缓冲,ID 为 0)
|
// 延迟创建默认帧缓冲对象(代表系统默认帧缓冲,ID 为 0)
|
||||||
defaultFramebuffer_ = makePtr<GLFramebuffer>();
|
defaultFramebuffer_ = makePtr<GLFramebuffer>();
|
||||||
|
|
@ -1061,8 +1060,8 @@ Ptr<GLFramebuffer> GLRenderer::getDefaultFramebuffer() const {
|
||||||
* @param clearDepth 是否清除深度缓冲
|
* @param clearDepth 是否清除深度缓冲
|
||||||
* @param clearStencil 是否清除模板缓冲
|
* @param clearStencil 是否清除模板缓冲
|
||||||
*/
|
*/
|
||||||
void GLRenderer::clearFramebuffer(const Color &color, bool clearColor,
|
void Renderer::clearFramebuffer(const Color &color, bool clearColor,
|
||||||
bool clearDepth, bool clearStencil) {
|
bool clearDepth, bool clearStencil) {
|
||||||
GLbitfield mask = 0;
|
GLbitfield mask = 0;
|
||||||
|
|
||||||
if (clearColor) {
|
if (clearColor) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/graphics/texture/texture_pool.h>
|
#include <extra2d/graphics/texture/texture_pool.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/scene/scene.h>
|
#include <extra2d/scene/scene.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -17,13 +17,8 @@ namespace extra2d {
|
||||||
* 创建一个未初始化的纹理池
|
* 创建一个未初始化的纹理池
|
||||||
*/
|
*/
|
||||||
TexturePool::TexturePool()
|
TexturePool::TexturePool()
|
||||||
: scene_(nullptr)
|
: scene_(nullptr), maxMemoryUsage_(0), currentMemoryUsage_(0),
|
||||||
, maxMemoryUsage_(0)
|
cacheHits_(0), cacheMisses_(0), evictionCount_(0) {}
|
||||||
, currentMemoryUsage_(0)
|
|
||||||
, cacheHits_(0)
|
|
||||||
, cacheMisses_(0)
|
|
||||||
, evictionCount_(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 构造函数
|
* @brief 构造函数
|
||||||
|
|
@ -32,14 +27,10 @@ TexturePool::TexturePool()
|
||||||
*
|
*
|
||||||
* 创建一个指定场景和内存限制的纹理池
|
* 创建一个指定场景和内存限制的纹理池
|
||||||
*/
|
*/
|
||||||
TexturePool::TexturePool(Scene* scene, size_t maxMemoryUsage)
|
TexturePool::TexturePool(Scene *scene, size_t maxMemoryUsage)
|
||||||
: scene_(scene)
|
: scene_(scene), maxMemoryUsage_(maxMemoryUsage), currentMemoryUsage_(0),
|
||||||
, maxMemoryUsage_(maxMemoryUsage)
|
cacheHits_(0), cacheMisses_(0), evictionCount_(0) {
|
||||||
, currentMemoryUsage_(0)
|
E2D_LOG_INFO("TexturePool 已创建,最大内存: {} 字节", maxMemoryUsage);
|
||||||
, cacheHits_(0)
|
|
||||||
, cacheMisses_(0)
|
|
||||||
, evictionCount_(0) {
|
|
||||||
E2D_LOG_INFO("TexturePool 已创建,最大内存: {} 字节", maxMemoryUsage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,10 +40,10 @@ TexturePool::TexturePool(Scene* scene, size_t maxMemoryUsage)
|
||||||
*
|
*
|
||||||
* 设置纹理池的场景和内存限制
|
* 设置纹理池的场景和内存限制
|
||||||
*/
|
*/
|
||||||
void TexturePool::init(Scene* scene, size_t maxMemoryUsage) {
|
void TexturePool::init(Scene *scene, size_t maxMemoryUsage) {
|
||||||
scene_ = scene;
|
scene_ = scene;
|
||||||
maxMemoryUsage_ = maxMemoryUsage;
|
maxMemoryUsage_ = maxMemoryUsage;
|
||||||
E2D_LOG_INFO("TexturePool 已初始化,最大内存: {} 字节", maxMemoryUsage);
|
E2D_LOG_INFO("TexturePool 已初始化,最大内存: {} 字节", maxMemoryUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,8 +52,8 @@ void TexturePool::init(Scene* scene, size_t maxMemoryUsage) {
|
||||||
* 清理纹理池并释放所有资源
|
* 清理纹理池并释放所有资源
|
||||||
*/
|
*/
|
||||||
TexturePool::~TexturePool() {
|
TexturePool::~TexturePool() {
|
||||||
clear();
|
clear();
|
||||||
E2D_LOG_INFO("TexturePool 已销毁");
|
E2D_LOG_INFO("TexturePool 已销毁");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -77,8 +68,9 @@ TexturePool::~TexturePool() {
|
||||||
*
|
*
|
||||||
* 加载完整纹理文件到纹理池
|
* 加载完整纹理文件到纹理池
|
||||||
*/
|
*/
|
||||||
TextureRef TexturePool::load(const std::string& path, const TextureLoadOptions& options) {
|
TextureRef TexturePool::load(const std::string &path,
|
||||||
return load(path, Rect::Zero(), options);
|
const TextureLoadOptions &options) {
|
||||||
|
return load(path, Rect::Zero(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -90,75 +82,76 @@ TextureRef TexturePool::load(const std::string& path, const TextureLoadOptions&
|
||||||
*
|
*
|
||||||
* 加载纹理文件的指定区域到纹理池
|
* 加载纹理文件的指定区域到纹理池
|
||||||
*/
|
*/
|
||||||
TextureRef TexturePool::load(const std::string& path, const Rect& region,
|
TextureRef TexturePool::load(const std::string &path, const Rect ®ion,
|
||||||
const TextureLoadOptions& options) {
|
const TextureLoadOptions &options) {
|
||||||
TextureKey key(path, region);
|
TextureKey key(path, region);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
// 缓存命中
|
// 缓存命中
|
||||||
it->second.touch();
|
it->second.touch();
|
||||||
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
||||||
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
E2D_LOG_DEBUG("纹理缓存命中: {}", path);
|
E2D_LOG_DEBUG("纹理缓存命中: {}", path);
|
||||||
return TextureRef(it->second.texture, &it->second, &mutex_);
|
return TextureRef(it->second.texture, &it->second, &mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 缓存未命中
|
// 缓存未命中
|
||||||
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
// 获取渲染后端
|
// 获取渲染后端
|
||||||
RenderBackend* backend = nullptr;
|
Renderer *backend = nullptr;
|
||||||
if (scene_) {
|
if (scene_) {
|
||||||
// 假设 Scene 有获取 RenderBackend 的方法
|
// 假设 Scene 有获取 Renderer 的方法
|
||||||
// 这里需要根据实际接口调整
|
// 这里需要根据实际接口调整
|
||||||
backend = nullptr; // TODO: 从 Scene 获取 RenderBackend
|
backend = nullptr; // TODO: 从 Scene 获取 Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backend) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载纹理
|
|
||||||
Ptr<Texture> texture = backend->loadTexture(path);
|
|
||||||
if (!texture) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path);
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算内存大小
|
|
||||||
size_t memorySize = calculateTextureMemory(texture.get());
|
|
||||||
|
|
||||||
// 检查内存限制
|
|
||||||
if (maxMemoryUsage_ > 0 && currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
// 尝试淘汰
|
|
||||||
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
|
||||||
|
|
||||||
// 再次检查
|
|
||||||
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
E2D_LOG_WARN("TexturePool: 内存限制超出,无法加载纹理: {}", path);
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建缓存条目
|
|
||||||
auto result = cache_.emplace(key, TexturePoolEntry(nullptr, key, 0));
|
|
||||||
if (result.second) {
|
|
||||||
result.first->second.texture = texture;
|
|
||||||
result.first->second.memorySize = memorySize;
|
|
||||||
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
|
||||||
result.first->second.touch();
|
|
||||||
currentMemoryUsage_ += memorySize;
|
|
||||||
E2D_LOG_INFO("TexturePool: 已加载纹理: {} ({} 字节)", path, memorySize);
|
|
||||||
return TextureRef(texture, &result.first->second, &mutex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!backend) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
||||||
return TextureRef();
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载纹理
|
||||||
|
Ptr<Texture> texture = backend->loadTexture(path);
|
||||||
|
if (!texture) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path);
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算内存大小
|
||||||
|
size_t memorySize = calculateTextureMemory(texture.get());
|
||||||
|
|
||||||
|
// 检查内存限制
|
||||||
|
if (maxMemoryUsage_ > 0 &&
|
||||||
|
currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
// 尝试淘汰
|
||||||
|
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
||||||
|
|
||||||
|
// 再次检查
|
||||||
|
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
E2D_LOG_WARN("TexturePool: 内存限制超出,无法加载纹理: {}", path);
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建缓存条目
|
||||||
|
auto result = cache_.emplace(key, TexturePoolEntry(nullptr, key, 0));
|
||||||
|
if (result.second) {
|
||||||
|
result.first->second.texture = texture;
|
||||||
|
result.first->second.memorySize = memorySize;
|
||||||
|
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
||||||
|
result.first->second.touch();
|
||||||
|
currentMemoryUsage_ += memorySize;
|
||||||
|
E2D_LOG_INFO("TexturePool: 已加载纹理: {} ({} 字节)", path, memorySize);
|
||||||
|
return TextureRef(texture, &result.first->second, &mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -172,67 +165,70 @@ TextureRef TexturePool::load(const std::string& path, const Rect& region,
|
||||||
*
|
*
|
||||||
* 从内存中的像素数据创建纹理并加入纹理池
|
* 从内存中的像素数据创建纹理并加入纹理池
|
||||||
*/
|
*/
|
||||||
TextureRef TexturePool::loadFromMemory(const uint8_t* data, int width, int height,
|
TextureRef TexturePool::loadFromMemory(const uint8_t *data, int width,
|
||||||
int channels, const std::string& key) {
|
int height, int channels,
|
||||||
TextureKey textureKey(key);
|
const std::string &key) {
|
||||||
|
TextureKey textureKey(key);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
auto it = cache_.find(textureKey);
|
auto it = cache_.find(textureKey);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
it->second.touch();
|
it->second.touch();
|
||||||
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
||||||
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
||||||
return TextureRef(it->second.texture, &it->second, &mutex_);
|
return TextureRef(it->second.texture, &it->second, &mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
// 获取渲染后端
|
// 获取渲染后端
|
||||||
RenderBackend* backend = nullptr;
|
Renderer *backend = nullptr;
|
||||||
if (scene_) {
|
if (scene_) {
|
||||||
backend = nullptr; // TODO: 从 Scene 获取 RenderBackend
|
backend = nullptr; // TODO: 从 Scene 获取 Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backend) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建纹理
|
|
||||||
Ptr<Texture> texture = backend->createTexture(width, height, data, channels);
|
|
||||||
if (!texture) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 从内存创建纹理失败");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算内存大小
|
|
||||||
size_t memorySize = calculateTextureMemory(texture.get());
|
|
||||||
|
|
||||||
// 检查内存限制
|
|
||||||
if (maxMemoryUsage_ > 0 && currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
|
||||||
|
|
||||||
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
E2D_LOG_WARN("TexturePool: 内存限制超出");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建缓存条目
|
|
||||||
auto result = cache_.emplace(textureKey, TexturePoolEntry(nullptr, textureKey, 0));
|
|
||||||
if (result.second) {
|
|
||||||
result.first->second.texture = texture;
|
|
||||||
result.first->second.memorySize = memorySize;
|
|
||||||
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
|
||||||
result.first->second.touch();
|
|
||||||
currentMemoryUsage_ += memorySize;
|
|
||||||
E2D_LOG_INFO("TexturePool: 已从内存创建纹理 ({} 字节)", memorySize);
|
|
||||||
return TextureRef(texture, &result.first->second, &mutex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!backend) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
||||||
return TextureRef();
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建纹理
|
||||||
|
Ptr<Texture> texture = backend->createTexture(width, height, data, channels);
|
||||||
|
if (!texture) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 从内存创建纹理失败");
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算内存大小
|
||||||
|
size_t memorySize = calculateTextureMemory(texture.get());
|
||||||
|
|
||||||
|
// 检查内存限制
|
||||||
|
if (maxMemoryUsage_ > 0 &&
|
||||||
|
currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
||||||
|
|
||||||
|
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
E2D_LOG_WARN("TexturePool: 内存限制超出");
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建缓存条目
|
||||||
|
auto result =
|
||||||
|
cache_.emplace(textureKey, TexturePoolEntry(nullptr, textureKey, 0));
|
||||||
|
if (result.second) {
|
||||||
|
result.first->second.texture = texture;
|
||||||
|
result.first->second.memorySize = memorySize;
|
||||||
|
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
||||||
|
result.first->second.touch();
|
||||||
|
currentMemoryUsage_ += memorySize;
|
||||||
|
E2D_LOG_INFO("TexturePool: 已从内存创建纹理 ({} 字节)", memorySize);
|
||||||
|
return TextureRef(texture, &result.first->second, &mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -243,8 +239,9 @@ TextureRef TexturePool::loadFromMemory(const uint8_t* data, int width, int heigh
|
||||||
*
|
*
|
||||||
* 如果纹理已缓存则返回缓存,否则加载纹理
|
* 如果纹理已缓存则返回缓存,否则加载纹理
|
||||||
*/
|
*/
|
||||||
TextureRef TexturePool::getOrLoad(const std::string& path, const TextureLoadOptions& options) {
|
TextureRef TexturePool::getOrLoad(const std::string &path,
|
||||||
return getOrLoad(path, Rect::Zero(), options);
|
const TextureLoadOptions &options) {
|
||||||
|
return getOrLoad(path, Rect::Zero(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -256,65 +253,66 @@ TextureRef TexturePool::getOrLoad(const std::string& path, const TextureLoadOpti
|
||||||
*
|
*
|
||||||
* 如果纹理区域已缓存则返回缓存,否则加载纹理区域
|
* 如果纹理区域已缓存则返回缓存,否则加载纹理区域
|
||||||
*/
|
*/
|
||||||
TextureRef TexturePool::getOrLoad(const std::string& path, const Rect& region,
|
TextureRef TexturePool::getOrLoad(const std::string &path, const Rect ®ion,
|
||||||
const TextureLoadOptions& options) {
|
const TextureLoadOptions &options) {
|
||||||
TextureKey key(path, region);
|
TextureKey key(path, region);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
it->second.touch();
|
it->second.touch();
|
||||||
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
||||||
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
cacheHits_.fetch_add(1, std::memory_order_relaxed);
|
||||||
return TextureRef(it->second.texture, &it->second, &mutex_);
|
return TextureRef(it->second.texture, &it->second, &mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放锁后调用 load
|
// 释放锁后调用 load
|
||||||
// 注意:这里需要重新设计以避免死锁
|
// 注意:这里需要重新设计以避免死锁
|
||||||
// 简化处理:直接在这里加载
|
// 简化处理:直接在这里加载
|
||||||
|
|
||||||
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
cacheMisses_.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
RenderBackend* backend = nullptr;
|
Renderer *backend = nullptr;
|
||||||
if (scene_) {
|
if (scene_) {
|
||||||
backend = nullptr; // TODO: 从 Scene 获取 RenderBackend
|
backend = nullptr; // TODO: 从 Scene 获取 Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backend) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<Texture> texture = backend->loadTexture(path);
|
|
||||||
if (!texture) {
|
|
||||||
E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path);
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t memorySize = calculateTextureMemory(texture.get());
|
|
||||||
|
|
||||||
if (maxMemoryUsage_ > 0 && currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
|
||||||
|
|
||||||
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
|
||||||
E2D_LOG_WARN("TexturePool: 内存限制超出");
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = cache_.emplace(key, TexturePoolEntry(nullptr, key, 0));
|
|
||||||
if (result.second) {
|
|
||||||
result.first->second.texture = texture;
|
|
||||||
result.first->second.memorySize = memorySize;
|
|
||||||
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
|
||||||
result.first->second.touch();
|
|
||||||
currentMemoryUsage_ += memorySize;
|
|
||||||
return TextureRef(texture, &result.first->second, &mutex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!backend) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 渲染后端不可用");
|
||||||
return TextureRef();
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr<Texture> texture = backend->loadTexture(path);
|
||||||
|
if (!texture) {
|
||||||
|
E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path);
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t memorySize = calculateTextureMemory(texture.get());
|
||||||
|
|
||||||
|
if (maxMemoryUsage_ > 0 &&
|
||||||
|
currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_);
|
||||||
|
|
||||||
|
if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) {
|
||||||
|
E2D_LOG_WARN("TexturePool: 内存限制超出");
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = cache_.emplace(key, TexturePoolEntry(nullptr, key, 0));
|
||||||
|
if (result.second) {
|
||||||
|
result.first->second.texture = texture;
|
||||||
|
result.first->second.memorySize = memorySize;
|
||||||
|
result.first->second.refCount.store(1, std::memory_order_relaxed);
|
||||||
|
result.first->second.touch();
|
||||||
|
currentMemoryUsage_ += memorySize;
|
||||||
|
return TextureRef(texture, &result.first->second, &mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -328,16 +326,16 @@ TextureRef TexturePool::getOrLoad(const std::string& path, const Rect& region,
|
||||||
*
|
*
|
||||||
* 增加指定纹理的引用计数
|
* 增加指定纹理的引用计数
|
||||||
*/
|
*/
|
||||||
bool TexturePool::addRef(const TextureKey& key) {
|
bool TexturePool::addRef(const TextureKey &key) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
it->second.touch();
|
it->second.touch();
|
||||||
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
it->second.refCount.fetch_add(1, std::memory_order_relaxed);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -347,15 +345,16 @@ bool TexturePool::addRef(const TextureKey& key) {
|
||||||
*
|
*
|
||||||
* 减少指定纹理的引用计数并返回新值
|
* 减少指定纹理的引用计数并返回新值
|
||||||
*/
|
*/
|
||||||
uint32_t TexturePool::release(const TextureKey& key) {
|
uint32_t TexturePool::release(const TextureKey &key) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
uint32_t count = it->second.refCount.fetch_sub(1, std::memory_order_relaxed);
|
uint32_t count =
|
||||||
return count > 0 ? count - 1 : 0;
|
it->second.refCount.fetch_sub(1, std::memory_order_relaxed);
|
||||||
}
|
return count > 0 ? count - 1 : 0;
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -365,14 +364,14 @@ uint32_t TexturePool::release(const TextureKey& key) {
|
||||||
*
|
*
|
||||||
* 获取指定纹理的当前引用计数
|
* 获取指定纹理的当前引用计数
|
||||||
*/
|
*/
|
||||||
uint32_t TexturePool::getRefCount(const TextureKey& key) const {
|
uint32_t TexturePool::getRefCount(const TextureKey &key) const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
return it->second.refCount.load(std::memory_order_relaxed);
|
return it->second.refCount.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -386,9 +385,9 @@ uint32_t TexturePool::getRefCount(const TextureKey& key) const {
|
||||||
*
|
*
|
||||||
* 检查指定纹理是否存在于缓存中
|
* 检查指定纹理是否存在于缓存中
|
||||||
*/
|
*/
|
||||||
bool TexturePool::isCached(const TextureKey& key) const {
|
bool TexturePool::isCached(const TextureKey &key) const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
return cache_.find(key) != cache_.end();
|
return cache_.find(key) != cache_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -398,17 +397,17 @@ bool TexturePool::isCached(const TextureKey& key) const {
|
||||||
*
|
*
|
||||||
* 从缓存中移除指定的纹理
|
* 从缓存中移除指定的纹理
|
||||||
*/
|
*/
|
||||||
bool TexturePool::removeFromCache(const TextureKey& key) {
|
bool TexturePool::removeFromCache(const TextureKey &key) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
auto it = cache_.find(key);
|
auto it = cache_.find(key);
|
||||||
if (it != cache_.end()) {
|
if (it != cache_.end()) {
|
||||||
currentMemoryUsage_ -= it->second.memorySize;
|
currentMemoryUsage_ -= it->second.memorySize;
|
||||||
cache_.erase(it);
|
cache_.erase(it);
|
||||||
E2D_LOG_DEBUG("TexturePool: 已从缓存移除纹理");
|
E2D_LOG_DEBUG("TexturePool: 已从缓存移除纹理");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -418,24 +417,24 @@ bool TexturePool::removeFromCache(const TextureKey& key) {
|
||||||
* 清理所有引用计数为0的纹理,释放内存
|
* 清理所有引用计数为0的纹理,释放内存
|
||||||
*/
|
*/
|
||||||
size_t TexturePool::collectGarbage() {
|
size_t TexturePool::collectGarbage() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
size_t removed = 0;
|
size_t removed = 0;
|
||||||
for (auto it = cache_.begin(); it != cache_.end(); ) {
|
for (auto it = cache_.begin(); it != cache_.end();) {
|
||||||
if (it->second.refCount.load(std::memory_order_relaxed) == 0) {
|
if (it->second.refCount.load(std::memory_order_relaxed) == 0) {
|
||||||
currentMemoryUsage_ -= it->second.memorySize;
|
currentMemoryUsage_ -= it->second.memorySize;
|
||||||
it = cache_.erase(it);
|
it = cache_.erase(it);
|
||||||
++removed;
|
++removed;
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (removed > 0) {
|
if (removed > 0) {
|
||||||
E2D_LOG_INFO("TexturePool: 垃圾回收 {} 个纹理", removed);
|
E2D_LOG_INFO("TexturePool: 垃圾回收 {} 个纹理", removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -444,12 +443,12 @@ size_t TexturePool::collectGarbage() {
|
||||||
* 移除纹理池中的所有纹理
|
* 移除纹理池中的所有纹理
|
||||||
*/
|
*/
|
||||||
void TexturePool::clear() {
|
void TexturePool::clear() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
cache_.clear();
|
cache_.clear();
|
||||||
currentMemoryUsage_ = 0;
|
currentMemoryUsage_ = 0;
|
||||||
|
|
||||||
E2D_LOG_INFO("TexturePool: 已清除所有纹理");
|
E2D_LOG_INFO("TexturePool: 已清除所有纹理");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -463,8 +462,8 @@ void TexturePool::clear() {
|
||||||
* 返回纹理池当前的内存使用量
|
* 返回纹理池当前的内存使用量
|
||||||
*/
|
*/
|
||||||
size_t TexturePool::getMemoryUsage() const {
|
size_t TexturePool::getMemoryUsage() const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
return currentMemoryUsage_;
|
return currentMemoryUsage_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -474,15 +473,15 @@ size_t TexturePool::getMemoryUsage() const {
|
||||||
* 设置纹理池的内存上限,如果当前使用量超过新上限则执行淘汰
|
* 设置纹理池的内存上限,如果当前使用量超过新上限则执行淘汰
|
||||||
*/
|
*/
|
||||||
void TexturePool::setMaxMemoryUsage(size_t maxMemory) {
|
void TexturePool::setMaxMemoryUsage(size_t maxMemory) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
maxMemoryUsage_ = maxMemory;
|
maxMemoryUsage_ = maxMemory;
|
||||||
|
|
||||||
// 如果当前内存超过新的限制,执行淘汰
|
// 如果当前内存超过新的限制,执行淘汰
|
||||||
if (maxMemoryUsage_ > 0 && currentMemoryUsage_ > maxMemoryUsage_) {
|
if (maxMemoryUsage_ > 0 && currentMemoryUsage_ > maxMemoryUsage_) {
|
||||||
evictLRU(maxMemoryUsage_);
|
evictLRU(maxMemoryUsage_);
|
||||||
}
|
}
|
||||||
|
|
||||||
E2D_LOG_INFO("TexturePool: 最大内存设置为 {} 字节", maxMemory);
|
E2D_LOG_INFO("TexturePool: 最大内存设置为 {} 字节", maxMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -493,49 +492,49 @@ void TexturePool::setMaxMemoryUsage(size_t maxMemory) {
|
||||||
* 根据LRU算法淘汰最少使用的纹理以达到目标内存使用量
|
* 根据LRU算法淘汰最少使用的纹理以达到目标内存使用量
|
||||||
*/
|
*/
|
||||||
size_t TexturePool::evictLRU(size_t targetMemory) {
|
size_t TexturePool::evictLRU(size_t targetMemory) {
|
||||||
// 注意:调用者应该已持有锁
|
// 注意:调用者应该已持有锁
|
||||||
|
|
||||||
if (cache_.empty()) {
|
if (cache_.empty()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有条目并按最后访问时间排序
|
||||||
|
std::vector<std::pair<TextureKey, uint64_t>> entries;
|
||||||
|
entries.reserve(cache_.size());
|
||||||
|
|
||||||
|
for (const auto &pair : cache_) {
|
||||||
|
// 只淘汰引用计数为 0 的纹理
|
||||||
|
if (pair.second.refCount.load(std::memory_order_relaxed) == 0) {
|
||||||
|
entries.emplace_back(pair.first, pair.second.lastAccessTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按访问时间升序排序(最旧的在前)
|
||||||
|
std::sort(entries.begin(), entries.end(),
|
||||||
|
[](const auto &a, const auto &b) { return a.second < b.second; });
|
||||||
|
|
||||||
|
size_t evicted = 0;
|
||||||
|
size_t target = targetMemory > 0 ? targetMemory : 0;
|
||||||
|
|
||||||
|
for (const auto &entry : entries) {
|
||||||
|
if (targetMemory > 0 && currentMemoryUsage_ <= target) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有条目并按最后访问时间排序
|
auto it = cache_.find(entry.first);
|
||||||
std::vector<std::pair<TextureKey, uint64_t>> entries;
|
if (it != cache_.end()) {
|
||||||
entries.reserve(cache_.size());
|
currentMemoryUsage_ -= it->second.memorySize;
|
||||||
|
cache_.erase(it);
|
||||||
for (const auto& pair : cache_) {
|
++evicted;
|
||||||
// 只淘汰引用计数为 0 的纹理
|
|
||||||
if (pair.second.refCount.load(std::memory_order_relaxed) == 0) {
|
|
||||||
entries.emplace_back(pair.first, pair.second.lastAccessTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 按访问时间升序排序(最旧的在前)
|
if (evicted > 0) {
|
||||||
std::sort(entries.begin(), entries.end(),
|
evictionCount_.fetch_add(evicted, std::memory_order_relaxed);
|
||||||
[](const auto& a, const auto& b) { return a.second < b.second; });
|
E2D_LOG_INFO("TexturePool: LRU 淘汰 {} 个纹理", evicted);
|
||||||
|
}
|
||||||
|
|
||||||
size_t evicted = 0;
|
return evicted;
|
||||||
size_t target = targetMemory > 0 ? targetMemory : 0;
|
|
||||||
|
|
||||||
for (const auto& entry : entries) {
|
|
||||||
if (targetMemory > 0 && currentMemoryUsage_ <= target) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = cache_.find(entry.first);
|
|
||||||
if (it != cache_.end()) {
|
|
||||||
currentMemoryUsage_ -= it->second.memorySize;
|
|
||||||
cache_.erase(it);
|
|
||||||
++evicted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evicted > 0) {
|
|
||||||
evictionCount_.fetch_add(evicted, std::memory_order_relaxed);
|
|
||||||
E2D_LOG_INFO("TexturePool: LRU 淘汰 {} 个纹理", evicted);
|
|
||||||
}
|
|
||||||
|
|
||||||
return evicted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -549,17 +548,17 @@ size_t TexturePool::evictLRU(size_t targetMemory) {
|
||||||
* 返回纹理池的统计信息,包括纹理数量、内存使用、缓存命中率等
|
* 返回纹理池的统计信息,包括纹理数量、内存使用、缓存命中率等
|
||||||
*/
|
*/
|
||||||
TexturePool::Stats TexturePool::getStats() const {
|
TexturePool::Stats TexturePool::getStats() const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
Stats stats;
|
Stats stats;
|
||||||
stats.textureCount = cache_.size();
|
stats.textureCount = cache_.size();
|
||||||
stats.memoryUsage = currentMemoryUsage_;
|
stats.memoryUsage = currentMemoryUsage_;
|
||||||
stats.maxMemoryUsage = maxMemoryUsage_;
|
stats.maxMemoryUsage = maxMemoryUsage_;
|
||||||
stats.cacheHits = cacheHits_.load(std::memory_order_relaxed);
|
stats.cacheHits = cacheHits_.load(std::memory_order_relaxed);
|
||||||
stats.cacheMisses = cacheMisses_.load(std::memory_order_relaxed);
|
stats.cacheMisses = cacheMisses_.load(std::memory_order_relaxed);
|
||||||
stats.evictionCount = evictionCount_.load(std::memory_order_relaxed);
|
stats.evictionCount = evictionCount_.load(std::memory_order_relaxed);
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -568,9 +567,9 @@ TexturePool::Stats TexturePool::getStats() const {
|
||||||
* 清零缓存命中、未命中和淘汰计数
|
* 清零缓存命中、未命中和淘汰计数
|
||||||
*/
|
*/
|
||||||
void TexturePool::resetStats() {
|
void TexturePool::resetStats() {
|
||||||
cacheHits_.store(0, std::memory_order_relaxed);
|
cacheHits_.store(0, std::memory_order_relaxed);
|
||||||
cacheMisses_.store(0, std::memory_order_relaxed);
|
cacheMisses_.store(0, std::memory_order_relaxed);
|
||||||
evictionCount_.store(0, std::memory_order_relaxed);
|
evictionCount_.store(0, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -584,48 +583,48 @@ void TexturePool::resetStats() {
|
||||||
*
|
*
|
||||||
* 根据纹理的尺寸、通道数和像素格式计算内存占用
|
* 根据纹理的尺寸、通道数和像素格式计算内存占用
|
||||||
*/
|
*/
|
||||||
size_t TexturePool::calculateTextureMemory(const Texture* texture) {
|
size_t TexturePool::calculateTextureMemory(const Texture *texture) {
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int width = texture->getWidth();
|
int width = texture->getWidth();
|
||||||
int height = texture->getHeight();
|
int height = texture->getHeight();
|
||||||
int channels = texture->getChannels();
|
int channels = texture->getChannels();
|
||||||
|
|
||||||
// 基础内存计算
|
// 基础内存计算
|
||||||
size_t baseSize = static_cast<size_t>(width) * height * channels;
|
size_t baseSize = static_cast<size_t>(width) * height * channels;
|
||||||
|
|
||||||
// 根据像素格式调整
|
// 根据像素格式调整
|
||||||
PixelFormat format = texture->getFormat();
|
PixelFormat format = texture->getFormat();
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PixelFormat::RGB16F:
|
case PixelFormat::RGB16F:
|
||||||
case PixelFormat::RGBA16F:
|
case PixelFormat::RGBA16F:
|
||||||
baseSize *= 2; // 半精度浮点
|
baseSize *= 2; // 半精度浮点
|
||||||
break;
|
break;
|
||||||
case PixelFormat::RGB32F:
|
case PixelFormat::RGB32F:
|
||||||
case PixelFormat::RGBA32F:
|
case PixelFormat::RGBA32F:
|
||||||
baseSize *= 4; // 全精度浮点
|
baseSize *= 4; // 全精度浮点
|
||||||
break;
|
break;
|
||||||
case PixelFormat::Depth16:
|
case PixelFormat::Depth16:
|
||||||
baseSize = static_cast<size_t>(width) * height * 2;
|
baseSize = static_cast<size_t>(width) * height * 2;
|
||||||
break;
|
break;
|
||||||
case PixelFormat::Depth24:
|
case PixelFormat::Depth24:
|
||||||
case PixelFormat::Depth24Stencil8:
|
case PixelFormat::Depth24Stencil8:
|
||||||
baseSize = static_cast<size_t>(width) * height * 4;
|
baseSize = static_cast<size_t>(width) * height * 4;
|
||||||
break;
|
break;
|
||||||
case PixelFormat::Depth32F:
|
case PixelFormat::Depth32F:
|
||||||
baseSize = static_cast<size_t>(width) * height * 4;
|
baseSize = static_cast<size_t>(width) * height * 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 考虑 Mipmaps(大约增加 33% 内存)
|
// 考虑 Mipmaps(大约增加 33% 内存)
|
||||||
// 注意:这里假设生成了 mipmaps,实际应该根据 TextureLoadOptions 判断
|
// 注意:这里假设生成了 mipmaps,实际应该根据 TextureLoadOptions 判断
|
||||||
// baseSize = baseSize * 4 / 3;
|
// baseSize = baseSize * 4 / 3;
|
||||||
|
|
||||||
return baseSize;
|
return baseSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -635,7 +634,7 @@ size_t TexturePool::calculateTextureMemory(const Texture* texture) {
|
||||||
* 检查当前内存使用量是否超过限制
|
* 检查当前内存使用量是否超过限制
|
||||||
*/
|
*/
|
||||||
bool TexturePool::needsEviction() const {
|
bool TexturePool::needsEviction() const {
|
||||||
return maxMemoryUsage_ > 0 && currentMemoryUsage_ > maxMemoryUsage_;
|
return maxMemoryUsage_ > 0 && currentMemoryUsage_ > maxMemoryUsage_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -644,9 +643,9 @@ bool TexturePool::needsEviction() const {
|
||||||
* 如果内存使用量超过限制,执行LRU淘汰
|
* 如果内存使用量超过限制,执行LRU淘汰
|
||||||
*/
|
*/
|
||||||
void TexturePool::tryAutoEvict() {
|
void TexturePool::tryAutoEvict() {
|
||||||
if (needsEviction()) {
|
if (needsEviction()) {
|
||||||
evictLRU(maxMemoryUsage_);
|
evictLRU(maxMemoryUsage_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -511,12 +511,12 @@ 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;
|
||||||
|
|
||||||
|
|
@ -579,7 +579,7 @@ void Node::update(float dt) { onUpdate(dt); }
|
||||||
*
|
*
|
||||||
* 如果需要则对子节点排序,然后调用onRender进行渲染
|
* 如果需要则对子节点排序,然后调用onRender进行渲染
|
||||||
*/
|
*/
|
||||||
void Node::render(RenderBackend &renderer) {
|
void Node::render(Renderer &renderer) {
|
||||||
if (childrenOrderDirty_) {
|
if (childrenOrderDirty_) {
|
||||||
sortChildren();
|
sortChildren();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_command.h>
|
#include <extra2d/graphics/core/render_command.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/scene/scene.h>
|
#include <extra2d/scene/scene.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -48,7 +49,7 @@ void Scene::setViewportSize(const Size &size) {
|
||||||
*
|
*
|
||||||
* 如果场景不可见则直接返回,否则开始帧渲染、渲染内容并结束帧
|
* 如果场景不可见则直接返回,否则开始帧渲染、渲染内容并结束帧
|
||||||
*/
|
*/
|
||||||
void Scene::renderScene(RenderBackend &renderer) {
|
void Scene::renderScene(Renderer &renderer) {
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -65,7 +66,7 @@ void Scene::renderScene(RenderBackend &renderer) {
|
||||||
* 批量更新节点变换,开始精灵批处理并渲染
|
* 批量更新节点变换,开始精灵批处理并渲染
|
||||||
* 注意:视图投影矩阵由 Application 通过 CameraService 设置
|
* 注意:视图投影矩阵由 Application 通过 CameraService 设置
|
||||||
*/
|
*/
|
||||||
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/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_command.h>
|
#include <extra2d/graphics/core/render_command.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/platform/keys.h>
|
#include <extra2d/platform/keys.h>
|
||||||
#include <extra2d/scene/scene_manager.h>
|
#include <extra2d/scene/scene_manager.h>
|
||||||
#include <extra2d/scene/transition_box_scene.h>
|
#include <extra2d/scene/transition_box_scene.h>
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <extra2d/services/event_service.h>
|
#include <extra2d/services/event_service.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
@ -89,32 +90,36 @@ void SceneManager::setupEventListeners() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseMoveListener_ = eventService->addListener(EventType::MouseMoved, [this](Event &e) {
|
mouseMoveListener_ =
|
||||||
auto &mouseEvent = std::get<MouseMoveEvent>(e.data);
|
eventService->addListener(EventType::MouseMoved, [this](Event &e) {
|
||||||
mousePos_ = mouseEvent.position;
|
auto &mouseEvent = std::get<MouseMoveEvent>(e.data);
|
||||||
mouseDelta_ = mouseEvent.delta;
|
mousePos_ = mouseEvent.position;
|
||||||
});
|
mouseDelta_ = mouseEvent.delta;
|
||||||
|
});
|
||||||
|
|
||||||
mousePressListener_ = eventService->addListener(EventType::MouseButtonPressed, [this](Event &e) {
|
mousePressListener_ = eventService->addListener(
|
||||||
auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
|
EventType::MouseButtonPressed, [this](Event &e) {
|
||||||
if (mouseEvent.button == static_cast<int>(Mouse::Left)) {
|
auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
|
||||||
mouseLeftPressed_ = true;
|
if (mouseEvent.button == static_cast<int>(Mouse::Left)) {
|
||||||
mouseLeftDown_ = true;
|
mouseLeftPressed_ = true;
|
||||||
}
|
mouseLeftDown_ = true;
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mouseReleaseListener_ = eventService->addListener(EventType::MouseButtonReleased, [this](Event &e) {
|
mouseReleaseListener_ = eventService->addListener(
|
||||||
auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
|
EventType::MouseButtonReleased, [this](Event &e) {
|
||||||
if (mouseEvent.button == static_cast<int>(Mouse::Left)) {
|
auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
|
||||||
mouseLeftReleased_ = true;
|
if (mouseEvent.button == static_cast<int>(Mouse::Left)) {
|
||||||
mouseLeftDown_ = false;
|
mouseLeftReleased_ = true;
|
||||||
}
|
mouseLeftDown_ = false;
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
scrollListener_ = eventService->addListener(EventType::MouseScrolled, [this](Event &e) {
|
scrollListener_ =
|
||||||
auto &scrollEvent = std::get<MouseScrollEvent>(e.data);
|
eventService->addListener(EventType::MouseScrolled, [this](Event &e) {
|
||||||
scrollDelta_ = scrollEvent.offset.y;
|
auto &scrollEvent = std::get<MouseScrollEvent>(e.data);
|
||||||
});
|
scrollDelta_ = scrollEvent.offset.y;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -610,7 +615,7 @@ void SceneManager::update(float dt) {
|
||||||
*
|
*
|
||||||
* 使用当前场景的背景色清除帧缓冲并渲染场景内容
|
* 使用当前场景的背景色清除帧缓冲并渲染场景内容
|
||||||
*/
|
*/
|
||||||
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,10 +1,11 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_command.h>
|
#include <extra2d/graphics/core/render_command.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/scene/shape_node.h>
|
#include <extra2d/scene/shape_node.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -196,24 +197,18 @@ Ptr<ShapeNode> ShapeNode::createFilledPolygon(const std::vector<Vec2> &points,
|
||||||
* @brief 设置形状的所有顶点
|
* @brief 设置形状的所有顶点
|
||||||
* @param points 顶点坐标数组
|
* @param points 顶点坐标数组
|
||||||
*/
|
*/
|
||||||
void ShapeNode::setPoints(const std::vector<Vec2> &points) {
|
void ShapeNode::setPoints(const std::vector<Vec2> &points) { points_ = points; }
|
||||||
points_ = points;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 添加一个顶点到形状
|
* @brief 添加一个顶点到形状
|
||||||
* @param point 要添加的顶点坐标
|
* @param point 要添加的顶点坐标
|
||||||
*/
|
*/
|
||||||
void ShapeNode::addPoint(const Vec2 &point) {
|
void ShapeNode::addPoint(const Vec2 &point) { points_.push_back(point); }
|
||||||
points_.push_back(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清除所有顶点
|
* @brief 清除所有顶点
|
||||||
*/
|
*/
|
||||||
void ShapeNode::clearPoints() {
|
void ShapeNode::clearPoints() { points_.clear(); }
|
||||||
points_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取形状的边界矩形
|
* @brief 获取形状的边界矩形
|
||||||
|
|
@ -271,7 +266,7 @@ Rect ShapeNode::getBounds() const {
|
||||||
* 注意:变换矩阵已由 Node::onRender 通过 pushTransform 应用,
|
* 注意:变换矩阵已由 Node::onRender 通过 pushTransform 应用,
|
||||||
* 此处直接使用本地坐标即可。
|
* 此处直接使用本地坐标即可。
|
||||||
*/
|
*/
|
||||||
void ShapeNode::onDraw(RenderBackend &renderer) {
|
void ShapeNode::onDraw(Renderer &renderer) {
|
||||||
if (points_.empty()) {
|
if (points_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -361,16 +356,16 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
case ShapeType::Point:
|
case ShapeType::Point:
|
||||||
if (!points_.empty()) {
|
if (!points_.empty()) {
|
||||||
cmd.type = RenderCommandType::FilledCircle;
|
cmd.type = RenderCommandType::FilledCircle;
|
||||||
cmd.data =
|
cmd.data = CircleCommandData{
|
||||||
CircleCommandData{points_[0] + offset, lineWidth_ * 0.5f, color_, 8, 0.0f, true};
|
points_[0] + offset, lineWidth_ * 0.5f, color_, 8, 0.0f, true};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ShapeType::Line:
|
case ShapeType::Line:
|
||||||
if (points_.size() >= 2) {
|
if (points_.size() >= 2) {
|
||||||
cmd.type = RenderCommandType::Line;
|
cmd.type = RenderCommandType::Line;
|
||||||
cmd.data = LineCommandData{points_[0] + offset, points_[1] + offset, color_,
|
cmd.data = LineCommandData{points_[0] + offset, points_[1] + offset,
|
||||||
lineWidth_};
|
color_, lineWidth_};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -380,14 +375,14 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
cmd.type = RenderCommandType::FilledRect;
|
cmd.type = RenderCommandType::FilledRect;
|
||||||
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
|
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
|
||||||
points_[2].y - points_[0].y);
|
points_[2].y - points_[0].y);
|
||||||
cmd.data =
|
cmd.data = RectCommandData{Rect(rect.origin + offset, rect.size),
|
||||||
RectCommandData{Rect(rect.origin + offset, rect.size), color_, 0.0f, true};
|
color_, 0.0f, true};
|
||||||
} else {
|
} else {
|
||||||
cmd.type = RenderCommandType::Rect;
|
cmd.type = RenderCommandType::Rect;
|
||||||
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
|
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
|
||||||
points_[2].y - points_[0].y);
|
points_[2].y - points_[0].y);
|
||||||
cmd.data =
|
cmd.data = RectCommandData{Rect(rect.origin + offset, rect.size),
|
||||||
RectCommandData{Rect(rect.origin + offset, rect.size), color_, lineWidth_, false};
|
color_, lineWidth_, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -397,12 +392,12 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
float radius = points_[1].x;
|
float radius = points_[1].x;
|
||||||
if (filled_) {
|
if (filled_) {
|
||||||
cmd.type = RenderCommandType::FilledCircle;
|
cmd.type = RenderCommandType::FilledCircle;
|
||||||
cmd.data =
|
cmd.data = CircleCommandData{points_[0] + offset, radius, color_,
|
||||||
CircleCommandData{points_[0] + offset, radius, color_, segments_, 0.0f, true};
|
segments_, 0.0f, true};
|
||||||
} else {
|
} else {
|
||||||
cmd.type = RenderCommandType::Circle;
|
cmd.type = RenderCommandType::Circle;
|
||||||
cmd.data = CircleCommandData{points_[0] + offset, radius, color_, segments_,
|
cmd.data = CircleCommandData{points_[0] + offset, radius, color_,
|
||||||
lineWidth_, false};
|
segments_, lineWidth_, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -435,7 +430,8 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
|
||||||
cmd.data = PolygonCommandData{transformedPoints, color_, 0.0f, true};
|
cmd.data = PolygonCommandData{transformedPoints, color_, 0.0f, true};
|
||||||
} else {
|
} else {
|
||||||
cmd.type = RenderCommandType::Polygon;
|
cmd.type = RenderCommandType::Polygon;
|
||||||
cmd.data = PolygonCommandData{transformedPoints, color_, lineWidth_, false};
|
cmd.data =
|
||||||
|
PolygonCommandData{transformedPoints, color_, lineWidth_, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <extra2d/graphics/core/render_command.h>
|
#include <extra2d/graphics/core/render_command.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/graphics/texture/texture.h>
|
#include <extra2d/graphics/texture/texture.h>
|
||||||
#include <extra2d/scene/sprite.h>
|
#include <extra2d/scene/sprite.h>
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ Rect Sprite::getBounds() const {
|
||||||
*
|
*
|
||||||
* 使用世界变换计算最终位置、缩放和旋转,然后绘制精灵
|
* 使用世界变换计算最终位置、缩放和旋转,然后绘制精灵
|
||||||
*/
|
*/
|
||||||
void Sprite::onDraw(RenderBackend &renderer) {
|
void Sprite::onDraw(Renderer &renderer) {
|
||||||
if (!texture_ || !texture_->isValid()) {
|
if (!texture_ || !texture_->isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +151,7 @@ void Sprite::onDraw(RenderBackend &renderer) {
|
||||||
|
|
||||||
auto anchor = getAnchor();
|
auto anchor = getAnchor();
|
||||||
|
|
||||||
// 锚点由 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
|
||||||
|
|
@ -204,7 +204,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,11 +1,12 @@
|
||||||
#include <extra2d/scene/transition_box_scene.h>
|
#include <algorithm>
|
||||||
#include <extra2d/app/application.h>
|
#include <extra2d/app/application.h>
|
||||||
#include <extra2d/core/color.h>
|
#include <extra2d/core/color.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/platform/glfw/glfw_window.h>
|
#include <extra2d/platform/glfw/glfw_window.h>
|
||||||
#include <algorithm>
|
#include <extra2d/scene/transition_box_scene.h>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,9 +26,8 @@ TransitionBoxScene::TransitionBoxScene(float duration, Ptr<Scene> inScene,
|
||||||
* @param divisions 方块分割数
|
* @param divisions 方块分割数
|
||||||
* @return 过渡场景智能指针
|
* @return 过渡场景智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<TransitionBoxScene> TransitionBoxScene::create(float duration,
|
Ptr<TransitionBoxScene>
|
||||||
Ptr<Scene> inScene,
|
TransitionBoxScene::create(float duration, Ptr<Scene> inScene, int divisions) {
|
||||||
int divisions) {
|
|
||||||
return makePtr<TransitionBoxScene>(duration, inScene, divisions);
|
return makePtr<TransitionBoxScene>(duration, inScene, divisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,8 +36,7 @@ Ptr<TransitionBoxScene> TransitionBoxScene::create(float duration,
|
||||||
*
|
*
|
||||||
* 方块过渡不需要特殊的初始化
|
* 方块过渡不需要特殊的初始化
|
||||||
*/
|
*/
|
||||||
void TransitionBoxScene::onTransitionStart() {
|
void TransitionBoxScene::onTransitionStart() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新过渡进度
|
* @brief 更新过渡进度
|
||||||
|
|
@ -53,7 +52,7 @@ void TransitionBoxScene::updateTransition(float dt) {
|
||||||
*
|
*
|
||||||
* 先渲染新场景,然后绘制方块遮罩逐渐消失
|
* 先渲染新场景,然后绘制方块遮罩逐渐消失
|
||||||
*/
|
*/
|
||||||
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/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
#include <extra2d/platform/glfw/glfw_window.h>
|
#include <extra2d/platform/glfw/glfw_window.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,8 @@
|
||||||
#include <extra2d/scene/transition_flip_scene.h>
|
|
||||||
#include <extra2d/core/math_types.h>
|
#include <extra2d/core/math_types.h>
|
||||||
#include <extra2d/graphics/camera/camera.h>
|
#include <extra2d/graphics/camera/camera.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
|
#include <extra2d/scene/transition_flip_scene.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -22,9 +23,8 @@ TransitionFlipScene::TransitionFlipScene(float duration, Ptr<Scene> inScene,
|
||||||
* @param axis 翻转轴
|
* @param axis 翻转轴
|
||||||
* @return 过渡场景智能指针
|
* @return 过渡场景智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<TransitionFlipScene> TransitionFlipScene::create(float duration,
|
Ptr<TransitionFlipScene>
|
||||||
Ptr<Scene> inScene,
|
TransitionFlipScene::create(float duration, Ptr<Scene> inScene, Axis axis) {
|
||||||
Axis axis) {
|
|
||||||
return makePtr<TransitionFlipScene>(duration, inScene, axis);
|
return makePtr<TransitionFlipScene>(duration, inScene, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,8 +33,7 @@ Ptr<TransitionFlipScene> TransitionFlipScene::create(float duration,
|
||||||
*
|
*
|
||||||
* 翻页过渡不需要特殊的初始化
|
* 翻页过渡不需要特殊的初始化
|
||||||
*/
|
*/
|
||||||
void TransitionFlipScene::onTransitionStart() {
|
void TransitionFlipScene::onTransitionStart() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新过渡进度
|
* @brief 更新过渡进度
|
||||||
|
|
@ -50,9 +49,10 @@ void TransitionFlipScene::updateTransition(float dt) {
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的翻转角度
|
* 根据进度控制新旧场景的翻转角度
|
||||||
*/
|
*/
|
||||||
void TransitionFlipScene::renderContent(RenderBackend &renderer) {
|
void TransitionFlipScene::renderContent(Renderer &renderer) {
|
||||||
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
float easeProgress = progress_ < 0.5f
|
||||||
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
? 2.0f * progress_ * progress_
|
||||||
|
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
||||||
|
|
||||||
float angle = easeProgress * PI_F;
|
float angle = easeProgress * PI_F;
|
||||||
|
|
||||||
|
|
@ -103,7 +103,6 @@ void TransitionFlipScene::renderContent(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#include <extra2d/scene/transition_scale_scene.h>
|
|
||||||
#include <extra2d/graphics/camera/camera.h>
|
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <extra2d/graphics/camera/camera.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
|
#include <extra2d/scene/transition_scale_scene.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -29,8 +30,7 @@ Ptr<TransitionScaleScene> TransitionScaleScene::create(float duration,
|
||||||
*
|
*
|
||||||
* 缩放过渡不需要特殊的初始化
|
* 缩放过渡不需要特殊的初始化
|
||||||
*/
|
*/
|
||||||
void TransitionScaleScene::onTransitionStart() {
|
void TransitionScaleScene::onTransitionStart() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新过渡进度
|
* @brief 更新过渡进度
|
||||||
|
|
@ -46,9 +46,10 @@ void TransitionScaleScene::updateTransition(float dt) {
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的缩放比例
|
* 根据进度控制新旧场景的缩放比例
|
||||||
*/
|
*/
|
||||||
void TransitionScaleScene::renderContent(RenderBackend &renderer) {
|
void TransitionScaleScene::renderContent(Renderer &renderer) {
|
||||||
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
float easeProgress = progress_ < 0.5f
|
||||||
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
? 2.0f * progress_ * progress_
|
||||||
|
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
||||||
|
|
||||||
if (outScene_) {
|
if (outScene_) {
|
||||||
float scale = std::max(0.01f, 1.0f - easeProgress);
|
float scale = std::max(0.01f, 1.0f - easeProgress);
|
||||||
|
|
@ -83,7 +84,6 @@ void TransitionScaleScene::renderContent(RenderBackend &renderer) {
|
||||||
camera->setZoom(originalZoom);
|
camera->setZoom(originalZoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <extra2d/core/service_locator.h>
|
#include <extra2d/core/service_locator.h>
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
#include <extra2d/graphics/opengl/gl_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>
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ void TransitionScene::cancel(bool immediate) {
|
||||||
*
|
*
|
||||||
* 默认先渲染退出场景,再渲染进入场景
|
* 默认先渲染退出场景,再渲染进入场景
|
||||||
*/
|
*/
|
||||||
void TransitionScene::renderContent(RenderBackend &renderer) {
|
void TransitionScene::renderContent(Renderer &renderer) {
|
||||||
drawOutScene(renderer);
|
drawOutScene(renderer);
|
||||||
drawInScene(renderer);
|
drawInScene(renderer);
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,7 @@ void TransitionScene::renderContent(RenderBackend &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);
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +138,7 @@ 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,7 +1,8 @@
|
||||||
#include <extra2d/scene/transition_slide_scene.h>
|
|
||||||
#include <extra2d/graphics/camera/camera.h>
|
|
||||||
#include <extra2d/graphics/core/render_backend.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <extra2d/graphics/camera/camera.h>
|
||||||
|
#include <extra2d/graphics/opengl/gl_renderer.h>
|
||||||
|
#include <extra2d/scene/transition_slide_scene.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -22,8 +23,9 @@ TransitionSlideScene::TransitionSlideScene(float duration, Ptr<Scene> inScene,
|
||||||
* @param direction 滑动方向
|
* @param direction 滑动方向
|
||||||
* @return 过渡场景智能指针
|
* @return 过渡场景智能指针
|
||||||
*/
|
*/
|
||||||
Ptr<TransitionSlideScene> TransitionSlideScene::create(
|
Ptr<TransitionSlideScene>
|
||||||
float duration, Ptr<Scene> inScene, TransitionDirection direction) {
|
TransitionSlideScene::create(float duration, Ptr<Scene> inScene,
|
||||||
|
TransitionDirection direction) {
|
||||||
return makePtr<TransitionSlideScene>(duration, inScene, direction);
|
return makePtr<TransitionSlideScene>(duration, inScene, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,8 +34,7 @@ Ptr<TransitionSlideScene> TransitionSlideScene::create(
|
||||||
*
|
*
|
||||||
* 滑动过渡不需要特殊的初始化
|
* 滑动过渡不需要特殊的初始化
|
||||||
*/
|
*/
|
||||||
void TransitionSlideScene::onTransitionStart() {
|
void TransitionSlideScene::onTransitionStart() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新过渡进度
|
* @brief 更新过渡进度
|
||||||
|
|
@ -49,7 +50,7 @@ void TransitionSlideScene::updateTransition(float dt) {
|
||||||
*
|
*
|
||||||
* 根据进度控制新旧场景的滑动位置
|
* 根据进度控制新旧场景的滑动位置
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
||||||
|
|
@ -67,8 +68,9 @@ void TransitionSlideScene::renderContent(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
|
float easeProgress = progress_ < 0.5f
|
||||||
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
? 2.0f * progress_ * progress_
|
||||||
|
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
|
||||||
|
|
||||||
if (outScene_) {
|
if (outScene_) {
|
||||||
float offsetX = 0.0f;
|
float offsetX = 0.0f;
|
||||||
|
|
@ -135,7 +137,6 @@ void TransitionSlideScene::renderContent(RenderBackend &renderer) {
|
||||||
camera->setPos(originalPos);
|
camera->setPos(originalPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneService::collectRenderCommands(std::vector<RenderCommand> &commands) {
|
void SceneService::collectRenderCommands(std::vector<RenderCommand> &commands) {
|
||||||
manager_.collectRenderCommands(commands);
|
manager_.collectRenderCommands(commands);
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ flowchart TB
|
||||||
subgraph Graphics["Graphics (图形系统)"]
|
subgraph Graphics["Graphics (图形系统)"]
|
||||||
direction TB
|
direction TB
|
||||||
RESOURCES[Resources<br/>资源抽象层]
|
RESOURCES[Resources<br/>资源抽象层]
|
||||||
BACKEND[RenderBackend<br/>渲染后端]
|
BACKEND[Renderer<br/>渲染后端]
|
||||||
BATCH[Batch Layer<br/>批处理层]
|
BATCH[Batch Layer<br/>批处理层]
|
||||||
GL[OpenGL Backend<br/>OpenGL 后端]
|
GL[OpenGL Backend<br/>OpenGL 后端]
|
||||||
VK[Vulkan Backend<br/>Vulkan 后端]
|
VK[Vulkan Backend<br/>Vulkan 后端]
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,9 @@ cameraService->setZoom(2.0f);
|
||||||
### 渲染后端接口
|
### 渲染后端接口
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class RenderBackend {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
virtual ~RenderBackend() = default;
|
virtual ~Renderer() = default;
|
||||||
|
|
||||||
// 生命周期
|
// 生命周期
|
||||||
virtual bool init(IWindow* window) = 0;
|
virtual bool init(IWindow* window) = 0;
|
||||||
|
|
@ -276,7 +276,7 @@ public:
|
||||||
virtual void drawText(const FontAtlas &font, const std::string &text, const Vec2 &position, const Color &color) = 0;
|
virtual void drawText(const FontAtlas &font, const std::string &text, const Vec2 &position, const Color &color) = 0;
|
||||||
|
|
||||||
// 工厂方法
|
// 工厂方法
|
||||||
static UniquePtr<RenderBackend> create(BackendType type);
|
static UniquePtr<Renderer> create(BackendType type);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ public:
|
||||||
virtual void onEnter();
|
virtual void onEnter();
|
||||||
virtual void onExit();
|
virtual void onExit();
|
||||||
virtual void onUpdate(float dt);
|
virtual void onUpdate(float dt);
|
||||||
virtual void onRender(RenderBackend& renderer);
|
virtual void onRender(Renderer& renderer);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ public:
|
||||||
* @brief 自定义渲染逻辑
|
* @brief 自定义渲染逻辑
|
||||||
* @param renderer 渲染后端
|
* @param renderer 渲染后端
|
||||||
*/
|
*/
|
||||||
void onRender(RenderBackend &renderer) override { Scene::onRender(renderer); }
|
void onRender(Renderer &renderer) override { Scene::onRender(renderer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
@ -107,9 +107,7 @@ int main(int argc, char *argv[]) {
|
||||||
cfg.priority = 0;
|
cfg.priority = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use<RenderModule>([](auto &cfg) {
|
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
||||||
cfg.priority = 10;
|
|
||||||
});
|
|
||||||
|
|
||||||
std::cout << "Initializing application..." << std::endl;
|
std::cout << "Initializing application..." << std::endl;
|
||||||
if (!app.init()) {
|
if (!app.init()) {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ public:
|
||||||
time_ = 0.0f;
|
time_ = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void onRender(RenderBackend &renderer) override { Scene::onRender(renderer); }
|
void onRender(Renderer &renderer) override { Scene::onRender(renderer); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float time_ = 0.0f;
|
float time_ = 0.0f;
|
||||||
|
|
@ -44,9 +44,7 @@ int main(int argc, char *argv[]) {
|
||||||
cfg.w = 800;
|
cfg.w = 800;
|
||||||
cfg.h = 600;
|
cfg.h = 600;
|
||||||
});
|
});
|
||||||
app.use<RenderModule>([](auto &cfg) {
|
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
||||||
cfg.priority = 10;
|
|
||||||
});
|
|
||||||
app.use<HelloModule>([](auto &cfg) {
|
app.use<HelloModule>([](auto &cfg) {
|
||||||
cfg.greeting = "Hello from custom module!";
|
cfg.greeting = "Hello from custom module!";
|
||||||
cfg.repeatCount = 3;
|
cfg.repeatCount = 3;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* @file main.cpp
|
* @file main.cpp
|
||||||
* @brief Extra2D 图片显示示例
|
* @brief Extra2D 图片显示示例
|
||||||
*
|
*
|
||||||
* 演示如何使用 RenderBackend 抽象接口加载和显示图片
|
* 演示如何使用 Renderer 抽象接口加载和显示图片
|
||||||
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -40,14 +40,14 @@ public:
|
||||||
|
|
||||||
void onExit() override { texture_.reset(); }
|
void onExit() override { texture_.reset(); }
|
||||||
|
|
||||||
void onRender(RenderBackend &renderer) override {
|
void onRender(Renderer &renderer) override {
|
||||||
Scene::onRender(renderer);
|
Scene::onRender(renderer);
|
||||||
|
|
||||||
if (!texture_) {
|
if (!texture_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 RenderBackend 的抽象接口绘制图片
|
// 使用 Renderer 的抽象接口绘制图片
|
||||||
// 不依赖任何特定后端(如 OpenGL)
|
// 不依赖任何特定后端(如 OpenGL)
|
||||||
// 自动批处理:无需手动调用 begin/endSpriteBatch
|
// 自动批处理:无需手动调用 begin/endSpriteBatch
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ public:
|
||||||
float x = (windowWidth - displayWidth) * 0.5f;
|
float x = (windowWidth - displayWidth) * 0.5f;
|
||||||
float y = (windowHeight - displayHeight) * 0.5f;
|
float y = (windowHeight - displayHeight) * 0.5f;
|
||||||
|
|
||||||
// 使用 RenderBackend 的 drawSprite 方法绘制图片
|
// 使用 Renderer 的 drawSprite 方法绘制图片
|
||||||
// 参数:纹理、目标矩形、源矩形、颜色、旋转角度、锚点
|
// 参数:纹理、目标矩形、源矩形、颜色、旋转角度、锚点
|
||||||
Rect destRect(x, y, displayWidth, displayHeight);
|
Rect destRect(x, y, displayWidth, displayHeight);
|
||||||
Rect srcRect(0, 0, imgWidth, imgHeight);
|
Rect srcRect(0, 0, imgWidth, imgHeight);
|
||||||
|
|
@ -80,11 +80,11 @@ public:
|
||||||
// 注意:无需手动调用 renderer.endSpriteBatch(),帧结束时会自动刷新
|
// 注意:无需手动调用 renderer.endSpriteBatch(),帧结束时会自动刷新
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRenderer(RenderBackend *renderer) { renderer_ = renderer; }
|
void setRenderer(Renderer *renderer) { renderer_ = renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ptr<Texture> texture_;
|
Ptr<Texture> texture_;
|
||||||
RenderBackend *renderer_ = nullptr;
|
Renderer *renderer_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
@ -103,9 +103,7 @@ int main(int argc, char *argv[]) {
|
||||||
cfg.priority = 0;
|
cfg.priority = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use<RenderModule>([](auto &cfg) {
|
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
||||||
cfg.priority = 10;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!app.init()) {
|
if (!app.init()) {
|
||||||
std::cerr << "Failed to initialize application!" << std::endl;
|
std::cerr << "Failed to initialize application!" << std::endl;
|
||||||
|
|
@ -127,7 +125,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取渲染器
|
// 获取渲染器
|
||||||
RenderBackend *renderer = app.renderer();
|
Renderer *renderer = app.renderer();
|
||||||
|
|
||||||
// 创建并配置场景
|
// 创建并配置场景
|
||||||
auto scene = makeShared<ImageDisplayScene>();
|
auto scene = makeShared<ImageDisplayScene>();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* @file main.cpp
|
* @file main.cpp
|
||||||
* @brief Extra2D 文字渲染示例
|
* @brief Extra2D 文字渲染示例
|
||||||
*
|
*
|
||||||
* 演示如何使用 RenderBackend 抽象接口渲染文字
|
* 演示如何使用 Renderer 抽象接口渲染文字
|
||||||
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
void onExit() override { font_.reset(); }
|
void onExit() override { font_.reset(); }
|
||||||
|
|
||||||
void onRender(RenderBackend &renderer) override {
|
void onRender(Renderer &renderer) override {
|
||||||
Scene::onRender(renderer);
|
Scene::onRender(renderer);
|
||||||
|
|
||||||
if (!font_) {
|
if (!font_) {
|
||||||
|
|
@ -85,21 +85,21 @@ public:
|
||||||
Color(0.5f, 0.5f, 0.5f, 1.0f));
|
Color(0.5f, 0.5f, 0.5f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRenderer(RenderBackend *renderer) { renderer_ = renderer; }
|
void setRenderer(Renderer *renderer) { renderer_ = renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderText(RenderBackend &renderer, const std::string &text, float x,
|
void renderText(Renderer &renderer, const std::string &text, float x, float y,
|
||||||
float y, const Color &color) {
|
const Color &color) {
|
||||||
if (!font_) {
|
if (!font_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 RenderBackend 的 drawText 方法
|
// 使用 Renderer 的 drawText 方法
|
||||||
renderer.drawText(*font_, text, Vec2(x, y), color);
|
renderer.drawText(*font_, text, Vec2(x, y), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<FontAtlas> font_;
|
Ptr<FontAtlas> font_;
|
||||||
RenderBackend *renderer_ = nullptr;
|
Renderer *renderer_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
@ -139,7 +139,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取渲染器
|
// 获取渲染器
|
||||||
RenderBackend *renderer = app.renderer();
|
Renderer *renderer = app.renderer();
|
||||||
|
|
||||||
// 创建并配置场景
|
// 创建并配置场景
|
||||||
auto scene = makeShared<TextRenderingScene>();
|
auto scene = makeShared<TextRenderingScene>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue