diff --git a/Extra2D/include/extra2d/core/module.h b/Extra2D/include/extra2d/core/module.h index 02fcc33..d1734b4 100644 --- a/Extra2D/include/extra2d/core/module.h +++ b/Extra2D/include/extra2d/core/module.h @@ -16,48 +16,54 @@ class Application; class Module { public: virtual ~Module() = default; - + /** * @brief 初始化模块 * @return 初始化成功返回 true */ virtual bool init() = 0; - + /** * @brief 关闭模块 */ virtual void shutdown() = 0; - + /** * @brief 检查模块是否已初始化 * @return 已初始化返回 true */ virtual bool ok() const = 0; - + /** * @brief 获取模块名称 * @return 模块名称 */ virtual const char* name() const = 0; - + /** * @brief 获取模块优先级(数值越小越优先) * @return 优先级值 */ virtual int priority() const { return 100; } - + /** * @brief 获取模块依赖列表 * @return 依赖模块类型列表 */ virtual std::vector deps() const { return {}; } - + + /** + * @brief 检查模块是否支持并行初始化 + * @return 支持并行初始化返回 true + */ + virtual bool allowParallelInit() const { return true; } + /** * @brief 设置所属Application * @param app Application指针 */ void setApp(class Application* app) { app_ = app; } - + /** * @brief 获取Application * @return Application指针 diff --git a/Extra2D/include/extra2d/core/registry.h b/Extra2D/include/extra2d/core/registry.h index 8196e67..157c568 100644 --- a/Extra2D/include/extra2d/core/registry.h +++ b/Extra2D/include/extra2d/core/registry.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace extra2d { @@ -18,10 +19,10 @@ class Application; class Registry { public: static Registry& instance(); - + Registry(const Registry&) = delete; Registry& operator=(const Registry&) = delete; - + /** * @brief 注册模块 * @tparam T 模块类型 @@ -32,19 +33,19 @@ public: template T* use(Args&&... args) { static_assert(std::is_base_of_v, "T must derive from Module"); - + auto typeIdx = std::type_index(typeid(T)); if (modules_.count(typeIdx)) { return static_cast(modules_[typeIdx].get()); } - + auto module = makeUnique(std::forward(args)...); T* ptr = module.get(); module->setApp(app_); modules_[typeIdx] = std::move(module); return ptr; } - + /** * @brief 获取模块 * @tparam T 模块类型 @@ -59,7 +60,7 @@ public: } return nullptr; } - + /** * @brief 获取模块(基类版本) * @param typeIdx 类型索引 @@ -72,28 +73,28 @@ public: } return nullptr; } - + /** * @brief 设置Application */ void setApp(Application* app) { app_ = app; } - + /** - * @brief 初始化所有模块(按优先级拓扑排序) + * @brief 初始化所有模块(按优先级拓扑排序,支持并行初始化) * @return 初始化成功返回 true */ bool init(); - + /** * @brief 关闭所有模块 */ void shutdown(); - + /** * @brief 清空所有模块 */ void clear(); - + /** * @brief 获取模块数量 */ @@ -102,13 +103,20 @@ public: private: Registry() = default; ~Registry() = default; - + /** * @brief 拓扑排序模块 * @return 排序后的模块列表 */ std::vector topologicalSort(); - + + /** + * @brief 按层级对模块进行分组 + * 同一层级的模块没有相互依赖,可以并行初始化 + * @return 按层级分组的模块列表 + */ + std::vector> groupByLevel(); + std::unordered_map> modules_; Application* app_ = nullptr; }; diff --git a/Extra2D/include/extra2d/graphics/core/render_module.h b/Extra2D/include/extra2d/graphics/core/render_module.h index 9a282b9..4f636a3 100644 --- a/Extra2D/include/extra2d/graphics/core/render_module.h +++ b/Extra2D/include/extra2d/graphics/core/render_module.h @@ -58,6 +58,13 @@ public: return {std::type_index(typeid(WindowModule))}; } + /** + * @brief 是否允许并行初始化 + * RenderModule 需要 OpenGL 上下文,必须在主线程初始化 + * @return 不允许并行初始化返回 false + */ + bool allowParallelInit() const override { return false; } + /** * @brief 获取渲染器 * @return 渲染后端指针 diff --git a/Extra2D/include/extra2d/graphics/shader/shader_loader.h b/Extra2D/include/extra2d/graphics/shader/shader_loader.h index 3f8bdc3..b752cd6 100644 --- a/Extra2D/include/extra2d/graphics/shader/shader_loader.h +++ b/Extra2D/include/extra2d/graphics/shader/shader_loader.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include #include @@ -11,24 +13,95 @@ namespace extra2d { // Shader加载结果 // ============================================================================ struct ShaderLoadResult { - bool success = false; - std::string errorMessage; - std::string vertSource; - std::string fragSource; - std::vector dependencies; + bool success = false; + std::string errorMessage; + std::string vertSource; + std::string fragSource; + std::vector dependencies; +}; + +// ============================================================================ +// Shader Uniform 定义 +// ============================================================================ +struct ShaderUniformDef { + std::string type; + std::string description; + float defaultValue = 0.0f; // 默认值(用于float类型) + float defaultVec4[4] = {0, 0, 0, 0}; // 默认值(用于vec4类型) + float defaultMat4[16] = { + 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1}; // 默认值(用于mat4类型,默认单位矩阵) + int defaultInt = 0; // 默认值(用于int类型) + bool defaultBool = false; // 默认值(用于bool类型) + bool hasDefault = false; // 是否有默认值 +}; + +// ============================================================================ +// Shader Uniform 值类型 +// ============================================================================ +struct ShaderUniformValue { + enum class Type { Float, Int, Bool, Vec2, Vec3, Vec4, Mat4 } type; + + union { + float f[16]; // 足够存储 mat4 + int i; + bool b; + } data; + + // 构造函数 + ShaderUniformValue() : type(Type::Float) { data.f[0] = 0; } + ShaderUniformValue(float v) : type(Type::Float) { data.f[0] = v; } + ShaderUniformValue(int v) : type(Type::Int) { data.i = v; } + ShaderUniformValue(bool v) : type(Type::Bool) { data.b = v; } + ShaderUniformValue(const glm::vec2 &v) : type(Type::Vec2) { + data.f[0] = v.x; + data.f[1] = v.y; + } + ShaderUniformValue(const glm::vec3 &v) : type(Type::Vec3) { + data.f[0] = v.x; + data.f[1] = v.y; + data.f[2] = v.z; + } + ShaderUniformValue(const glm::vec4 &v) : type(Type::Vec4) { + data.f[0] = v.x; + data.f[1] = v.y; + data.f[2] = v.z; + data.f[3] = v.w; + } + ShaderUniformValue(const glm::mat4 &m) : type(Type::Mat4) { + const float *ptr = glm::value_ptr(m); + for (int i = 0; i < 16; ++i) + data.f[i] = ptr[i]; + } +}; + +// Uniform 值映射表 +using UniformValueMap = std::unordered_map; + +// ============================================================================ +// Shader Sampler 定义 +// ============================================================================ +struct ShaderSamplerDef { + std::string type; + std::string description; }; // ============================================================================ // Shader元数据 // ============================================================================ struct ShaderMetadata { - std::string name; - std::string vertPath; - std::string fragPath; - std::string combinedPath; - uint64_t lastModified = 0; - std::vector defines; - std::unordered_map uniforms; + std::string name; + std::string category; + std::string version; + std::string description; + std::string vertPath; + std::string fragPath; + std::string combinedPath; + uint64_t lastModified = 0; + std::vector defines; + std::unordered_map uniforms; + std::unordered_map uniformDefs; + std::unordered_map samplerDefs; }; // ============================================================================ @@ -36,65 +109,61 @@ struct ShaderMetadata { // ============================================================================ class IShaderLoader { public: - virtual ~IShaderLoader() = default; + virtual ~IShaderLoader() = default; - /** - * @brief 从分离文件加载Shader (.vert + .frag) - * @param name Shader名称 - * @param vertPath 顶点着色器文件路径 - * @param fragPath 片段着色器文件路径 - * @return 加载结果 - */ - virtual ShaderLoadResult loadFromSeparateFiles( - const std::string& name, - const std::string& vertPath, - const std::string& fragPath) = 0; + /** + * @brief 从分离文件加载Shader (.vert + .frag) + * @param name Shader名称 + * @param vertPath 顶点着色器文件路径 + * @param fragPath 片段着色器文件路径 + * @return 加载结果 + */ + virtual ShaderLoadResult + loadFromSeparateFiles(const std::string &name, const std::string &vertPath, + const std::string &fragPath) = 0; - /** - * @brief 从组合文件加载Shader (.shader) - * @param path 组合Shader文件路径 - * @return 加载结果 - */ - virtual ShaderLoadResult loadFromCombinedFile(const std::string& path) = 0; + /** + * @brief 从组合文件加载Shader (.shader) + * @param path 组合Shader文件路径 + * @return 加载结果 + */ + virtual ShaderLoadResult loadFromCombinedFile(const std::string &path) = 0; - /** - * @brief 从源码字符串加载Shader - * @param vertSource 顶点着色器源码 - * @param fragSource 片段着色器源码 - * @return 加载结果 - */ - virtual ShaderLoadResult loadFromSource( - const std::string& vertSource, - const std::string& fragSource) = 0; + /** + * @brief 从源码字符串加载Shader + * @param vertSource 顶点着色器源码 + * @param fragSource 片段着色器源码 + * @return 加载结果 + */ + virtual ShaderLoadResult loadFromSource(const std::string &vertSource, + const std::string &fragSource) = 0; - /** - * @brief 处理Shader源码中的#include指令 - * @param source 原始源码 - * @param baseDir 基础目录 - * @param outDependencies 输出依赖列表 - * @return 处理后的源码 - */ - virtual std::string processIncludes( - const std::string& source, - const std::string& baseDir, - std::vector& outDependencies) = 0; + /** + * @brief 处理Shader源码中的#include指令 + * @param source 原始源码 + * @param baseDir 基础目录 + * @param outDependencies 输出依赖列表 + * @return 处理后的源码 + */ + virtual std::string + processIncludes(const std::string &source, const std::string &baseDir, + std::vector &outDependencies) = 0; - /** - * @brief 应用预处理器定义 - * @param source 原始源码 - * @param defines 预处理器定义列表 - * @return 处理后的源码 - */ - virtual std::string applyDefines( - const std::string& source, - const std::vector& defines) = 0; + /** + * @brief 应用预处理器定义 + * @param source 原始源码 + * @param defines 预处理器定义列表 + * @return 处理后的源码 + */ + virtual std::string applyDefines(const std::string &source, + const std::vector &defines) = 0; - /** - * @brief 获取Shader元数据 - * @param path Shader文件路径 - * @return 元数据 - */ - virtual ShaderMetadata getMetadata(const std::string& path) = 0; + /** + * @brief 获取Shader元数据 + * @param path Shader文件路径 + * @return 元数据 + */ + virtual ShaderMetadata getMetadata(const std::string &path) = 0; }; // ============================================================================ @@ -102,126 +171,122 @@ public: // ============================================================================ class ShaderLoader : public IShaderLoader { public: - ShaderLoader(); - ~ShaderLoader() override = default; + ShaderLoader(); + ~ShaderLoader() override = default; - /** - * @brief 从分离文件加载Shader (.vert + .frag) - * @param name Shader名称 - * @param vertPath 顶点着色器文件路径 - * @param fragPath 片段着色器文件路径 - * @return 加载结果 - */ - ShaderLoadResult loadFromSeparateFiles( - const std::string& name, - const std::string& vertPath, - const std::string& fragPath) override; + /** + * @brief 从分离文件加载Shader (.vert + .frag) + * @param name Shader名称 + * @param vertPath 顶点着色器文件路径 + * @param fragPath 片段着色器文件路径 + * @return 加载结果 + */ + ShaderLoadResult loadFromSeparateFiles(const std::string &name, + const std::string &vertPath, + const std::string &fragPath) override; - /** - * @brief 从组合文件加载Shader (.shader) - * @param path 组合Shader文件路径 - * @return 加载结果 - */ - ShaderLoadResult loadFromCombinedFile(const std::string& path) override; + /** + * @brief 从组合文件加载Shader (.shader) + * @param path 组合Shader文件路径 + * @return 加载结果 + */ + ShaderLoadResult loadFromCombinedFile(const std::string &path) override; - /** - * @brief 从源码字符串加载Shader - * @param vertSource 顶点着色器源码 - * @param fragSource 片段着色器源码 - * @return 加载结果 - */ - ShaderLoadResult loadFromSource( - const std::string& vertSource, - const std::string& fragSource) override; + /** + * @brief 从源码字符串加载Shader + * @param vertSource 顶点着色器源码 + * @param fragSource 片段着色器源码 + * @return 加载结果 + */ + ShaderLoadResult loadFromSource(const std::string &vertSource, + const std::string &fragSource) override; - /** - * @brief 处理Shader源码中的#include指令 - * @param source 原始源码 - * @param baseDir 基础目录 - * @param outDependencies 输出依赖列表 - * @return 处理后的源码 - */ - std::string processIncludes( - const std::string& source, - const std::string& baseDir, - std::vector& outDependencies) override; + /** + * @brief 处理Shader源码中的#include指令 + * @param source 原始源码 + * @param baseDir 基础目录 + * @param outDependencies 输出依赖列表 + * @return 处理后的源码 + */ + std::string + processIncludes(const std::string &source, const std::string &baseDir, + std::vector &outDependencies) override; - /** - * @brief 应用预处理器定义 - * @param source 原始源码 - * @param defines 预处理器定义列表 - * @return 处理后的源码 - */ - std::string applyDefines( - const std::string& source, - const std::vector& defines) override; + /** + * @brief 应用预处理器定义 + * @param source 原始源码 + * @param defines 预处理器定义列表 + * @return 处理后的源码 + */ + std::string applyDefines(const std::string &source, + const std::vector &defines) override; - /** - * @brief 获取Shader元数据 - * @param path Shader文件路径 - * @return 元数据 - */ - ShaderMetadata getMetadata(const std::string& path) override; + /** + * @brief 获取Shader元数据 + * @param path Shader文件路径 + * @return 元数据 + */ + ShaderMetadata getMetadata(const std::string &path) override; - /** - * @brief 添加include搜索路径 - * @param path 搜索路径 - */ - void addIncludePath(const std::string& path); + /** + * @brief 添加include搜索路径 + * @param path 搜索路径 + */ + void addIncludePath(const std::string &path); - /** - * @brief 读取文件内容 - * @param filepath 文件路径 - * @return 文件内容字符串 - */ - static std::string readFile(const std::string& filepath); + /** + * @brief 读取文件内容 + * @param filepath 文件路径 + * @return 文件内容字符串 + */ + static std::string readFile(const std::string &filepath); - /** - * @brief 获取文件修改时间 - * @param filepath 文件路径 - * @return 修改时间戳 - */ - static uint64_t getFileModifiedTime(const std::string& filepath); + /** + * @brief 获取文件修改时间 + * @param filepath 文件路径 + * @return 修改时间戳 + */ + static uint64_t getFileModifiedTime(const std::string &filepath); - /** - * @brief 检查文件是否存在 - * @param filepath 文件路径 - * @return 存在返回true,否则返回false - */ - static bool fileExists(const std::string& filepath); + /** + * @brief 检查文件是否存在 + * @param filepath 文件路径 + * @return 存在返回true,否则返回false + */ + static bool fileExists(const std::string &filepath); private: - std::vector includePaths_; - std::unordered_map includeCache_; + std::vector includePaths_; + std::unordered_map includeCache_; - /** - * @brief 解析组合Shader文件 - * @param content 文件内容 - * @param outVert 输出顶点着色器源码 - * @param outFrag 输出片段着色器源码 - * @param outMetadata 输出元数据 - * @return 解析成功返回true,失败返回false - */ - bool parseCombinedFile(const std::string& content, - std::string& outVert, - std::string& outFrag, - ShaderMetadata& outMetadata); + /** + * @brief 解析组合Shader文件 + * @param content 文件内容 + * @param outVert 输出顶点着色器源码 + * @param outFrag 输出片段着色器源码 + * @param outMetadata 输出元数据 + * @return 解析成功返回true,失败返回false + */ + bool parseCombinedFile(const std::string &content, std::string &outVert, + std::string &outFrag, ShaderMetadata &outMetadata); - /** - * @brief 解析元数据JSON块 - * @param jsonContent JSON内容 - * @param outMetadata 输出元数据 - * @return 解析成功返回true,失败返回false - */ - bool parseMetadata(const std::string& jsonContent, ShaderMetadata& outMetadata); + /** + * @brief 解析元数据JSON块 + * @param jsonContent JSON内容 + * @param outMetadata 输出元数据 + * @return 解析成功返回true,失败返回false + */ + bool parseMetadata(const std::string &jsonContent, + ShaderMetadata &outMetadata); - /** - * @brief 查找include文件路径 - * @param includeName include文件名 - * @param baseDir 基础目录 - * @return 找到的完整路径,未找到返回空字符串 - */ - std::string findIncludeFile(const std::string& includeName, const std::string& baseDir); + /** + * @brief 查找include文件路径 + * @param includeName include文件名 + * @param baseDir 基础目录 + * @return 找到的完整路径,未找到返回空字符串 + */ + std::string findIncludeFile(const std::string &includeName, + const std::string &baseDir); }; } // namespace extra2d diff --git a/Extra2D/include/extra2d/graphics/shader/shader_manager.h b/Extra2D/include/extra2d/graphics/shader/shader_manager.h index e4d6efa..d5dadc2 100644 --- a/Extra2D/include/extra2d/graphics/shader/shader_manager.h +++ b/Extra2D/include/extra2d/graphics/shader/shader_manager.h @@ -201,6 +201,44 @@ public: */ ShaderLoader& getLoader() { return loader_; } + /** + * @brief 获取Shader元数据 + * @param name Shader名称 + * @return Shader元数据,不存在返回空元数据 + */ + ShaderMetadata getMetadata(const std::string& name) const; + + /** + * @brief 获取Shader的uniform定义 + * @param name Shader名称 + * @return uniform定义映射,不存在返回空映射 + */ + std::unordered_map getUniformDefs(const std::string& name) const; + + /** + * @brief 获取Shader的sampler定义 + * @param name Shader名称 + * @return sampler定义映射,不存在返回空映射 + */ + std::unordered_map getSamplerDefs(const std::string& name) const; + + /** + * @brief 自动应用uniform值到着色器 + * 根据JSON元数据中的uniform定义,自动设置对应的uniform值 + * @param shader 目标着色器 + * @param shaderName Shader名称(用于查找元数据) + * @param values uniform值映射表 + */ + void applyUniforms(Ptr shader, const std::string& shaderName, const UniformValueMap& values); + + /** + * @brief 自动应用sampler绑定到着色器 + * 根据JSON元数据中的sampler定义,自动设置对应的纹理单元 + * @param shader 目标着色器 + * @param shaderName Shader名称(用于查找元数据) + */ + void applySamplers(Ptr shader, const std::string& shaderName); + private: ShaderManager() = default; ~ShaderManager() = default; @@ -239,11 +277,6 @@ private: const std::string& vertSource, const std::string& fragSource); - /** - * @brief 创建内置Shader源码 - */ - void createBuiltinShaderSources(); - /** * @brief 处理文件变化事件 * @param shaderName Shader名称 diff --git a/Extra2D/shaders/shared/builtin/shape.json b/Extra2D/shaders/shared/builtin/shape.json index 74ae28e..e5ba694 100644 --- a/Extra2D/shaders/shared/builtin/shape.json +++ b/Extra2D/shaders/shared/builtin/shape.json @@ -4,7 +4,28 @@ "version": "1.0", "description": "基本形状渲染Shader", "uniforms": { - "u_viewProjection": { "type": "mat4", "description": "视图投影矩阵" } + "u_viewProjection": { + "type": "mat4", + "default": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "description": "视图投影矩阵" + } }, "samplers": {}, "backends": { diff --git a/Extra2D/shaders/shared/builtin/sprite.json b/Extra2D/shaders/shared/builtin/sprite.json index 4cc2616..61bc06c 100644 --- a/Extra2D/shaders/shared/builtin/sprite.json +++ b/Extra2D/shaders/shared/builtin/sprite.json @@ -4,12 +4,61 @@ "version": "1.0", "description": "标准2D精灵渲染Shader", "uniforms": { - "u_viewProjection": { "type": "mat4", "description": "视图投影矩阵" }, - "u_model": { "type": "mat4", "description": "模型矩阵" }, - "u_opacity": { "type": "float", "default": 1.0, "description": "透明度" } + "u_viewProjection": { + "type": "mat4", + "default": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "description": "视图投影矩阵" + }, + "u_model": { + "type": "mat4", + "default": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "description": "模型矩阵" + }, + "u_opacity": { + "type": "float", + "default": 1.0, + "description": "透明度" + } }, "samplers": { - "u_texture": { "binding": 0, "description": "纹理采样器" } + "u_texture": { + "binding": 0, + "description": "纹理采样器" + } }, "backends": { "opengl": { diff --git a/Extra2D/src/core/registry.cpp b/Extra2D/src/core/registry.cpp index 474d9ae..c3b5c98 100644 --- a/Extra2D/src/core/registry.cpp +++ b/Extra2D/src/core/registry.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace extra2d { @@ -10,19 +11,79 @@ Registry &Registry::instance() { } bool Registry::init() { - auto sorted = topologicalSort(); - E2D_REGISTRY("Initializing {} modules...", sorted.size()); + auto levels = groupByLevel(); + E2D_REGISTRY("正在初始化 {} 个模块,共 {} 个层级...", modules_.size(), + levels.size()); - for (auto *module : sorted) { - E2D_REGISTRY("Initializing module: {}", module->name()); - if (!module->init()) { - E2D_ERROR("Failed to initialize module: {}", module->name()); - return false; + for (size_t level = 0; level < levels.size(); ++level) { + auto &modules = levels[level]; + + // 检查当前层级是否有支持并行初始化的模块 + bool hasParallelModules = false; + for (auto *module : modules) { + if (module->allowParallelInit()) { + hasParallelModules = true; + break; + } } - E2D_REGISTRY("Module {} initialized successfully", module->name()); + + // 如果只有一个模块或不支持并行,使用串行初始化 + if (modules.size() <= 1 || !hasParallelModules) { + for (auto *module : modules) { + E2D_REGISTRY("正在初始化模块: {} (层级 {})", module->name(), level); + + if (!module->init()) { + E2D_ERROR("初始化模块失败: {}", module->name()); + return false; + } + + E2D_REGISTRY("模块 {} 初始化成功", module->name()); + } + } else { + // 并行初始化当前层级的模块 + E2D_REGISTRY("正在并行初始化 {} 个模块 (层级 {})...", modules.size(), + level); + + std::vector>> futures; + std::vector serialModules; + + // 分离支持并行和不支持并行的模块 + for (auto *module : modules) { + if (module->allowParallelInit()) { + futures.push_back(std::async(std::launch::async, [module]() { + return std::make_pair(module, module->init()); + })); + } else { + serialModules.push_back(module); + } + } + + // 等待并行模块完成 + for (auto &future : futures) { + auto [module, success] = future.get(); + if (!success) { + E2D_ERROR("初始化模块失败: {}", module->name()); + return false; + } + E2D_REGISTRY("模块 {} 初始化成功 (并行)", module->name()); + } + + // 串行初始化不支持并行的模块 + for (auto *module : serialModules) { + E2D_REGISTRY("正在初始化模块: {} (串行, 层级 {})", module->name(), + level); + if (!module->init()) { + E2D_ERROR("初始化模块失败: {}", module->name()); + return false; + } + E2D_REGISTRY("模块 {} 初始化成功", module->name()); + } + } + + E2D_REGISTRY("层级 {} 初始化完成", level); } - E2D_REGISTRY("All modules initialized"); + E2D_REGISTRY("所有模块初始化完成"); return true; } @@ -83,4 +144,63 @@ std::vector Registry::topologicalSort() { return result; } +std::vector> Registry::groupByLevel() { + std::vector> levels; + std::unordered_map inDegree; + std::unordered_map> adj; + std::unordered_map levelMap; + + // 初始化入度 + for (auto &[typeIdx, module] : modules_) { + inDegree[module.get()] = 0; + } + + // 构建依赖图 + for (auto &[typeIdx, module] : modules_) { + for (auto &depType : module->deps()) { + Module *dep = get(depType); + if (dep) { + adj[dep].push_back(module.get()); + inDegree[module.get()]++; + } + } + } + + // 使用 BFS 按层级分组 + std::queue q; + + // 找到所有入度为 0 的模块(第一层) + for (auto &[mod, degree] : inDegree) { + if (degree == 0) { + q.push(mod); + levelMap[mod] = 0; + } + } + + // BFS 遍历 + while (!q.empty()) { + Module *curr = q.front(); + q.pop(); + + int currLevel = levelMap[curr]; + + // 确保当前层级存在 + if (levels.size() <= static_cast(currLevel)) { + levels.resize(currLevel + 1); + } + levels[currLevel].push_back(curr); + + // 处理依赖当前模块的其他模块 + for (Module *next : adj[curr]) { + inDegree[next]--; + if (inDegree[next] == 0) { + q.push(next); + levelMap[next] = currLevel + 1; + } + } + } + + return levels; +} + } // namespace extra2d diff --git a/Extra2D/src/graphics/backends/backend_factory.cpp b/Extra2D/src/graphics/backends/backend_factory.cpp index e60613d..1b22365 100644 --- a/Extra2D/src/graphics/backends/backend_factory.cpp +++ b/Extra2D/src/graphics/backends/backend_factory.cpp @@ -14,7 +14,7 @@ BackendFactory::registry() { void BackendFactory::reg(const std::string &name, BackendFn backend, const std::vector &windowBackends) { registry()[name] = {backend, windowBackends}; - E2D_LOG_DEBUG("Registered graphics backend: {} (window backends: {})", name, + E2D_LOG_DEBUG("已注册图形后端: {} (窗口后端数量: {})", name, windowBackends.size()); } @@ -23,17 +23,17 @@ BackendFactory::createBackend(const std::string &name) { auto ® = registry(); auto it = reg.find(name); if (it != reg.end() && it->second.createFn) { - E2D_LOG_INFO("Creating graphics backend: {}", name); + E2D_LOG_INFO("正在创建图形后端: {}", name); return it->second.createFn(); } - E2D_LOG_ERROR("Graphics backend '{}' not found", name); + E2D_LOG_ERROR("未找到图形后端 '{}'", name); return nullptr; } UniquePtr BackendFactory::createDefaultBackend() { std::string recommended = getRecommendedBackend(); if (recommended.empty()) { - E2D_LOG_ERROR("No graphics backend available"); + E2D_LOG_ERROR("无可用的图形后端"); return nullptr; } return createBackend(recommended); @@ -43,8 +43,7 @@ UniquePtr BackendFactory::createBackendForWindow(const std::string &windowBackend) { std::string recommended = getRecommendedBackendForWindow(windowBackend); if (recommended.empty()) { - E2D_LOG_ERROR("No compatible graphics backend for window backend: {}", - windowBackend); + E2D_LOG_ERROR("未找到与窗口后端 '{}' 兼容的图形后端", windowBackend); return nullptr; } return createBackend(recommended); @@ -78,7 +77,7 @@ std::string BackendFactory::getRecommendedBackend() { return reg.begin()->first; } - E2D_LOG_WARN("No graphics backend registered"); + E2D_LOG_WARN("未注册任何图形后端"); return ""; } @@ -102,8 +101,7 @@ std::string BackendFactory::getRecommendedBackendForWindow( } } - E2D_LOG_WARN("No compatible graphics backend for window backend: {}", - windowBackend); + E2D_LOG_WARN("未找到与窗口后端 '{}' 兼容的图形后端", windowBackend); return ""; } diff --git a/Extra2D/src/graphics/backends/opengl/gl_buffer.cpp b/Extra2D/src/graphics/backends/opengl/gl_buffer.cpp index adf5260..71d3eaa 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_buffer.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_buffer.cpp @@ -29,7 +29,7 @@ bool GLBuffer::init(const BufferDesc &desc) { // 生成缓冲区 glGenBuffers(1, &bufferID_); if (bufferID_ == 0) { - E2D_LOG_ERROR("Failed to generate OpenGL buffer"); + E2D_LOG_ERROR("生成 OpenGL 缓冲区失败"); return false; } @@ -42,7 +42,7 @@ bool GLBuffer::init(const BufferDesc &desc) { // 追踪显存使用 VRAMMgr::get().allocBuffer(size_); - E2D_LOG_DEBUG("GLBuffer created: ID={}, Size={}, Type={}, Usage={}", + E2D_LOG_DEBUG("GLBuffer 已创建: ID={}, 大小={}, 类型={}, 用途={}", bufferID_, size_, static_cast(type_), static_cast(usage_)); @@ -57,7 +57,7 @@ void GLBuffer::shutdown() { // 释放显存追踪 VRAMMgr::get().freeBuffer(size_); glDeleteBuffers(1, &bufferID_); - E2D_LOG_DEBUG("GLBuffer destroyed: ID={}", bufferID_); + E2D_LOG_DEBUG("GLBuffer 已销毁: ID={}", bufferID_); bufferID_ = 0; } size_ = 0; @@ -128,7 +128,7 @@ void *GLBuffer::map() { if (mappedPtr_) { mapped_ = true; } else { - E2D_LOG_ERROR("Failed to map GLBuffer"); + E2D_LOG_ERROR("映射 GLBuffer 失败"); } return mappedPtr_; diff --git a/Extra2D/src/graphics/backends/opengl/gl_context.cpp b/Extra2D/src/graphics/backends/opengl/gl_context.cpp index cd925f9..fc7d2b3 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_context.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_context.cpp @@ -24,7 +24,7 @@ bool GLContext::init() { // 加载扩展(GLAD 已在 glad.c 中完成) if (!loadExtensions()) { - E2D_LOG_ERROR("Failed to load OpenGL extensions"); + E2D_LOG_ERROR("加载 OpenGL 扩展失败"); return false; } @@ -33,12 +33,12 @@ bool GLContext::init() { // 标记 GPU 上下文为有效 GPUContext::get().markValid(); - E2D_LOG_INFO("OpenGL Context initialized"); - E2D_LOG_INFO(" Version: {}", getVersionString()); - E2D_LOG_INFO(" Vendor: {}", getVendor()); - E2D_LOG_INFO(" Renderer: {}", getRenderer()); - E2D_LOG_INFO(" Max Texture Size: {}", getMaxTextureSize()); - E2D_LOG_INFO(" Max Texture Units: {}", getMaxTextureUnits()); + E2D_LOG_INFO("OpenGL 上下文已初始化"); + E2D_LOG_INFO(" 版本: {}", getVersionString()); + E2D_LOG_INFO(" 供应商: {}", getVendor()); + E2D_LOG_INFO(" 渲染器: {}", getRenderer()); + E2D_LOG_INFO(" 最大纹理大小: {}", getMaxTextureSize()); + E2D_LOG_INFO(" 最大纹理单元数: {}", getMaxTextureUnits()); return true; } diff --git a/Extra2D/src/graphics/backends/opengl/gl_font_atlas.cpp b/Extra2D/src/graphics/backends/opengl/gl_font_atlas.cpp index 776e8a3..fd0e89c 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_font_atlas.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_font_atlas.cpp @@ -26,7 +26,7 @@ GLFontAtlas::GLFontAtlas(const std::string &filepath, int fontSize, bool useSDF) // 加载字体文件 if (!initFont(filepath)) { - E2D_LOG_ERROR("Failed to initialize font: {}", filepath); + E2D_LOG_ERROR("初始化字体失败: {}", filepath); return; } @@ -53,7 +53,7 @@ GLFontAtlas::GLFontAtlas(const std::string &filepath, int fontSize, bool useSDF) cacheGlyph(codepoint); } - E2D_LOG_INFO("Font atlas created: {} ({}px, {}x{})", filepath, fontSize_, + E2D_LOG_INFO("字体图集已创建: {} ({}px, {}x{})", filepath, fontSize_, ATLAS_WIDTH, ATLAS_HEIGHT); } @@ -134,7 +134,7 @@ bool GLFontAtlas::initFont(const std::string &filepath) { // 读取字体文件到内存 std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (!file.is_open()) { - E2D_LOG_ERROR("Failed to open font file: {}", filepath); + E2D_LOG_ERROR("打开字体文件失败: {}", filepath); return false; } @@ -143,13 +143,13 @@ bool GLFontAtlas::initFont(const std::string &filepath) { fontData_.resize(static_cast(size)); if (!file.read(reinterpret_cast(fontData_.data()), size)) { - E2D_LOG_ERROR("Failed to read font file: {}", filepath); + E2D_LOG_ERROR("读取字体文件失败: {}", filepath); return false; } // 初始化 STB 字体 if (!stbtt_InitFont(&fontInfo_, fontData_.data(), 0)) { - E2D_LOG_ERROR("Failed to initialize STB font: {}", filepath); + E2D_LOG_ERROR("初始化 STB 字体失败: {}", filepath); return false; } @@ -224,7 +224,7 @@ void GLFontAtlas::cacheGlyph(char32_t codepoint) { stbrp_pack_rects(&packContext_, &rect, 1); if (!rect.was_packed) { - E2D_LOG_WARN("Font atlas is full, cannot cache codepoint: {}", codepoint); + E2D_LOG_WARN("字体图集已满,无法缓存字符码点: {}", codepoint); stbtt_FreeSDF(sdf, nullptr); return; } @@ -304,7 +304,7 @@ void GLFontAtlas::cacheGlyph(char32_t codepoint) { stbrp_pack_rects(&packContext_, &rect, 1); if (!rect.was_packed) { - E2D_LOG_WARN("Font atlas is full, cannot cache codepoint: {}", codepoint); + E2D_LOG_WARN("字体图集已满,无法缓存字符码点: {}", codepoint); return; } diff --git a/Extra2D/src/graphics/backends/opengl/gl_framebuffer.cpp b/Extra2D/src/graphics/backends/opengl/gl_framebuffer.cpp index 42f3719..a8cbb56 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_framebuffer.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_framebuffer.cpp @@ -33,11 +33,11 @@ bool GLFramebuffer::init(const FramebufferDesc &desc) { // 生成 FBO glGenFramebuffers(1, &fboID_); if (fboID_ == 0) { - E2D_LOG_ERROR("Failed to generate OpenGL framebuffer"); + E2D_LOG_ERROR("生成 OpenGL 帧缓冲区失败"); return false; } - E2D_LOG_DEBUG("GLFramebuffer created: ID={}, Size={}x{}, ColorAttachments={}", + E2D_LOG_DEBUG("GLFramebuffer 已创建: ID={}, 大小={}x{}, 颜色附件={}", fboID_, width_, height_, numColorAttachments_); return true; @@ -46,7 +46,7 @@ bool GLFramebuffer::init(const FramebufferDesc &desc) { void GLFramebuffer::shutdown() { if (fboID_ != 0) { glDeleteFramebuffers(1, &fboID_); - E2D_LOG_DEBUG("GLFramebuffer destroyed: ID={}", fboID_); + E2D_LOG_DEBUG("GLFramebuffer 已销毁: ID={}", fboID_); fboID_ = 0; } @@ -234,31 +234,31 @@ bool GLFramebuffer::checkStatus() { case GL_FRAMEBUFFER_COMPLETE: return true; case GL_FRAMEBUFFER_UNDEFINED: - E2D_LOG_ERROR("Framebuffer incomplete: GL_FRAMEBUFFER_UNDEFINED"); + E2D_LOG_ERROR("帧缓冲区不完整: GL_FRAMEBUFFER_UNDEFINED"); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: E2D_LOG_ERROR( - "Framebuffer incomplete: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + "帧缓冲区不完整: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: E2D_LOG_ERROR( - "Framebuffer incomplete: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); + "帧缓冲区不完整: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); break; #ifndef GL_ES_VERSION_2_0 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: E2D_LOG_ERROR( - "Framebuffer incomplete: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"); + "帧缓冲区不完整: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: E2D_LOG_ERROR( - "Framebuffer incomplete: GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"); + "帧缓冲区不完整: GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"); break; #endif case GL_FRAMEBUFFER_UNSUPPORTED: - E2D_LOG_ERROR("Framebuffer incomplete: GL_FRAMEBUFFER_UNSUPPORTED"); + E2D_LOG_ERROR("帧缓冲区不完整: GL_FRAMEBUFFER_UNSUPPORTED"); break; default: - E2D_LOG_ERROR("Framebuffer incomplete: Unknown error {}", status); + E2D_LOG_ERROR("帧缓冲区不完整: 未知错误 {}", status); break; } diff --git a/Extra2D/src/graphics/backends/opengl/gl_renderer.cpp b/Extra2D/src/graphics/backends/opengl/gl_renderer.cpp index 26a4c19..4067808 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_renderer.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_renderer.cpp @@ -51,13 +51,13 @@ bool GLRenderer::init(IWindow *window) { // 初始化 OpenGL 上下文(Switch 平台已通过 SDL2 + EGL 初始化,GLContext // 会处理兼容性) if (!GLContext::get().init()) { - E2D_LOG_ERROR("Failed to initialize OpenGL context"); + E2D_LOG_ERROR("初始化 OpenGL 上下文失败"); return false; } // 初始化精灵批渲染器 if (!spriteBatch_.init()) { - E2D_LOG_ERROR("Failed to initialize sprite batch"); + E2D_LOG_ERROR("初始化精灵批处理失败"); return false; } @@ -70,7 +70,7 @@ bool GLRenderer::init(IWindow *window) { pipelineDesc.depthTest = false; pipelineDesc.depthWrite = false; if (!pipeline_.init(pipelineDesc)) { - E2D_LOG_ERROR("Failed to initialize GLPipeline"); + E2D_LOG_ERROR("初始化 GLPipeline 失败"); return false; } @@ -80,8 +80,8 @@ bool GLRenderer::init(IWindow *window) { // 标记 GPU 上下文为有效 GPUContext::get().markValid(); - E2D_LOG_INFO("OpenGL Renderer initialized"); - E2D_LOG_INFO("OpenGL Version: {}", GLContext::get().getVersionString()); + E2D_LOG_INFO("OpenGL 渲染器初始化成功"); + E2D_LOG_INFO("OpenGL 版本: {}", GLContext::get().getVersionString()); return true; } @@ -756,9 +756,9 @@ void GLRenderer::initShapeRendering() { // 从ShaderManager获取形状着色器 shapeShader_ = ShaderManager::getInstance().getBuiltin("shape"); if (!shapeShader_) { - E2D_LOG_WARN("Failed to get builtin shape shader, loading from manager"); + E2D_LOG_WARN("获取内置形状着色器失败,尝试从管理器加载"); if (!ShaderManager::getInstance().isInitialized()) { - E2D_LOG_ERROR("ShaderManager not initialized, shape rendering may fail"); + E2D_LOG_ERROR("ShaderManager 未初始化,形状渲染可能失败"); } } @@ -768,7 +768,7 @@ void GLRenderer::initShapeRendering() { shapeBufferDesc.usage = BufferUsage::Dynamic; shapeBufferDesc.size = MAX_SHAPE_VERTICES * sizeof(ShapeVertex); if (!shapeBuffer_.init(shapeBufferDesc)) { - E2D_LOG_ERROR("Failed to initialize shape buffer"); + E2D_LOG_ERROR("初始化形状缓冲区失败"); } // 创建形状 VAO(手动管理,用于顶点属性配置) @@ -794,7 +794,7 @@ void GLRenderer::initShapeRendering() { lineBufferDesc.usage = BufferUsage::Dynamic; lineBufferDesc.size = MAX_LINE_VERTICES * sizeof(ShapeVertex); if (!lineBuffer_.init(lineBufferDesc)) { - E2D_LOG_ERROR("Failed to initialize line buffer"); + E2D_LOG_ERROR("初始化线条缓冲区失败"); } // 创建线条 VAO(手动管理,用于顶点属性配置) @@ -889,7 +889,14 @@ void GLRenderer::flushShapeBatch() { if (shapeShader_) { shapeShader_->bind(); - shapeShader_->setMat4("u_viewProjection", viewProjection_); + + // 只提供需要动态计算的值,其他值使用JSON中定义的默认值 + UniformValueMap uniformValues; + uniformValues["u_viewProjection"] = viewProjection_; + + // 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值) + // 使用着色器自己的名称(从JSON中解析的name字段) + ShaderManager::getInstance().applyUniforms(shapeShader_, shapeShader_->getName(), uniformValues); } // 使用 GLBuffer::updateData() 更新缓冲区数据 @@ -918,7 +925,14 @@ void GLRenderer::flushLineBatch() { glLineWidth(currentLineWidth_); if (shapeShader_) { shapeShader_->bind(); - shapeShader_->setMat4("u_viewProjection", viewProjection_); + + // 只提供需要动态计算的值,其他值使用JSON中定义的默认值 + UniformValueMap uniformValues; + uniformValues["u_viewProjection"] = viewProjection_; + + // 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值) + // 使用着色器自己的名称(从JSON中解析的name字段) + ShaderManager::getInstance().applyUniforms(shapeShader_, shapeShader_->getName(), uniformValues); } // 使用 GLBuffer::updateData() 更新缓冲区数据 @@ -941,7 +955,7 @@ void GLRenderer::flushLineBatch() { Ptr GLRenderer::createFramebuffer(const FramebufferDesc &desc) { auto framebuffer = makePtr(); if (!framebuffer->init(desc)) { - E2D_LOG_ERROR("Failed to create framebuffer"); + E2D_LOG_ERROR("创建帧缓冲区失败"); return nullptr; } return framebuffer; @@ -961,12 +975,12 @@ void GLRenderer::bindFramebuffer(GLFramebuffer *framebuffer) { // 绑定默认帧缓冲(ID 为 0) glBindFramebuffer(GL_FRAMEBUFFER, 0); currentFramebuffer_ = nullptr; - E2D_LOG_TRACE("Bound default framebuffer (0)"); + E2D_LOG_TRACE("绑定默认帧缓冲区 (0)"); } else { // 绑定自定义帧缓冲 framebuffer->bind(); currentFramebuffer_ = framebuffer; - E2D_LOG_TRACE("Bound custom framebuffer (ID: {})", framebuffer->getFboID()); + E2D_LOG_TRACE("绑定自定义帧缓冲区 (ID: {})", framebuffer->getFboID()); } } diff --git a/Extra2D/src/graphics/backends/opengl/gl_shader.cpp b/Extra2D/src/graphics/backends/opengl/gl_shader.cpp index 1f927db..6ea4bfc 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_shader.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_shader.cpp @@ -136,7 +136,7 @@ bool GLShader::compileFromSource(const char *vertexSource, if (!success) { char infoLog[512]; glGetProgramInfoLog(programID_, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader program linking failed: {}", infoLog); + E2D_LOG_ERROR("着色器程序链接失败: {}", infoLog); glDeleteProgram(programID_); programID_ = 0; } @@ -154,14 +154,14 @@ bool GLShader::compileFromSource(const char *vertexSource, */ bool GLShader::compileFromBinary(const std::vector &binary) { if (binary.empty()) { - E2D_LOG_ERROR("Binary data is empty"); + E2D_LOG_ERROR("二进制数据为空"); return false; } GLint numFormats = 0; glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numFormats); if (numFormats == 0) { - E2D_LOG_ERROR("Program binary formats not supported"); + E2D_LOG_ERROR("不支持程序二进制格式"); return false; } @@ -184,7 +184,7 @@ bool GLShader::compileFromBinary(const std::vector &binary) { if (!success) { char infoLog[512]; glGetProgramInfoLog(programID_, 512, nullptr, infoLog); - E2D_LOG_ERROR("Failed to load shader from binary: {}", infoLog); + E2D_LOG_ERROR("从二进制加载着色器失败: {}", infoLog); glDeleteProgram(programID_); programID_ = 0; return false; @@ -200,17 +200,17 @@ bool GLShader::compileFromBinary(const std::vector &binary) { */ bool GLShader::getBinary(std::vector &outBinary) { if (programID_ == 0) { - E2D_LOG_WARN("Cannot get binary: shader program is 0"); + E2D_LOG_WARN("无法获取二进制数据: 着色器程序为 0"); return false; } GLint binaryLength = 0; glGetProgramiv(programID_, GL_PROGRAM_BINARY_LENGTH, &binaryLength); - E2D_LOG_DEBUG("Shader binary length: {}", binaryLength); + E2D_LOG_DEBUG("着色器二进制数据长度: {}", binaryLength); if (binaryLength <= 0) { - E2D_LOG_WARN("Shader binary length is 0 or negative"); + E2D_LOG_WARN("着色器二进制数据长度为 0 或负数"); return false; } @@ -223,13 +223,13 @@ bool GLShader::getBinary(std::vector &outBinary) { GLenum err = glGetError(); if (err != GL_NO_ERROR) { - E2D_LOG_ERROR("glGetProgramBinary failed with error: {}", err); + E2D_LOG_ERROR("glGetProgramBinary 失败,错误码: {}", err); outBinary.clear(); return false; } if (actualLength == 0) { - E2D_LOG_WARN("glGetProgramBinary returned 0 bytes"); + E2D_LOG_WARN("glGetProgramBinary 返回 0 字节"); outBinary.clear(); return false; } @@ -238,7 +238,7 @@ bool GLShader::getBinary(std::vector &outBinary) { outBinary.resize(actualLength); } - E2D_LOG_DEBUG("Shader binary retrieved: {} bytes, format: {}", actualLength, + E2D_LOG_DEBUG("着色器二进制数据已获取: {} 字节, 格式: {}", actualLength, binaryFormat); return true; } @@ -259,7 +259,7 @@ GLuint GLShader::compileShader(GLenum type, const char *source) { if (!success) { char infoLog[512]; glGetShaderInfoLog(shader, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader compilation failed: {}", infoLog); + E2D_LOG_ERROR("着色器编译失败: {}", infoLog); glDeleteShader(shader); return 0; } @@ -302,7 +302,7 @@ Ptr GLShaderFactory::createFromSource(const std::string &name, shader->setName(name); if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) { - E2D_LOG_ERROR("Failed to compile shader from source: {}", name); + E2D_LOG_ERROR("从源码编译着色器失败: {}", name); return nullptr; } @@ -323,7 +323,7 @@ GLShaderFactory::createFromBinary(const std::string &name, shader->setName(name); if (!shader->compileFromBinary(binary)) { - E2D_LOG_ERROR("Failed to create shader from binary: {}", name); + E2D_LOG_ERROR("从二进制创建着色器失败: {}", name); return nullptr; } @@ -340,7 +340,7 @@ bool GLShaderFactory::getShaderBinary(const IShader &shader, std::vector &outBinary) { const GLShader *glShader = dynamic_cast(&shader); if (!glShader) { - E2D_LOG_ERROR("Shader is not a GLShader instance"); + E2D_LOG_ERROR("着色器不是 GLShader 实例"); return false; } diff --git a/Extra2D/src/graphics/backends/opengl/gl_sprite_batch.cpp b/Extra2D/src/graphics/backends/opengl/gl_sprite_batch.cpp index 43134b5..6226326 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_sprite_batch.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_sprite_batch.cpp @@ -4,7 +4,6 @@ #include #include - namespace extra2d { GLSpriteBatch::GLSpriteBatch() @@ -16,7 +15,7 @@ bool GLSpriteBatch::init() { // 从ShaderManager获取精灵着色器 shader_ = ShaderManager::getInstance().getBuiltin("sprite"); if (!shader_) { - E2D_LOG_ERROR("Failed to get builtin sprite shader"); + E2D_LOG_ERROR("获取内置精灵着色器失败"); return false; } @@ -31,7 +30,7 @@ bool GLSpriteBatch::init() { vboDesc.size = SpriteBatch::MAX_VERTICES * sizeof(SpriteVertex); vboDesc.initialData = nullptr; if (!vbo_.init(vboDesc)) { - E2D_LOG_ERROR("Failed to initialize sprite batch VBO"); + E2D_LOG_ERROR("初始化精灵批处理 VBO 失败"); return false; } vbo_.bind(); @@ -59,7 +58,7 @@ bool GLSpriteBatch::init() { eboDesc.size = batch_.getIndices().size() * sizeof(uint16_t); eboDesc.initialData = batch_.getIndices().data(); if (!ebo_.init(eboDesc)) { - E2D_LOG_ERROR("Failed to initialize sprite batch EBO"); + E2D_LOG_ERROR("初始化精灵批处理 EBO 失败"); return false; } ebo_.bind(); @@ -108,7 +107,7 @@ void GLSpriteBatch::end() { void GLSpriteBatch::draw(const Texture &texture, const SpriteData &data) { const GLTexture *glTex = dynamic_cast(&texture); if (!glTex) { - E2D_LOG_WARN("Invalid texture type for sprite batch"); + E2D_LOG_WARN("精灵批处理纹理类型无效"); return; } @@ -128,7 +127,7 @@ void GLSpriteBatch::drawBatch(const Texture &texture, const std::vector &sprites) { const GLTexture *glTex = dynamic_cast(&texture); if (!glTex) { - E2D_LOG_WARN("Invalid texture type for sprite batch"); + E2D_LOG_WARN("精灵批处理纹理类型无效"); return; } @@ -162,15 +161,18 @@ void GLSpriteBatch::submitBatch() { // 绑定着色器并设置uniform if (shader_) { shader_->bind(); - // 设置视图投影矩阵 - shader_->setMat4("u_viewProjection", viewProjection_); - // 设置模型矩阵为单位矩阵(精灵位置已经在顶点生成时计算) - glm::mat4 model(1.0f); - shader_->setMat4("u_model", model); + + // 只提供需要动态计算的值,其他值使用JSON中定义的默认值 + UniformValueMap uniformValues; + uniformValues["u_viewProjection"] = viewProjection_; + + // 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值) + // 使用着色器自己的名称(从JSON中解析的name字段) + ShaderManager::getInstance().applyUniforms(shader_, shader_->getName(), + uniformValues); + // 设置纹理采样器 shader_->setInt("u_texture", 0); - // 设置透明度 - shader_->setFloat("u_opacity", 1.0f); } // 上传顶点数据 - 使用 orphaning 策略优化动态缓冲区 diff --git a/Extra2D/src/graphics/backends/opengl/gl_texture.cpp b/Extra2D/src/graphics/backends/opengl/gl_texture.cpp index 308ccd3..722b793 100644 --- a/Extra2D/src/graphics/backends/opengl/gl_texture.cpp +++ b/Extra2D/src/graphics/backends/opengl/gl_texture.cpp @@ -146,7 +146,7 @@ GLTexture::GLTexture(const std::string &filepath) createTexture(data); stbi_image_free(data); } else { - E2D_LOG_ERROR("Failed to load texture: {}", filepath); + E2D_LOG_ERROR("加载纹理失败: {}", filepath); } } @@ -251,7 +251,7 @@ bool GLTexture::loadCompressed(const std::string &filepath) { if (ext == "dds" || ext == "DDS") { return loadDDS(filepath); } - E2D_LOG_ERROR("Unsupported compressed texture format: {}", filepath); + E2D_LOG_ERROR("不支持的压缩纹理格式: {}", filepath); return false; } @@ -263,20 +263,20 @@ bool GLTexture::loadCompressed(const std::string &filepath) { bool GLTexture::loadKTX(const std::string &filepath) { std::ifstream file(filepath, std::ios::binary); if (!file.is_open()) { - E2D_LOG_ERROR("Failed to open KTX file: {}", filepath); + E2D_LOG_ERROR("打开 KTX 文件失败: {}", filepath); return false; } KTXHeader header; file.read(reinterpret_cast(&header), sizeof(header)); if (!file) { - E2D_LOG_ERROR("Failed to read KTX header: {}", filepath); + E2D_LOG_ERROR("读取 KTX 文件头失败: {}", filepath); return false; } // 验证标识符 if (std::memcmp(header.identifier, KTX_IDENTIFIER, 12) != 0) { - E2D_LOG_ERROR("Invalid KTX identifier: {}", filepath); + E2D_LOG_ERROR("无效的 KTX 标识符: {}", filepath); return false; } @@ -304,7 +304,7 @@ bool GLTexture::loadKTX(const std::string &filepath) { format_ = PixelFormat::ASTC_8x8; break; default: - E2D_LOG_ERROR("Unsupported KTX internal format: {:#06x}", glInternalFormat); + E2D_LOG_ERROR("不支持的 KTX 内部格式: {:#06x}", glInternalFormat); return false; } @@ -315,14 +315,14 @@ bool GLTexture::loadKTX(const std::string &filepath) { uint32_t imageSize = 0; file.read(reinterpret_cast(&imageSize), sizeof(imageSize)); if (!file || imageSize == 0) { - E2D_LOG_ERROR("Failed to read KTX image size: {}", filepath); + E2D_LOG_ERROR("读取 KTX 图像大小失败: {}", filepath); return false; } std::vector compressedData(imageSize); file.read(reinterpret_cast(compressedData.data()), imageSize); if (!file) { - E2D_LOG_ERROR("Failed to read KTX image data: {}", filepath); + E2D_LOG_ERROR("读取 KTX 图像数据失败: {}", filepath); return false; } @@ -336,7 +336,7 @@ bool GLTexture::loadKTX(const std::string &filepath) { GLenum err = glGetError(); if (err != GL_NO_ERROR) { - E2D_LOG_ERROR("glCompressedTexImage2D failed for KTX: {:#06x}", err); + E2D_LOG_ERROR("KTX 纹理上传失败: {:#06x}", err); glDeleteTextures(1, &textureID_); textureID_ = 0; return false; @@ -351,7 +351,7 @@ bool GLTexture::loadKTX(const std::string &filepath) { dataSize_ = imageSize; VRAMMgr::get().allocTexture(dataSize_); - E2D_LOG_INFO("Loaded compressed KTX texture: {} ({}x{}, format={:#06x})", + E2D_LOG_INFO("已加载 KTX 压缩纹理: {} ({}x{}, 格式={:#06x})", filepath, width_, height_, glInternalFormat); return true; } @@ -364,19 +364,19 @@ bool GLTexture::loadKTX(const std::string &filepath) { bool GLTexture::loadDDS(const std::string &filepath) { std::ifstream file(filepath, std::ios::binary); if (!file.is_open()) { - E2D_LOG_ERROR("Failed to open DDS file: {}", filepath); + E2D_LOG_ERROR("打开 DDS 文件失败: {}", filepath); return false; } DDSHeader header; file.read(reinterpret_cast(&header), sizeof(header)); if (!file) { - E2D_LOG_ERROR("Failed to read DDS header: {}", filepath); + E2D_LOG_ERROR("读取 DDS 文件头失败: {}", filepath); return false; } if (header.magic != DDS_MAGIC) { - E2D_LOG_ERROR("Invalid DDS magic: {}", filepath); + E2D_LOG_ERROR("无效的 DDS 魔数: {}", filepath); return false; } @@ -392,7 +392,7 @@ bool GLTexture::loadDDS(const std::string &filepath) { DDSHeaderDXT10 dx10Header; file.read(reinterpret_cast(&dx10Header), sizeof(dx10Header)); if (!file) { - E2D_LOG_ERROR("Failed to read DDS DX10 header: {}", filepath); + E2D_LOG_ERROR("读取 DDS DX10 文件头失败: {}", filepath); return false; } @@ -408,11 +408,11 @@ bool GLTexture::loadDDS(const std::string &filepath) { format_ = PixelFormat::ETC2_RGBA8; break; default: - E2D_LOG_ERROR("Unsupported DDS DX10 format: {}", dx10Header.dxgiFormat); + E2D_LOG_ERROR("不支持的 DDS DX10 格式: {}", dx10Header.dxgiFormat); return false; } } else { - E2D_LOG_ERROR("DDS file does not use DX10 extension, unsupported: {}", + E2D_LOG_ERROR("DDS 文件未使用 DX10 扩展,不支持: {}", filepath); return false; } @@ -426,7 +426,7 @@ bool GLTexture::loadDDS(const std::string &filepath) { std::vector compressedData(imageSize); file.read(reinterpret_cast(compressedData.data()), imageSize); if (!file) { - E2D_LOG_ERROR("Failed to read DDS image data: {}", filepath); + E2D_LOG_ERROR("读取 DDS 图像数据失败: {}", filepath); return false; } @@ -440,7 +440,7 @@ bool GLTexture::loadDDS(const std::string &filepath) { GLenum err = glGetError(); if (err != GL_NO_ERROR) { - E2D_LOG_ERROR("glCompressedTexImage2D failed for DDS: {:#06x}", err); + E2D_LOG_ERROR("DDS 纹理上传失败: {:#06x}", err); glDeleteTextures(1, &textureID_); textureID_ = 0; return false; @@ -455,21 +455,21 @@ bool GLTexture::loadDDS(const std::string &filepath) { dataSize_ = imageSize; VRAMMgr::get().allocTexture(dataSize_); - E2D_LOG_INFO("Loaded compressed DDS texture: {} ({}x{})", filepath, width_, + E2D_LOG_INFO("已加载 DDS 压缩纹理: {} ({}x{})", filepath, width_, height_); return true; } void GLTexture::generateAlphaMask() { if (pixelData_.empty() || width_ <= 0 || height_ <= 0) { - E2D_LOG_WARN("Cannot generate alpha mask: no pixel data available"); + E2D_LOG_WARN("无法生成透明遮罩: 没有可用的像素数据"); return; } alphaMask_ = std::make_unique(AlphaMask::createFromPixels( pixelData_.data(), width_, height_, channels_)); - E2D_LOG_DEBUG("Generated alpha mask for texture: {}x{}", width_, height_); + E2D_LOG_DEBUG("已为纹理生成透明遮罩: {}x{}", width_, height_); } PixelFormat GLTexture::getFormat() const { return format_; } diff --git a/Extra2D/src/graphics/backends/vulkan/vk_renderer.cpp b/Extra2D/src/graphics/backends/vulkan/vk_renderer.cpp index 39c090a..8e7e200 100644 --- a/Extra2D/src/graphics/backends/vulkan/vk_renderer.cpp +++ b/Extra2D/src/graphics/backends/vulkan/vk_renderer.cpp @@ -10,7 +10,7 @@ VulkanRenderer::VulkanRenderer() = default; VulkanRenderer::~VulkanRenderer() { shutdown(); } bool VulkanRenderer::init(IWindow *window) { - E2D_LOG_WARN("Vulkan renderer is not fully implemented yet"); + E2D_LOG_WARN("Vulkan 渲染器尚未完全实现"); initialized_ = true; return true; } diff --git a/Extra2D/src/graphics/core/render_module.cpp b/Extra2D/src/graphics/core/render_module.cpp index c75b6e0..e5b4177 100644 --- a/Extra2D/src/graphics/core/render_module.cpp +++ b/Extra2D/src/graphics/core/render_module.cpp @@ -7,7 +7,6 @@ #include #include #include -#include namespace extra2d { @@ -31,22 +30,13 @@ RenderModule::~RenderModule() { } } -static std::string getExecutableDir() { - try { - auto currentPath = std::filesystem::current_path(); - return currentPath.string() + "/"; - } catch (...) { - return "./"; - } -} - bool RenderModule::init() { if (initialized_) return true; auto *winMod = Registry::instance().get(); if (!winMod || !winMod->win()) { - E2D_LOG_ERROR("WindowModule not available"); + E2D_LOG_ERROR("窗口模块不可用"); return false; } @@ -58,44 +48,39 @@ bool RenderModule::init() { graphics::initVulkanBackend(); #endif + // 使用ShaderManager的默认路径初始化 if (!ShaderManager::getInstance().isInitialized()) { auto factory = makeShared(); - std::string shaderDir = getExecutableDir() + "shaders/"; - std::string cacheDir = getExecutableDir() + "shader_cache/"; - if (!ShaderManager::getInstance().init(shaderDir, cacheDir, factory)) { - E2D_LOG_WARN("Failed to initialize ShaderManager with dir: {}", - shaderDir); + if (!ShaderManager::getInstance().init(factory)) { + E2D_LOG_WARN("使用默认路径初始化 ShaderManager 失败"); } } std::string windowBackend = winMod->getWindowBackend(); if (cfg_.backend.empty()) { - E2D_LOG_INFO( - "No graphics backend specified, auto-selecting for window backend: {}", - windowBackend); + E2D_LOG_INFO("未指定图形后端,正在为窗口后端自动选择:{}", windowBackend); renderer_ = graphics::BackendFactory::createBackendForWindow(windowBackend); } else { if (!graphics::BackendFactory::isCompatible(cfg_.backend, windowBackend)) { - E2D_LOG_WARN( - "Graphics backend '{}' is not compatible with window backend '{}'", - cfg_.backend, windowBackend); + E2D_LOG_WARN("图形后端 '{}' 与窗口后端 '{}' 不兼容", cfg_.backend, + windowBackend); } renderer_ = graphics::BackendFactory::createBackend(cfg_.backend); } if (!renderer_) { - E2D_LOG_ERROR("Failed to create render backend"); + E2D_LOG_ERROR("创建渲染后端失败"); return false; } if (!renderer_->init(winMod->win())) { - E2D_LOG_ERROR("Failed to initialize render backend"); + E2D_LOG_ERROR("初始化渲染后端失败"); renderer_.reset(); return false; } - E2D_LOG_INFO("Render module initialized successfully"); + E2D_LOG_INFO("渲染模块初始化成功"); initialized_ = true; return true; } diff --git a/Extra2D/src/graphics/memory/vram_manager.cpp b/Extra2D/src/graphics/memory/vram_manager.cpp index f4f7c11..768ae52 100644 --- a/Extra2D/src/graphics/memory/vram_manager.cpp +++ b/Extra2D/src/graphics/memory/vram_manager.cpp @@ -43,7 +43,7 @@ void VRAMMgr::allocTexture(size_t size) { peakTextureVRAM_ = std::max(peakTextureVRAM_, textureVRAM_); if (isOverBudget()) { - E2D_LOG_WARN("VRAM over budget! Used: {} MB / Budget: {} MB", + E2D_LOG_WARN("显存超出预算! 已使用: {} MB / 预算: {} MB", getUsedVRAM() / (1024 * 1024), vramBudget_ / (1024 * 1024)); } } @@ -77,7 +77,7 @@ void VRAMMgr::allocBuffer(size_t size) { peakBufferVRAM_ = std::max(peakBufferVRAM_, bufferVRAM_); if (isOverBudget()) { - E2D_LOG_WARN("VRAM over budget! Used: {} MB / Budget: {} MB", + E2D_LOG_WARN("显存超出预算! 已使用: {} MB / 预算: {} MB", getUsedVRAM() / (1024 * 1024), vramBudget_ / (1024 * 1024)); } } @@ -138,7 +138,7 @@ size_t VRAMMgr::getAvailableVRAM() const { void VRAMMgr::setVRAMBudget(size_t budget) { std::lock_guard lock(mutex_); vramBudget_ = budget; - E2D_LOG_INFO("VRAM budget set to {} MB", budget / (1024 * 1024)); + E2D_LOG_INFO("显存预算设置为 {} MB", budget / (1024 * 1024)); } /** @@ -160,17 +160,17 @@ bool VRAMMgr::isOverBudget() const { return getUsedVRAM() > vramBudget_; } */ void VRAMMgr::printStats() const { std::lock_guard lock(mutex_); - E2D_LOG_INFO("=== VRAM Stats ==="); - E2D_LOG_INFO(" Texture VRAM: {} MB (peak: {} MB)", + E2D_LOG_INFO("=== 显存统计 ==="); + E2D_LOG_INFO(" 纹理显存: {} MB (峰值: {} MB)", textureVRAM_ / (1024 * 1024), peakTextureVRAM_ / (1024 * 1024)); - E2D_LOG_INFO(" Buffer VRAM: {} MB (peak: {} MB)", + E2D_LOG_INFO(" 缓冲显存: {} MB (峰值: {} MB)", bufferVRAM_ / (1024 * 1024), peakBufferVRAM_ / (1024 * 1024)); - E2D_LOG_INFO(" Total Used: {} MB / {} MB budget", + E2D_LOG_INFO(" 总计使用: {} MB / {} MB 预算", (textureVRAM_ + bufferVRAM_) / (1024 * 1024), vramBudget_ / (1024 * 1024)); - E2D_LOG_INFO(" Texture allocs/frees: {} / {}", textureAllocCount_, + E2D_LOG_INFO(" 纹理分配/释放次数: {} / {}", textureAllocCount_, textureFreeCount_); - E2D_LOG_INFO(" Buffer allocs/frees: {} / {}", bufferAllocCount_, + E2D_LOG_INFO(" 缓冲分配/释放次数: {} / {}", bufferAllocCount_, bufferFreeCount_); } diff --git a/Extra2D/src/graphics/shader/shader_cache.cpp b/Extra2D/src/graphics/shader/shader_cache.cpp index 498a384..f63e421 100644 --- a/Extra2D/src/graphics/shader/shader_cache.cpp +++ b/Extra2D/src/graphics/shader/shader_cache.cpp @@ -29,16 +29,16 @@ bool ShaderCache::init(const std::string &cacheDir) { cacheDir_ = cacheDir; if (!ensureCacheDirectory()) { - E2D_LOG_ERROR("Failed to create cache directory: {}", cacheDir); + E2D_LOG_ERROR("创建缓存目录失败: {}", cacheDir); return false; } if (!loadCacheIndex()) { - E2D_LOG_WARN("Failed to load cache index, starting fresh"); + E2D_LOG_WARN("加载缓存索引失败,重新开始"); } initialized_ = true; - E2D_LOG_INFO("Shader cache initialized at: {}", cacheDir); + E2D_LOG_INFO("着色器缓存已初始化,位置: {}", cacheDir); return true; } @@ -53,7 +53,7 @@ void ShaderCache::shutdown() { saveCacheIndex(); cacheMap_.clear(); initialized_ = false; - E2D_LOG_INFO("Shader cache shutdown"); + E2D_LOG_INFO("着色器缓存已关闭"); } /** @@ -86,7 +86,7 @@ Ptr ShaderCache::loadCache(const std::string &name) { std::string cachePath = getCachePath(name); std::ifstream file(cachePath, std::ios::binary); if (!file.is_open()) { - E2D_LOG_WARN("Failed to open cache file: {}", cachePath); + E2D_LOG_WARN("打开缓存文件失败: {}", cachePath); return nullptr; } @@ -110,23 +110,23 @@ Ptr ShaderCache::loadCache(const std::string &name) { */ bool ShaderCache::saveCache(const ShaderCacheEntry &entry) { if (!initialized_) { - E2D_LOG_WARN("ShaderCache not initialized, cannot save cache"); + E2D_LOG_WARN("着色器缓存未初始化,无法保存缓存"); return false; } if (entry.binary.empty()) { - E2D_LOG_WARN("Shader binary is empty, skipping cache save for: {}", + E2D_LOG_WARN("着色器二进制数据为空,跳过缓存保存: {}", entry.name); return false; } std::string cachePath = getCachePath(entry.name); - E2D_LOG_DEBUG("Saving shader cache to: {} ({} bytes)", cachePath, + E2D_LOG_DEBUG("正在保存着色器缓存到: {} ({} 字节)", cachePath, entry.binary.size()); std::ofstream file(cachePath, std::ios::binary); if (!file.is_open()) { - E2D_LOG_ERROR("Failed to create cache file: {}", cachePath); + E2D_LOG_ERROR("创建缓存文件失败: {}", cachePath); return false; } @@ -137,7 +137,7 @@ bool ShaderCache::saveCache(const ShaderCacheEntry &entry) { cacheMap_[entry.name] = entry; saveCacheIndex(); - E2D_LOG_INFO("Shader cache saved: {} ({} bytes)", entry.name, + E2D_LOG_INFO("着色器缓存已保存: {} ({} 字节)", entry.name, entry.binary.size()); return true; } @@ -158,7 +158,7 @@ void ShaderCache::invalidate(const std::string &name) { cacheMap_.erase(it); saveCacheIndex(); - E2D_LOG_DEBUG("Shader cache invalidated: {}", name); + E2D_LOG_DEBUG("着色器缓存已失效: {}", name); } /** @@ -173,7 +173,7 @@ void ShaderCache::clearAll() { cacheMap_.clear(); saveCacheIndex(); - E2D_LOG_INFO("All shader caches cleared"); + E2D_LOG_INFO("所有着色器缓存已清除"); } /** diff --git a/Extra2D/src/graphics/shader/shader_hot_reloader.cpp b/Extra2D/src/graphics/shader/shader_hot_reloader.cpp index ad00f05..f400ebd 100644 --- a/Extra2D/src/graphics/shader/shader_hot_reloader.cpp +++ b/Extra2D/src/graphics/shader/shader_hot_reloader.cpp @@ -32,7 +32,7 @@ bool ShaderHotReloader::init() { #endif initialized_ = true; - E2D_LOG_INFO("Shader hot reloader initialized"); + E2D_LOG_INFO("着色器热重载器已初始化"); return true; } @@ -54,7 +54,7 @@ void ShaderHotReloader::shutdown() { watchMap_.clear(); initialized_ = false; enabled_ = false; - E2D_LOG_INFO("Shader hot reloader shutdown"); + E2D_LOG_INFO("着色器热重载器已关闭"); } /** @@ -67,7 +67,7 @@ void ShaderHotReloader::watch(const std::string &shaderName, const std::vector &filePaths, FileChangeCallback callback) { if (!initialized_) { - E2D_LOG_WARN("Hot reloader not initialized"); + E2D_LOG_WARN("热重载器未初始化"); return; } @@ -80,7 +80,7 @@ void ShaderHotReloader::watch(const std::string &shaderName, } watchMap_[shaderName] = std::move(info); - E2D_LOG_DEBUG("Watching shader: {} ({} files)", shaderName, filePaths.size()); + E2D_LOG_DEBUG("正在监视着色器: {} ({} 个文件)", shaderName, filePaths.size()); } /** @@ -91,7 +91,7 @@ void ShaderHotReloader::unwatch(const std::string &shaderName) { auto it = watchMap_.find(shaderName); if (it != watchMap_.end()) { watchMap_.erase(it); - E2D_LOG_DEBUG("Stopped watching shader: {}", shaderName); + E2D_LOG_DEBUG("停止监视着色器: {}", shaderName); } } @@ -112,7 +112,7 @@ void ShaderHotReloader::update() { */ void ShaderHotReloader::setEnabled(bool enabled) { enabled_ = enabled; - E2D_LOG_DEBUG("Hot reload {}", enabled ? "enabled" : "disabled"); + E2D_LOG_DEBUG("热重载已{}", enabled ? "启用" : "禁用"); } /** @@ -138,7 +138,7 @@ void ShaderHotReloader::pollChanges() { event.type = FileChangeEvent::Type::Modified; event.timestamp = now; - E2D_LOG_DEBUG("Shader file changed: {}", filePath); + E2D_LOG_DEBUG("着色器文件已更改: {}", filePath); if (info.callback) { info.callback(event); diff --git a/Extra2D/src/graphics/shader/shader_loader.cpp b/Extra2D/src/graphics/shader/shader_loader.cpp index 62ebac1..21ffcf6 100644 --- a/Extra2D/src/graphics/shader/shader_loader.cpp +++ b/Extra2D/src/graphics/shader/shader_loader.cpp @@ -173,7 +173,7 @@ ShaderLoader::processIncludes(const std::string &source, result += "\n"; continue; } else { - E2D_LOG_WARN("Include file not found: {}", includeName); + E2D_LOG_WARN("未找到包含文件: {}", includeName); } } } diff --git a/Extra2D/src/graphics/shader/shader_manager.cpp b/Extra2D/src/graphics/shader/shader_manager.cpp index 8b682ee..6df36bc 100644 --- a/Extra2D/src/graphics/shader/shader_manager.cpp +++ b/Extra2D/src/graphics/shader/shader_manager.cpp @@ -2,10 +2,11 @@ #include #include - +#include #include namespace nl = nlohmann; +namespace fs = std::filesystem; namespace extra2d { @@ -28,8 +29,8 @@ ShaderManager &ShaderManager::getInstance() { bool ShaderManager::init(Ptr factory, const std::string &appName) { // 使用相对路径作为Shader目录 - std::string shaderDir = "shaders/"; - std::string cacheDir = "cache/shaders/"; + fs::path shaderDir = "shaders"; + fs::path cacheDir = "cache/shaders"; // 非Switch平台支持热重载 #ifndef __SWITCH__ @@ -38,10 +39,10 @@ bool ShaderManager::init(Ptr factory, hotReloadSupported_ = false; #endif - E2D_LOG_INFO("ShaderManager init (HotReload: {})", + E2D_LOG_INFO("ShaderManager 初始化 (热重载: {})", hotReloadSupported_ ? "supported" : "not supported"); - return init(shaderDir, cacheDir, factory); + return init(shaderDir.string(), cacheDir.string(), factory); } /** @@ -55,12 +56,12 @@ bool ShaderManager::init(const std::string &shaderDir, const std::string &cacheDir, Ptr factory) { if (initialized_) { - E2D_LOG_WARN("ShaderManager already initialized"); + E2D_LOG_WARN("ShaderManager 已初始化"); return true; } if (!factory) { - E2D_LOG_ERROR("Shader factory is null"); + E2D_LOG_ERROR("Shader 工厂为空"); return false; } @@ -77,28 +78,28 @@ bool ShaderManager::init(const std::string &shaderDir, #ifdef __SWITCH__ if (!ShaderCache::getInstance().init(cacheDir_)) { - E2D_LOG_WARN("Failed to initialize shader cache on Switch"); + E2D_LOG_WARN("Switch 平台初始化着色器缓存失败"); } #else if (!ShaderCache::getInstance().init(cacheDir_)) { - E2D_LOG_WARN("Failed to initialize shader cache, caching disabled"); + E2D_LOG_WARN("初始化着色器缓存失败,已禁用缓存"); } #endif if (hotReloadSupported_) { if (!ShaderHotReloader::getInstance().init()) { - E2D_LOG_WARN("Failed to initialize hot reloader"); + E2D_LOG_WARN("初始化热重载器失败"); } } loader_.addIncludePath(shaderDir_ + "common"); initialized_ = true; - E2D_LOG_INFO("ShaderManager initialized"); - E2D_LOG_INFO(" Shader directory: {}", shaderDir_); - E2D_LOG_INFO(" Cache directory: {}", cacheDir_); - E2D_LOG_INFO(" Hot reload: {}", - hotReloadSupported_ ? "supported" : "not supported"); + E2D_LOG_INFO("ShaderManager 初始化成功"); + E2D_LOG_INFO(" 着色器目录: {}", shaderDir_); + E2D_LOG_INFO(" 缓存目录: {}", cacheDir_); + E2D_LOG_INFO(" 热重载: {}", + hotReloadSupported_ ? "支持" : "不支持"); return true; } @@ -120,7 +121,7 @@ void ShaderManager::shutdown() { factory_.reset(); initialized_ = false; - E2D_LOG_INFO("ShaderManager shutdown"); + E2D_LOG_INFO("ShaderManager 已关闭"); } /** @@ -134,7 +135,7 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, const std::string &vertPath, const std::string &fragPath) { if (!initialized_) { - E2D_LOG_ERROR("ShaderManager not initialized"); + E2D_LOG_ERROR("ShaderManager 未初始化"); return nullptr; } @@ -146,7 +147,7 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, ShaderLoadResult result = loader_.loadFromSeparateFiles(name, vertPath, fragPath); if (!result.success) { - E2D_LOG_ERROR("Failed to load shader files: {} - {}", vertPath, fragPath); + E2D_LOG_ERROR("加载着色器文件失败: {} - {}", vertPath, fragPath); return nullptr; } @@ -156,18 +157,18 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, loadFromCache(name, sourceHash, result.vertSource, result.fragSource); if (!shader) { - E2D_LOG_DEBUG("No valid cache found, compiling shader from source: {}", + E2D_LOG_DEBUG("未找到有效缓存,从源码编译着色器: {}", name); shader = factory_->createFromSource(name, result.vertSource, result.fragSource); if (!shader) { - E2D_LOG_ERROR("Failed to create shader from source: {}", name); + E2D_LOG_ERROR("从源码创建着色器失败: {}", name); return nullptr; } std::vector binary; if (factory_->getShaderBinary(*shader, binary)) { - E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size()); + E2D_LOG_DEBUG("获取到着色器二进制数据,大小: {} 字节", binary.size()); ShaderCacheEntry entry; entry.name = name; entry.sourceHash = sourceHash; @@ -175,7 +176,7 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, entry.dependencies = result.dependencies; ShaderCache::getInstance().saveCache(entry); } else { - E2D_LOG_WARN("Failed to get shader binary for: {}", name); + E2D_LOG_WARN("获取着色器二进制数据失败: {}", name); } } @@ -201,7 +202,7 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, callback); } - E2D_LOG_DEBUG("Shader loaded: {}", name); + E2D_LOG_DEBUG("着色器已加载: {}", name); return shader; } @@ -212,7 +213,7 @@ Ptr ShaderManager::loadFromFiles(const std::string &name, */ Ptr ShaderManager::loadFromCombinedFile(const std::string &path) { if (!initialized_) { - E2D_LOG_ERROR("ShaderManager not initialized"); + E2D_LOG_ERROR("ShaderManager 未初始化"); return nullptr; } @@ -226,7 +227,7 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string &path) { ShaderLoadResult result = loader_.loadFromCombinedFile(path); if (!result.success) { - E2D_LOG_ERROR("Failed to load combined shader file: {}", path); + E2D_LOG_ERROR("加载组合着色器文件失败: {}", path); return nullptr; } @@ -241,13 +242,13 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string &path) { shader = factory_->createFromSource(name, result.vertSource, result.fragSource); if (!shader) { - E2D_LOG_ERROR("Failed to create shader from source: {}", name); + E2D_LOG_ERROR("从源码创建着色器失败: {}", name); return nullptr; } std::vector binary; if (factory_->getShaderBinary(*shader, binary)) { - E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size()); + E2D_LOG_DEBUG("获取到着色器二进制数据,大小: {} 字节", binary.size()); ShaderCacheEntry entry; entry.name = name; entry.sourceHash = sourceHash; @@ -255,7 +256,7 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string &path) { entry.dependencies = result.dependencies; ShaderCache::getInstance().saveCache(entry); } else { - E2D_LOG_WARN("Failed to get shader binary for: {}", name); + E2D_LOG_WARN("获取着色器二进制数据失败: {}", name); } } @@ -278,7 +279,7 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string &path) { callback); } - E2D_LOG_DEBUG("Shader loaded from combined file: {}", name); + E2D_LOG_DEBUG("从组合文件加载着色器成功: {}", name); return shader; } @@ -293,7 +294,7 @@ Ptr ShaderManager::loadFromSource(const std::string &name, const std::string &vertSource, const std::string &fragSource) { if (!initialized_) { - E2D_LOG_ERROR("ShaderManager not initialized"); + E2D_LOG_ERROR("ShaderManager 未初始化"); return nullptr; } @@ -305,7 +306,7 @@ Ptr ShaderManager::loadFromSource(const std::string &name, Ptr shader = factory_->createFromSource(name, vertSource, fragSource); if (!shader) { - E2D_LOG_ERROR("Failed to create shader from source: {}", name); + E2D_LOG_ERROR("从源码创建着色器失败: {}", name); return nullptr; } @@ -317,7 +318,7 @@ Ptr ShaderManager::loadFromSource(const std::string &name, shaders_[name] = std::move(info); - E2D_LOG_DEBUG("Shader loaded from source: {}", name); + E2D_LOG_DEBUG("从源码加载着色器成功: {}", name); return shader; } @@ -352,7 +353,7 @@ void ShaderManager::remove(const std::string &name) { if (it != shaders_.end()) { ShaderHotReloader::getInstance().unwatch(name); shaders_.erase(it); - E2D_LOG_DEBUG("Shader removed: {}", name); + E2D_LOG_DEBUG("着色器已移除: {}", name); } } @@ -366,7 +367,7 @@ void ShaderManager::clear() { } } shaders_.clear(); - E2D_LOG_DEBUG("All shaders cleared"); + E2D_LOG_DEBUG("所有着色器已清除"); } /** @@ -388,12 +389,12 @@ void ShaderManager::setReloadCallback(const std::string &name, */ void ShaderManager::setHotReloadEnabled(bool enabled) { if (!hotReloadSupported_) { - E2D_LOG_WARN("Hot reload not supported on this platform"); + E2D_LOG_WARN("当前平台不支持热重载"); return; } hotReloadEnabled_ = enabled; ShaderHotReloader::getInstance().setEnabled(enabled); - E2D_LOG_INFO("Hot reload {}", enabled ? "enabled" : "disabled"); + E2D_LOG_INFO("热重载已{}", enabled ? "启用" : "禁用"); } /** @@ -421,7 +422,7 @@ void ShaderManager::update() { bool ShaderManager::reload(const std::string &name) { auto it = shaders_.find(name); if (it == shaders_.end()) { - E2D_LOG_WARN("Shader not found for reload: {}", name); + E2D_LOG_WARN("未找到要重载的着色器: {}", name); return false; } @@ -449,7 +450,7 @@ bool ShaderManager::reload(const std::string &name) { Ptr newShader = factory_->createFromSource(name, vertSource, fragSource); if (!newShader) { - E2D_LOG_ERROR("Failed to reload shader: {}", name); + E2D_LOG_ERROR("重载着色器失败: {}", name); return false; } @@ -461,7 +462,7 @@ bool ShaderManager::reload(const std::string &name) { info.reloadCallback(newShader); } - E2D_LOG_INFO("Shader reloaded: {}", name); + E2D_LOG_INFO("着色器重载成功: {}", name); return true; } @@ -476,15 +477,15 @@ Ptr ShaderManager::getBuiltin(const std::string &name) { return shader; } - // 尝试从新的多后端JSON元数据加载 - std::string jsonPath = shaderDir_ + "shared/builtin/" + name + ".json"; - if (loader_.fileExists(jsonPath)) { - return loadFromMetadata(jsonPath, name); + // 从JSON元数据文件加载内置着色器 + fs::path jsonPath = + fs::path(shaderDir_) / "shared" / "builtin" / (name + ".json"); + if (loader_.fileExists(jsonPath.string())) { + return loadFromMetadata(jsonPath.string(), name); } - // 回退到旧的组合文件格式 - std::string path = shaderDir_ + "builtin/" + name + ".shader"; - return loadFromCombinedFile(path); + E2D_LOG_ERROR("未找到内置着色器: {}", jsonPath.string()); + return nullptr; } /** @@ -496,7 +497,7 @@ Ptr ShaderManager::getBuiltin(const std::string &name) { Ptr ShaderManager::loadFromMetadata(const std::string &jsonPath, const std::string &name) { if (!initialized_) { - E2D_LOG_ERROR("ShaderManager not initialized"); + E2D_LOG_ERROR("ShaderManager 未初始化"); return nullptr; } @@ -509,7 +510,7 @@ Ptr ShaderManager::loadFromMetadata(const std::string &jsonPath, // 读取JSON文件 std::string jsonContent = loader_.readFile(jsonPath); if (jsonContent.empty()) { - E2D_LOG_ERROR("Failed to read shader metadata: {}", jsonPath); + E2D_LOG_ERROR("读取着色器元数据失败: {}", jsonPath); return nullptr; } @@ -517,15 +518,80 @@ Ptr ShaderManager::loadFromMetadata(const std::string &jsonPath, // 使用nlohmann/json解析 nl::json j = nl::json::parse(jsonContent); + // 解析基本元数据 + ShaderMetadata metadata; + metadata.name = name; + + if (j.contains("category")) { + metadata.category = j["category"].get(); + } + if (j.contains("version")) { + metadata.version = j["version"].get(); + } + if (j.contains("description")) { + metadata.description = j["description"].get(); + } + + // 解析 uniforms 详细定义 + if (j.contains("uniforms")) { + for (auto &[key, value] : j["uniforms"].items()) { + ShaderUniformDef def; + if (value.contains("type")) { + def.type = value["type"].get(); + } + if (value.contains("description")) { + def.description = value["description"].get(); + } + // 解析默认值 + if (value.contains("default")) { + def.hasDefault = true; + if (def.type == "float") { + def.defaultValue = value["default"].get(); + } else if (def.type == "int") { + def.defaultInt = value["default"].get(); + } else if (def.type == "bool") { + def.defaultBool = value["default"].get(); + } else if (def.type == "vec4" && value["default"].is_array()) { + auto arr = value["default"].get>(); + for (size_t i = 0; i < arr.size() && i < 4; ++i) { + def.defaultVec4[i] = arr[i]; + } + } else if (def.type == "mat4" && value["default"].is_array()) { + auto arr = value["default"].get>(); + for (size_t i = 0; i < arr.size() && i < 16; ++i) { + def.defaultMat4[i] = arr[i]; + } + } + } + metadata.uniformDefs[key] = def; + // 同时填充旧的uniforms映射以保持兼容性 + metadata.uniforms[key] = def.type; + } + } + + // 解析 samplers 定义 + if (j.contains("samplers")) { + for (auto &[key, value] : j["samplers"].items()) { + ShaderSamplerDef def; + if (value.contains("type")) { + def.type = value["type"].get(); + } + if (value.contains("description")) { + def.description = value["description"].get(); + } + metadata.samplerDefs[key] = def; + } + } + // 获取OpenGL后端路径 if (!j.contains("backends") || !j["backends"].contains("opengl")) { - E2D_LOG_ERROR("No OpenGL backend found in shader metadata: {}", jsonPath); + E2D_LOG_ERROR("着色器元数据中未找到 OpenGL 后端: {}", jsonPath); return nullptr; } auto &opengl = j["backends"]["opengl"]; if (!opengl.contains("vertex") || !opengl.contains("fragment")) { - E2D_LOG_ERROR("Missing vertex or fragment path in shader metadata: {}", + E2D_LOG_ERROR("着色器元数据中缺少顶点或片段路径: {}", jsonPath); return nullptr; } @@ -533,18 +599,26 @@ Ptr ShaderManager::loadFromMetadata(const std::string &jsonPath, std::string vertRelativePath = opengl["vertex"].get(); std::string fragRelativePath = opengl["fragment"].get(); - // 构建完整路径 - std::string vertPath = shaderDir_ + vertRelativePath; - std::string fragPath = shaderDir_ + fragRelativePath; + // 使用C++17文件系统构建完整路径 + fs::path vertPath = fs::path(shaderDir_) / vertRelativePath; + fs::path fragPath = fs::path(shaderDir_) / fragRelativePath; - E2D_LOG_DEBUG("Loading shader from metadata: {} -> vert: {}, frag: {}", - name, vertPath, fragPath); + E2D_LOG_DEBUG("从元数据加载着色器: {} -> 顶点: {}, 片段: {}", + name, vertPath.string(), fragPath.string()); // 使用分离文件加载 - return loadFromFiles(name, vertPath, fragPath); + Ptr shader = + loadFromFiles(name, vertPath.string(), fragPath.string()); + + // 更新着色器元数据 + if (shader && shaders_.find(name) != shaders_.end()) { + shaders_[name].metadata = metadata; + } + + return shader; } catch (const nl::json::exception &e) { - E2D_LOG_ERROR("Failed to parse shader metadata {}: {}", jsonPath, e.what()); + E2D_LOG_ERROR("解析着色器元数据 {} 失败: {}", jsonPath, e.what()); return nullptr; } } @@ -555,7 +629,7 @@ Ptr ShaderManager::loadFromMetadata(const std::string &jsonPath, */ bool ShaderManager::loadBuiltinShaders() { if (!initialized_) { - E2D_LOG_ERROR("ShaderManager not initialized"); + E2D_LOG_ERROR("ShaderManager 未初始化"); return false; } @@ -565,21 +639,17 @@ bool ShaderManager::loadBuiltinShaders() { "font"}; for (const char *name : builtinNames) { - // 首先尝试新的多后端JSON格式 - std::string jsonPath = shaderDir_ + "shared/builtin/" + name + ".json"; + fs::path jsonPath = fs::path(shaderDir_) / "shared" / "builtin" / + (std::string(name) + ".json"); std::string shaderName = std::string("builtin_") + name; Ptr shader = nullptr; - if (loader_.fileExists(jsonPath)) { - shader = loadFromMetadata(jsonPath, name); - } else { - // 回退到旧的组合文件格式 - std::string path = shaderDir_ + "builtin/" + name + ".shader"; - shader = loadFromCombinedFile(path); + if (loader_.fileExists(jsonPath.string())) { + shader = loadFromMetadata(jsonPath.string(), name); } if (!shader) { - E2D_LOG_ERROR("Failed to load builtin {} shader", name); + E2D_LOG_ERROR("加载内置 {} 着色器失败", name); allSuccess = false; } else { // 同时注册带 builtin_ 前缀的名称 @@ -591,7 +661,7 @@ bool ShaderManager::loadBuiltinShaders() { } if (allSuccess) { - E2D_LOG_INFO("All builtin shaders loaded"); + E2D_LOG_INFO("所有内置着色器加载成功"); } return allSuccess; @@ -624,7 +694,7 @@ Ptr ShaderManager::loadFromCache(const std::string &name, Ptr shader = factory_->createFromBinary(name, entry->binary); if (shader) { - E2D_LOG_DEBUG("Shader loaded from cache: {}", name); + E2D_LOG_DEBUG("从缓存加载着色器成功: {}", name); } return shader; @@ -637,8 +707,136 @@ Ptr ShaderManager::loadFromCache(const std::string &name, */ void ShaderManager::handleFileChange(const std::string &shaderName, const FileChangeEvent &event) { - E2D_LOG_DEBUG("Shader file changed: {} -> {}", shaderName, event.filepath); + E2D_LOG_DEBUG("着色器文件已更改: {} -> {}", shaderName, event.filepath); reload(shaderName); } +/** + * @brief 获取Shader元数据 + * @param name Shader名称 + * @return Shader元数据,不存在返回空元数据 + */ +ShaderMetadata ShaderManager::getMetadata(const std::string &name) const { + auto it = shaders_.find(name); + if (it != shaders_.end()) { + return it->second.metadata; + } + return ShaderMetadata{}; +} + +/** + * @brief 获取Shader的uniform定义 + * @param name Shader名称 + * @return uniform定义映射,不存在返回空映射 + */ +std::unordered_map +ShaderManager::getUniformDefs(const std::string &name) const { + auto it = shaders_.find(name); + if (it != shaders_.end()) { + return it->second.metadata.uniformDefs; + } + return {}; +} + +/** + * @brief 获取Shader的sampler定义 + * @param name Shader名称 + * @return sampler定义映射,不存在返回空映射 + */ +std::unordered_map +ShaderManager::getSamplerDefs(const std::string &name) const { + auto it = shaders_.find(name); + if (it != shaders_.end()) { + return it->second.metadata.samplerDefs; + } + return {}; +} + +/** + * @brief 自动应用uniform值到着色器 + * 根据JSON元数据中的uniform定义,自动设置对应的uniform值 + * 如果值映射表中不存在该uniform,则使用JSON中定义的默认值 + * @param shader 目标着色器 + * @param shaderName Shader名称(用于查找元数据) + * @param values uniform值映射表(可选,用于覆盖默认值) + */ +void ShaderManager::applyUniforms(Ptr shader, + const std::string &shaderName, + const UniformValueMap &values) { + if (!shader) + return; + + auto uniformDefs = getUniformDefs(shaderName); + for (const auto &[name, def] : uniformDefs) { + auto it = values.find(name); + + if (it != values.end()) { + // 使用提供的值 + const auto &value = it->second; + if (def.type == "float" && + value.type == ShaderUniformValue::Type::Float) { + shader->setFloat(name, value.data.f[0]); + } else if (def.type == "int" && + value.type == ShaderUniformValue::Type::Int) { + shader->setInt(name, value.data.i); + } else if (def.type == "bool" && + value.type == ShaderUniformValue::Type::Bool) { + shader->setBool(name, value.data.b); + } else if (def.type == "vec2" && + value.type == ShaderUniformValue::Type::Vec2) { + shader->setVec2(name, glm::vec2(value.data.f[0], value.data.f[1])); + } else if (def.type == "vec3" && + value.type == ShaderUniformValue::Type::Vec3) { + shader->setVec3( + name, glm::vec3(value.data.f[0], value.data.f[1], value.data.f[2])); + } else if (def.type == "vec4" && + value.type == ShaderUniformValue::Type::Vec4) { + shader->setVec4(name, glm::vec4(value.data.f[0], value.data.f[1], + value.data.f[2], value.data.f[3])); + } else if (def.type == "mat4" && + value.type == ShaderUniformValue::Type::Mat4) { + glm::mat4 mat; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + mat[i][j] = value.data.f[i * 4 + j]; + shader->setMat4(name, mat); + } + } else if (def.hasDefault) { + // 使用JSON中定义的默认值 + if (def.type == "float") { + shader->setFloat(name, def.defaultValue); + } else if (def.type == "int") { + shader->setInt(name, def.defaultInt); + } else if (def.type == "bool") { + shader->setBool(name, def.defaultBool); + } else if (def.type == "vec4") { + shader->setVec4(name, + glm::vec4(def.defaultVec4[0], def.defaultVec4[1], + def.defaultVec4[2], def.defaultVec4[3])); + } else if (def.type == "mat4") { + glm::mat4 mat; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + mat[i][j] = def.defaultMat4[i * 4 + j]; + shader->setMat4(name, mat); + } + } + } +} + +/** + * @brief 自动应用sampler绑定到着色器 + * 根据JSON元数据中的sampler定义,自动设置对应的纹理单元 + * @param shader 目标着色器 + * @param shaderName Shader名称(用于查找元数据) + */ +void ShaderManager::applySamplers(Ptr shader, + const std::string &shaderName) { + if (!shader) + return; + + // TODO: 从JSON中解析binding并设置 + // 目前sampler绑定在submitBatch中通过setInt设置 +} + } // namespace extra2d diff --git a/Extra2D/src/graphics/shader/shader_preset.cpp b/Extra2D/src/graphics/shader/shader_preset.cpp index e86cb3a..9f44d71 100644 --- a/Extra2D/src/graphics/shader/shader_preset.cpp +++ b/Extra2D/src/graphics/shader/shader_preset.cpp @@ -14,7 +14,7 @@ namespace extra2d { Ptr ShaderPreset::Water(const WaterParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("water"); if (!shader) { - E2D_LOG_ERROR("Failed to get water shader"); + E2D_LOG_ERROR("获取水波纹着色器失败"); return nullptr; } @@ -33,7 +33,7 @@ Ptr ShaderPreset::Water(const WaterParams ¶ms) { Ptr ShaderPreset::Outline(const OutlineParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("outline"); if (!shader) { - E2D_LOG_ERROR("Failed to get outline shader"); + E2D_LOG_ERROR("获取描边着色器失败"); return nullptr; } @@ -52,7 +52,7 @@ Ptr ShaderPreset::Outline(const OutlineParams ¶ms) { Ptr ShaderPreset::Distortion(const DistortionParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("distortion"); if (!shader) { - E2D_LOG_ERROR("Failed to get distortion shader"); + E2D_LOG_ERROR("获取扭曲效果着色器失败"); return nullptr; } @@ -70,7 +70,7 @@ Ptr ShaderPreset::Distortion(const DistortionParams ¶ms) { Ptr ShaderPreset::Pixelate(const PixelateParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("pixelate"); if (!shader) { - E2D_LOG_ERROR("Failed to get pixelate shader"); + E2D_LOG_ERROR("获取像素化着色器失败"); return nullptr; } @@ -87,7 +87,7 @@ Ptr ShaderPreset::Pixelate(const PixelateParams ¶ms) { Ptr ShaderPreset::Invert(const InvertParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("invert"); if (!shader) { - E2D_LOG_ERROR("Failed to get invert shader"); + E2D_LOG_ERROR("获取反相着色器失败"); return nullptr; } @@ -104,7 +104,7 @@ Ptr ShaderPreset::Invert(const InvertParams ¶ms) { Ptr ShaderPreset::Grayscale(const GrayscaleParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("grayscale"); if (!shader) { - E2D_LOG_ERROR("Failed to get grayscale shader"); + E2D_LOG_ERROR("获取灰度着色器失败"); return nullptr; } @@ -121,7 +121,7 @@ Ptr ShaderPreset::Grayscale(const GrayscaleParams ¶ms) { Ptr ShaderPreset::Blur(const BlurParams ¶ms) { Ptr shader = ShaderManager::getInstance().get("blur"); if (!shader) { - E2D_LOG_ERROR("Failed to get blur shader"); + E2D_LOG_ERROR("获取模糊着色器失败"); return nullptr; } @@ -140,13 +140,13 @@ Ptr ShaderPreset::GrayscaleOutline(const GrayscaleParams &grayParams, const OutlineParams &outlineParams) { std::string shaderDir = ShaderManager::getInstance().getShaderDir(); - std::string shaderPath = shaderDir + "effects/grayscale_outline.shader"; + std::string jsonPath = shaderDir + "effects/grayscale_outline.json"; Ptr shader = - ShaderManager::getInstance().loadFromCombinedFile(shaderPath); + ShaderManager::getInstance().loadFromMetadata(jsonPath, "grayscale_outline"); if (!shader) { - E2D_LOG_ERROR("Failed to load grayscale_outline shader from: {}", - shaderPath); + E2D_LOG_ERROR("从 {} 加载灰度描边组合着色器失败", + jsonPath); return nullptr; } @@ -168,12 +168,12 @@ ShaderPreset::GrayscaleOutline(const GrayscaleParams &grayParams, Ptr ShaderPreset::PixelateInvert(const PixelateParams &pixParams, const InvertParams &invParams) { std::string shaderDir = ShaderManager::getInstance().getShaderDir(); - std::string shaderPath = shaderDir + "effects/pixelate_invert.shader"; + std::string jsonPath = shaderDir + "effects/pixelate_invert.json"; Ptr shader = - ShaderManager::getInstance().loadFromCombinedFile(shaderPath); + ShaderManager::getInstance().loadFromMetadata(jsonPath, "pixelate_invert"); if (!shader) { - E2D_LOG_ERROR("Failed to load pixelate_invert shader from: {}", shaderPath); + E2D_LOG_ERROR("从 {} 加载像素化反相组合着色器失败", jsonPath); return nullptr; } diff --git a/Extra2D/src/graphics/texture/texture_atlas.cpp b/Extra2D/src/graphics/texture/texture_atlas.cpp index 5bf5cfa..677cba4 100644 --- a/Extra2D/src/graphics/texture/texture_atlas.cpp +++ b/Extra2D/src/graphics/texture/texture_atlas.cpp @@ -24,7 +24,7 @@ TextureAtlasPage::TextureAtlasPage(int width, int height) // 初始化矩形打包根节点 root_ = std::make_unique(0, 0, width, height); - E2D_LOG_INFO("Created texture atlas page: {}x{}", width, height); + E2D_LOG_INFO("已创建纹理图集页面: {}x{}", width, height); } /** @@ -92,7 +92,7 @@ bool TextureAtlasPage::tryAddTexture(const std::string &name, int texWidth, entries_[name] = std::move(entry); usedArea_ += paddedWidth * paddedHeight; - E2D_LOG_DEBUG("Added texture '{}' to atlas: {}x{} at ({}, {})", name, + E2D_LOG_DEBUG("已将纹理 '{}' 添加到图集: {}x{} 位置 ({}, {})", name, texWidth, texHeight, node->x, node->y); return true; @@ -233,7 +233,7 @@ TextureAtlas::~TextureAtlas() = default; void TextureAtlas::init(int pageSize) { pageSize_ = pageSize; initialized_ = true; - E2D_LOG_INFO("TextureAtlas initialized with page size: {}", pageSize); + E2D_LOG_INFO("纹理图集已初始化,页面大小: {}", pageSize); } /** @@ -259,7 +259,7 @@ bool TextureAtlas::addTexture(const std::string &name, int width, int height, // 检查纹理大小 if (width > sizeThreshold_ || height > sizeThreshold_) { - E2D_LOG_DEBUG("Texture '{}' too large for atlas ({}x{} > {}), skipping", + E2D_LOG_DEBUG("纹理 '{}' 太大无法加入图集 ({}x{} > {}),跳过", name, width, height, sizeThreshold_); return false; } @@ -281,7 +281,7 @@ bool TextureAtlas::addTexture(const std::string &name, int width, int height, return true; } - E2D_LOG_WARN("Failed to add texture '{}' to atlas", name); + E2D_LOG_WARN("添加纹理 '{}' 到图集失败", name); return false; } @@ -365,7 +365,7 @@ float TextureAtlas::getTotalUsageRatio() const { void TextureAtlas::clear() { pages_.clear(); entryToPage_.clear(); - E2D_LOG_INFO("TextureAtlas cleared"); + E2D_LOG_INFO("纹理图集已清空"); } // ============================================================================ diff --git a/Extra2D/src/graphics/texture/texture_pool.cpp b/Extra2D/src/graphics/texture/texture_pool.cpp index 841ad76..d56a8df 100644 --- a/Extra2D/src/graphics/texture/texture_pool.cpp +++ b/Extra2D/src/graphics/texture/texture_pool.cpp @@ -39,7 +39,7 @@ TexturePool::TexturePool(Scene* scene, size_t maxMemoryUsage) , cacheHits_(0) , cacheMisses_(0) , evictionCount_(0) { - E2D_LOG_INFO("TexturePool created with max memory: {} bytes", maxMemoryUsage); + E2D_LOG_INFO("TexturePool 已创建,最大内存: {} 字节", maxMemoryUsage); } /** @@ -52,7 +52,7 @@ TexturePool::TexturePool(Scene* scene, size_t maxMemoryUsage) void TexturePool::init(Scene* scene, size_t maxMemoryUsage) { scene_ = scene; maxMemoryUsage_ = maxMemoryUsage; - E2D_LOG_INFO("TexturePool initialized with max memory: {} bytes", maxMemoryUsage); + E2D_LOG_INFO("TexturePool 已初始化,最大内存: {} 字节", maxMemoryUsage); } /** @@ -62,7 +62,7 @@ void TexturePool::init(Scene* scene, size_t maxMemoryUsage) { */ TexturePool::~TexturePool() { clear(); - E2D_LOG_INFO("TexturePool destroyed"); + E2D_LOG_INFO("TexturePool 已销毁"); } // ============================================================================ @@ -104,7 +104,7 @@ TextureRef TexturePool::load(const std::string& path, const Rect& region, it->second.refCount.fetch_add(1, std::memory_order_relaxed); cacheHits_.fetch_add(1, std::memory_order_relaxed); - E2D_LOG_DEBUG("Texture cache hit: {}", path); + E2D_LOG_DEBUG("纹理缓存命中: {}", path); return TextureRef(it->second.texture, &it->second, &mutex_); } @@ -120,14 +120,14 @@ TextureRef TexturePool::load(const std::string& path, const Rect& region, } if (!backend) { - E2D_LOG_ERROR("TexturePool: RenderBackend not available"); + E2D_LOG_ERROR("TexturePool: 渲染后端不可用"); return TextureRef(); } // 加载纹理 Ptr texture = backend->loadTexture(path); if (!texture) { - E2D_LOG_ERROR("TexturePool: Failed to load texture: {}", path); + E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path); return TextureRef(); } @@ -141,7 +141,7 @@ TextureRef TexturePool::load(const std::string& path, const Rect& region, // 再次检查 if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) { - E2D_LOG_WARN("TexturePool: Memory limit exceeded, cannot load texture: {}", path); + E2D_LOG_WARN("TexturePool: 内存限制超出,无法加载纹理: {}", path); return TextureRef(); } } @@ -154,7 +154,7 @@ TextureRef TexturePool::load(const std::string& path, const Rect& region, result.first->second.refCount.store(1, std::memory_order_relaxed); result.first->second.touch(); currentMemoryUsage_ += memorySize; - E2D_LOG_INFO("TexturePool: Loaded texture: {} ({} bytes)", path, memorySize); + E2D_LOG_INFO("TexturePool: 已加载纹理: {} ({} 字节)", path, memorySize); return TextureRef(texture, &result.first->second, &mutex_); } @@ -196,14 +196,14 @@ TextureRef TexturePool::loadFromMemory(const uint8_t* data, int width, int heigh } if (!backend) { - E2D_LOG_ERROR("TexturePool: RenderBackend not available"); + E2D_LOG_ERROR("TexturePool: 渲染后端不可用"); return TextureRef(); } // 创建纹理 Ptr texture = backend->createTexture(width, height, data, channels); if (!texture) { - E2D_LOG_ERROR("TexturePool: Failed to create texture from memory"); + E2D_LOG_ERROR("TexturePool: 从内存创建纹理失败"); return TextureRef(); } @@ -215,7 +215,7 @@ TextureRef TexturePool::loadFromMemory(const uint8_t* data, int width, int heigh evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_); if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) { - E2D_LOG_WARN("TexturePool: Memory limit exceeded"); + E2D_LOG_WARN("TexturePool: 内存限制超出"); return TextureRef(); } } @@ -228,7 +228,7 @@ TextureRef TexturePool::loadFromMemory(const uint8_t* data, int width, int heigh result.first->second.refCount.store(1, std::memory_order_relaxed); result.first->second.touch(); currentMemoryUsage_ += memorySize; - E2D_LOG_INFO("TexturePool: Created texture from memory ({} bytes)", memorySize); + E2D_LOG_INFO("TexturePool: 已从内存创建纹理 ({} 字节)", memorySize); return TextureRef(texture, &result.first->second, &mutex_); } @@ -283,13 +283,13 @@ TextureRef TexturePool::getOrLoad(const std::string& path, const Rect& region, } if (!backend) { - E2D_LOG_ERROR("TexturePool: RenderBackend not available"); + E2D_LOG_ERROR("TexturePool: 渲染后端不可用"); return TextureRef(); } Ptr texture = backend->loadTexture(path); if (!texture) { - E2D_LOG_ERROR("TexturePool: Failed to load texture: {}", path); + E2D_LOG_ERROR("TexturePool: 加载纹理失败: {}", path); return TextureRef(); } @@ -299,7 +299,7 @@ TextureRef TexturePool::getOrLoad(const std::string& path, const Rect& region, evictLRU(currentMemoryUsage_ + memorySize - maxMemoryUsage_); if (currentMemoryUsage_ + memorySize > maxMemoryUsage_) { - E2D_LOG_WARN("TexturePool: Memory limit exceeded"); + E2D_LOG_WARN("TexturePool: 内存限制超出"); return TextureRef(); } } @@ -405,7 +405,7 @@ bool TexturePool::removeFromCache(const TextureKey& key) { if (it != cache_.end()) { currentMemoryUsage_ -= it->second.memorySize; cache_.erase(it); - E2D_LOG_DEBUG("TexturePool: Removed texture from cache"); + E2D_LOG_DEBUG("TexturePool: 已从缓存移除纹理"); return true; } return false; @@ -432,7 +432,7 @@ size_t TexturePool::collectGarbage() { } if (removed > 0) { - E2D_LOG_INFO("TexturePool: Garbage collected {} textures", removed); + E2D_LOG_INFO("TexturePool: 垃圾回收 {} 个纹理", removed); } return removed; @@ -449,7 +449,7 @@ void TexturePool::clear() { cache_.clear(); currentMemoryUsage_ = 0; - E2D_LOG_INFO("TexturePool: Cleared all textures"); + E2D_LOG_INFO("TexturePool: 已清除所有纹理"); } // ============================================================================ @@ -482,7 +482,7 @@ void TexturePool::setMaxMemoryUsage(size_t maxMemory) { evictLRU(maxMemoryUsage_); } - E2D_LOG_INFO("TexturePool: Max memory set to {} bytes", maxMemory); + E2D_LOG_INFO("TexturePool: 最大内存设置为 {} 字节", maxMemory); } /** @@ -532,7 +532,7 @@ size_t TexturePool::evictLRU(size_t targetMemory) { if (evicted > 0) { evictionCount_.fetch_add(evicted, std::memory_order_relaxed); - E2D_LOG_INFO("TexturePool: LRU evicted {} textures", evicted); + E2D_LOG_INFO("TexturePool: LRU 淘汰 {} 个纹理", evicted); } return evicted; diff --git a/Extra2D/src/platform/backends/glfw/glfw_input.cpp b/Extra2D/src/platform/backends/glfw/glfw_input.cpp index 33b7da2..ca291fb 100644 --- a/Extra2D/src/platform/backends/glfw/glfw_input.cpp +++ b/Extra2D/src/platform/backends/glfw/glfw_input.cpp @@ -184,13 +184,13 @@ GLFWInput::GLFWInput() { GLFWInput::~GLFWInput() { shutdown(); } void GLFWInput::init() { - E2D_LOG_INFO("GLFWInput initialized"); + E2D_LOG_INFO("GLFWInput 已初始化"); openGamepad(); } void GLFWInput::shutdown() { closeGamepad(); - E2D_LOG_INFO("GLFWInput shutdown"); + E2D_LOG_INFO("GLFWInput 已关闭"); } void GLFWInput::update() { @@ -394,13 +394,13 @@ void GLFWInput::handleScrollEvent(double xoffset, double yoffset) { void GLFWInput::handleJoystickEvent(int jid, int event) { if (event == GLFW_CONNECTED) { - E2D_LOG_INFO("Gamepad connected: {}", jid); + E2D_LOG_INFO("游戏手柄已连接: {}", jid); if (gamepadId_ == -1) { openGamepad(); } } else if (event == GLFW_DISCONNECTED) { if (jid == gamepadId_) { - E2D_LOG_INFO("Gamepad disconnected: {}", jid); + E2D_LOG_INFO("游戏手柄已断开: {}", jid); closeGamepad(); } } @@ -463,7 +463,7 @@ void GLFWInput::openGamepad() { for (int jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; ++jid) { if (glfwJoystickPresent(jid) && glfwJoystickIsGamepad(jid)) { gamepadId_ = jid; - E2D_LOG_INFO("Gamepad opened: {}", glfwGetGamepadName(jid)); + E2D_LOG_INFO("游戏手柄已打开: {}", glfwGetGamepadName(jid)); return; } } diff --git a/Extra2D/src/platform/backends/glfw/glfw_window.cpp b/Extra2D/src/platform/backends/glfw/glfw_window.cpp index 74939f4..b939140 100644 --- a/Extra2D/src/platform/backends/glfw/glfw_window.cpp +++ b/Extra2D/src/platform/backends/glfw/glfw_window.cpp @@ -4,7 +4,6 @@ #include #include - namespace extra2d { GLFWWindow::GLFWWindow() {} @@ -42,7 +41,7 @@ bool GLFWWindow::create(const std::string &title, int width, int height, glfwCreateWindow(width, height, title.c_str(), monitor, nullptr); if (!glfwWindow_) { - E2D_LOG_ERROR("Failed to create GLFW window"); + E2D_LOG_ERROR("创建 GLFW 窗口失败"); deinitGLFW(); return false; } @@ -66,7 +65,7 @@ bool GLFWWindow::create(const std::string &title, int width, int height, glfwMakeContextCurrent(glfwWindow_); if (!gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress)) { - E2D_LOG_ERROR("Failed to initialize GLAD GLES2"); + E2D_LOG_ERROR("初始化 GLAD GLES2 失败"); glfwDestroyWindow(glfwWindow_); glfwWindow_ = nullptr; deinitGLFW(); @@ -94,8 +93,7 @@ bool GLFWWindow::create(const std::string &title, int width, int height, input_->setWindow(glfwWindow_); input_->init(); - E2D_LOG_INFO("GLFW window created: {}x{}", width_, height_); - E2D_LOG_INFO(" Platform: OpenGL ES 3.2"); + E2D_LOG_INFO("GLFW 窗口创建成功: {}x{}", width_, height_); return true; } @@ -326,7 +324,7 @@ bool GLFWWindow::initGLFW() { static int glfwInitCount = 0; if (glfwInitCount == 0) { if (!glfwInit()) { - E2D_LOG_ERROR("Failed to initialize GLFW"); + E2D_LOG_ERROR("初始化 GLFW 失败"); return false; } glfwInitCount++; diff --git a/Extra2D/src/platform/backends/sdl2/sdl2_input.cpp b/Extra2D/src/platform/backends/sdl2/sdl2_input.cpp index 608bc31..a84660f 100644 --- a/Extra2D/src/platform/backends/sdl2/sdl2_input.cpp +++ b/Extra2D/src/platform/backends/sdl2/sdl2_input.cpp @@ -18,10 +18,10 @@ SDL2Input::SDL2Input() { SDL2Input::~SDL2Input() { shutdown(); } void SDL2Input::init() { - E2D_LOG_INFO("SDL2Input initialized"); + E2D_LOG_INFO("SDL2Input 已初始化"); if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) { - E2D_LOG_WARN("Failed to init gamecontroller subsystem: {}", SDL_GetError()); + E2D_LOG_WARN("初始化游戏手柄子系统失败: {}", SDL_GetError()); } openGamepad(); @@ -29,7 +29,7 @@ void SDL2Input::init() { void SDL2Input::shutdown() { closeGamepad(); - E2D_LOG_INFO("SDL2Input shutdown"); + E2D_LOG_INFO("SDL2Input 已关闭"); } void SDL2Input::update() { @@ -131,7 +131,7 @@ void SDL2Input::handleSDLEvent(const SDL_Event &event) { } case SDL_CONTROLLERDEVICEADDED: - E2D_LOG_INFO("Gamepad connected: index {}", event.cdevice.which); + E2D_LOG_INFO("游戏手柄已连接: 索引 {}", event.cdevice.which); openGamepad(); break; @@ -139,7 +139,7 @@ void SDL2Input::handleSDLEvent(const SDL_Event &event) { if (gamepad_ && event.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamepad_))) { - E2D_LOG_INFO("Gamepad disconnected"); + E2D_LOG_INFO("游戏手柄已断开"); closeGamepad(); } break; @@ -354,7 +354,7 @@ void SDL2Input::openGamepad() { gamepad_ = SDL_GameControllerOpen(i); if (gamepad_) { gamepadIndex_ = i; - E2D_LOG_INFO("Gamepad opened: {}", SDL_GameControllerName(gamepad_)); + E2D_LOG_INFO("游戏手柄已打开: {}", SDL_GameControllerName(gamepad_)); return; } } diff --git a/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp b/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp index 1131d76..216d138 100644 --- a/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp +++ b/Extra2D/src/platform/backends/sdl2/sdl2_window.cpp @@ -39,14 +39,14 @@ bool SDL2Window::create(const std::string &title, int width, int height, SDL_WINDOWPOS_CENTERED, width, height, flags); if (!sdlWindow_) { - E2D_LOG_ERROR("Failed to create SDL window: {}", SDL_GetError()); + E2D_LOG_ERROR("创建 SDL 窗口失败: {}", SDL_GetError()); deinitSDL(); return false; } glContext_ = SDL_GL_CreateContext(sdlWindow_); if (!glContext_) { - E2D_LOG_ERROR("Failed to create OpenGL context: {}", SDL_GetError()); + E2D_LOG_ERROR("创建 OpenGL 上下文失败: {}", SDL_GetError()); SDL_DestroyWindow(sdlWindow_); sdlWindow_ = nullptr; deinitSDL(); @@ -54,7 +54,7 @@ bool SDL2Window::create(const std::string &title, int width, int height, } if (!gladLoadGLES2Loader((GLADloadproc)SDL_GL_GetProcAddress)) { - E2D_LOG_ERROR("Failed to initialize GLAD GLES2"); + E2D_LOG_ERROR("初始化 GLAD GLES2 失败"); SDL_GL_DeleteContext(glContext_); glContext_ = nullptr; SDL_DestroyWindow(sdlWindow_); @@ -77,8 +77,8 @@ bool SDL2Window::create(const std::string &title, int width, int height, input_ = makeUnique(); input_->init(); - E2D_LOG_INFO("SDL2 window created: {}x{}", width_, height_); - E2D_LOG_INFO(" Platform: OpenGL ES 3.2"); + E2D_LOG_INFO("SDL2 窗口创建成功: {}x{}", width_, height_); + E2D_LOG_INFO(" 平台: OpenGL ES 3.2"); return true; } @@ -270,7 +270,7 @@ bool SDL2Window::initSDL() { if (sdlInitCount == 0) { Uint32 initFlags = SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER; if (SDL_Init(initFlags) != 0) { - E2D_LOG_ERROR("Failed to initialize SDL: {}", SDL_GetError()); + E2D_LOG_ERROR("初始化 SDL 失败: {}", SDL_GetError()); return false; } sdlInitCount++; diff --git a/Extra2D/src/platform/window_module.cpp b/Extra2D/src/platform/window_module.cpp index 15b3e78..c8044f7 100644 --- a/Extra2D/src/platform/window_module.cpp +++ b/Extra2D/src/platform/window_module.cpp @@ -41,24 +41,24 @@ bool WindowModule::init() { #error "No window backend defined" #endif - E2D_LOG_INFO("Window backend initialized"); + E2D_LOG_INFO("窗口后端已初始化"); - E2D_LOG_INFO("Creating window with size {}x{}", cfg_.w, cfg_.h); + E2D_LOG_INFO("正在创建窗口,尺寸 {}x{}", cfg_.w, cfg_.h); // 创建窗口(使用配置的后端) win_ = platform::BackendFactory::createWindow(cfg_.backend); if (!win_) { - E2D_LOG_ERROR("Failed to create window backend: {}", cfg_.backend); + E2D_LOG_ERROR("创建窗口后端失败: {}", cfg_.backend); return false; } if (!win_->create(cfg_.title, cfg_.w, cfg_.h, cfg_.vsync)) { - E2D_LOG_ERROR("Failed to create window"); + E2D_LOG_ERROR("创建窗口失败"); shutdown(); return false; } - E2D_LOG_INFO("Window created successfully"); + E2D_LOG_INFO("窗口创建成功"); initialized_ = true; return true; } diff --git a/Extra2D/src/scene/scene_manager.cpp b/Extra2D/src/scene/scene_manager.cpp index 56077d8..497d11c 100644 --- a/Extra2D/src/scene/scene_manager.cpp +++ b/Extra2D/src/scene/scene_manager.cpp @@ -88,7 +88,7 @@ void SceneManager::runWithScene(Ptr scene) { } if (!sceneStack_.empty()) { - E2D_LOG_WARN("SceneManager: runWithScene should only be called once"); + E2D_LOG_WARN("SceneManager: runWithScene 应该只被调用一次"); return; } @@ -575,15 +575,15 @@ void SceneManager::render(RenderBackend &renderer) { clearColor = sceneStack_.top()->getBackgroundColor(); } - E2D_LOG_TRACE("SceneManager::render - beginFrame with color({}, {}, {})", + E2D_LOG_TRACE("SceneManager::render - beginFrame 颜色({}, {}, {})", clearColor.r, clearColor.g, clearColor.b); renderer.beginFrame(clearColor); if (!sceneStack_.empty()) { - E2D_LOG_TRACE("SceneManager::render - rendering scene content"); + E2D_LOG_TRACE("SceneManager::render - 正在渲染场景内容"); sceneStack_.top()->renderContent(renderer); } else { - E2D_LOG_WARN("SceneManager::render - no scene to render"); + E2D_LOG_WARN("SceneManager::render - 没有场景可渲染"); } renderer.endFrame();