feat: 添加并行模块初始化支持并优化日志本地化

refactor(registry): 重构模块初始化逻辑以支持并行初始化
style: 统一日志消息为中文并优化格式
fix: 修复着色器元数据处理和默认值应用问题
This commit is contained in:
ChestnutYueyue 2026-02-19 00:48:04 +08:00
parent 463965439e
commit e9bd44b63e
33 changed files with 1011 additions and 507 deletions

View File

@ -52,6 +52,12 @@ public:
*/
virtual std::vector<std::type_index> deps() const { return {}; }
/**
* @brief
* @return true
*/
virtual bool allowParallelInit() const { return true; }
/**
* @brief Application
* @param app Application指针

View File

@ -6,6 +6,7 @@
#include <typeindex>
#include <vector>
#include <memory>
#include <future>
namespace extra2d {
@ -79,7 +80,7 @@ public:
void setApp(Application* app) { app_ = app; }
/**
* @brief
* @brief
* @return true
*/
bool init();
@ -109,6 +110,13 @@ private:
*/
std::vector<Module*> topologicalSort();
/**
* @brief
*
* @return
*/
std::vector<std::vector<Module*>> groupByLevel();
std::unordered_map<std::type_index, UniquePtr<Module>> modules_;
Application* app_ = nullptr;
};

View File

@ -58,6 +58,13 @@ public:
return {std::type_index(typeid(WindowModule))};
}
/**
* @brief
* RenderModule OpenGL 线
* @return false
*/
bool allowParallelInit() const override { return false; }
/**
* @brief
* @return

View File

@ -1,6 +1,8 @@
#pragma once
#include <extra2d/core/types.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <string>
#include <unordered_map>
#include <vector>
@ -18,17 +20,88 @@ struct ShaderLoadResult {
std::vector<std::string> 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<std::string, ShaderUniformValue>;
// ============================================================================
// Shader Sampler 定义
// ============================================================================
struct ShaderSamplerDef {
std::string type;
std::string description;
};
// ============================================================================
// Shader元数据
// ============================================================================
struct ShaderMetadata {
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<std::string> defines;
std::unordered_map<std::string, std::string> uniforms;
std::unordered_map<std::string, ShaderUniformDef> uniformDefs;
std::unordered_map<std::string, ShaderSamplerDef> samplerDefs;
};
// ============================================================================
@ -45,9 +118,8 @@ public:
* @param fragPath
* @return
*/
virtual ShaderLoadResult loadFromSeparateFiles(
const std::string& name,
const std::string& vertPath,
virtual ShaderLoadResult
loadFromSeparateFiles(const std::string &name, const std::string &vertPath,
const std::string &fragPath) = 0;
/**
@ -63,8 +135,7 @@ public:
* @param fragSource
* @return
*/
virtual ShaderLoadResult loadFromSource(
const std::string& vertSource,
virtual ShaderLoadResult loadFromSource(const std::string &vertSource,
const std::string &fragSource) = 0;
/**
@ -74,9 +145,8 @@ public:
* @param outDependencies
* @return
*/
virtual std::string processIncludes(
const std::string& source,
const std::string& baseDir,
virtual std::string
processIncludes(const std::string &source, const std::string &baseDir,
std::vector<std::string> &outDependencies) = 0;
/**
@ -85,8 +155,7 @@ public:
* @param defines
* @return
*/
virtual std::string applyDefines(
const std::string& source,
virtual std::string applyDefines(const std::string &source,
const std::vector<std::string> &defines) = 0;
/**
@ -112,8 +181,7 @@ public:
* @param fragPath
* @return
*/
ShaderLoadResult loadFromSeparateFiles(
const std::string& name,
ShaderLoadResult loadFromSeparateFiles(const std::string &name,
const std::string &vertPath,
const std::string &fragPath) override;
@ -130,8 +198,7 @@ public:
* @param fragSource
* @return
*/
ShaderLoadResult loadFromSource(
const std::string& vertSource,
ShaderLoadResult loadFromSource(const std::string &vertSource,
const std::string &fragSource) override;
/**
@ -141,9 +208,8 @@ public:
* @param outDependencies
* @return
*/
std::string processIncludes(
const std::string& source,
const std::string& baseDir,
std::string
processIncludes(const std::string &source, const std::string &baseDir,
std::vector<std::string> &outDependencies) override;
/**
@ -152,8 +218,7 @@ public:
* @param defines
* @return
*/
std::string applyDefines(
const std::string& source,
std::string applyDefines(const std::string &source,
const std::vector<std::string> &defines) override;
/**
@ -202,10 +267,8 @@ private:
* @param outMetadata
* @return truefalse
*/
bool parseCombinedFile(const std::string& content,
std::string& outVert,
std::string& outFrag,
ShaderMetadata& outMetadata);
bool parseCombinedFile(const std::string &content, std::string &outVert,
std::string &outFrag, ShaderMetadata &outMetadata);
/**
* @brief JSON块
@ -213,7 +276,8 @@ private:
* @param outMetadata
* @return truefalse
*/
bool parseMetadata(const std::string& jsonContent, ShaderMetadata& outMetadata);
bool parseMetadata(const std::string &jsonContent,
ShaderMetadata &outMetadata);
/**
* @brief include文件路径
@ -221,7 +285,8 @@ private:
* @param baseDir
* @return
*/
std::string findIncludeFile(const std::string& includeName, const std::string& baseDir);
std::string findIncludeFile(const std::string &includeName,
const std::string &baseDir);
};
} // namespace extra2d

View File

@ -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<std::string, ShaderUniformDef> getUniformDefs(const std::string& name) const;
/**
* @brief Shader的sampler定义
* @param name Shader名称
* @return sampler定义映射
*/
std::unordered_map<std::string, ShaderSamplerDef> getSamplerDefs(const std::string& name) const;
/**
* @brief uniform值到着色器
* JSON元数据中的uniform定义uniform值
* @param shader
* @param shaderName Shader名称
* @param values uniform值映射表
*/
void applyUniforms(Ptr<IShader> shader, const std::string& shaderName, const UniformValueMap& values);
/**
* @brief sampler绑定到着色器
* JSON元数据中的sampler定义
* @param shader
* @param shaderName Shader名称
*/
void applySamplers(Ptr<IShader> 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名称

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#include <extra2d/core/registry.h>
#include <extra2d/services/logger_service.h>
#include <future>
#include <queue>
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 (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;
}
}
// 如果只有一个模块或不支持并行,使用串行初始化
if (modules.size() <= 1 || !hasParallelModules) {
for (auto *module : modules) {
E2D_REGISTRY("正在初始化模块: {} (层级 {})", module->name(), level);
for (auto *module : sorted) {
E2D_REGISTRY("Initializing module: {}", module->name());
if (!module->init()) {
E2D_ERROR("Failed to initialize module: {}", module->name());
E2D_ERROR("初始化模块失败: {}", module->name());
return false;
}
E2D_REGISTRY("Module {} initialized successfully", module->name());
E2D_REGISTRY("模块 {} 初始化成功", module->name());
}
} else {
// 并行初始化当前层级的模块
E2D_REGISTRY("正在并行初始化 {} 个模块 (层级 {})...", modules.size(),
level);
std::vector<std::future<std::pair<Module *, bool>>> futures;
std::vector<Module *> 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);
}
}
E2D_REGISTRY("All modules initialized");
// 等待并行模块完成
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("所有模块初始化完成");
return true;
}
@ -83,4 +144,63 @@ std::vector<Module *> Registry::topologicalSort() {
return result;
}
std::vector<std::vector<Module *>> Registry::groupByLevel() {
std::vector<std::vector<Module *>> levels;
std::unordered_map<Module *, int> inDegree;
std::unordered_map<Module *, std::vector<Module *>> adj;
std::unordered_map<Module *, int> 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<Module *> 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<size_t>(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

View File

@ -14,7 +14,7 @@ BackendFactory::registry() {
void BackendFactory::reg(const std::string &name, BackendFn backend,
const std::vector<std::string> &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 &reg = 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<RenderBackend> 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<RenderBackend>
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 "";
}

View File

@ -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<int>(type_),
static_cast<int>(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_;

View File

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

View File

@ -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_t>(size));
if (!file.read(reinterpret_cast<char *>(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;
}

View File

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

View File

@ -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<GLFramebuffer> GLRenderer::createFramebuffer(const FramebufferDesc &desc) {
auto framebuffer = makePtr<GLFramebuffer>();
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());
}
}

View File

@ -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<uint8_t> &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<uint8_t> &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<uint8_t> &binary) {
*/
bool GLShader::getBinary(std::vector<uint8_t> &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<uint8_t> &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<uint8_t> &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<IShader> 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<uint8_t> &outBinary) {
const GLShader *glShader = dynamic_cast<const GLShader *>(&shader);
if (!glShader) {
E2D_LOG_ERROR("Shader is not a GLShader instance");
E2D_LOG_ERROR("着色器不是 GLShader 实例");
return false;
}

View File

@ -4,7 +4,6 @@
#include <extra2d/graphics/shader/shader_manager.h>
#include <extra2d/services/logger_service.h>
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<const GLTexture *>(&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<SpriteData> &sprites) {
const GLTexture *glTex = dynamic_cast<const GLTexture *>(&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 策略优化动态缓冲区

View File

@ -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<char *>(&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<char *>(&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<uint8_t> compressedData(imageSize);
file.read(reinterpret_cast<char *>(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<char *>(&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<char *>(&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<uint8_t> compressedData(imageSize);
file.read(reinterpret_cast<char *>(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>(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_; }

View File

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

View File

@ -7,7 +7,6 @@
#include <extra2d/graphics/shader/shader_manager.h>
#include <extra2d/platform/window_module.h>
#include <extra2d/services/logger_service.h>
#include <filesystem>
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<WindowModule>();
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<GLShaderFactory>();
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;
}

View File

@ -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<std::mutex> 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<std::mutex> 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_);
}

View File

@ -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<ShaderCacheEntry> 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<ShaderCacheEntry> 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("所有着色器缓存已清除");
}
/**

View File

@ -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<std::string> &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);

View File

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

View File

@ -2,10 +2,11 @@
#include <extra2d/graphics/shader/shader_manager.h>
#include <extra2d/services/logger_service.h>
#include <filesystem>
#include <nlohmann/json.hpp>
namespace nl = nlohmann;
namespace fs = std::filesystem;
namespace extra2d {
@ -28,8 +29,8 @@ ShaderManager &ShaderManager::getInstance() {
bool ShaderManager::init(Ptr<IShaderFactory> 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<IShaderFactory> 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<IShaderFactory> 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<IShader> 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<IShader> 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<IShader> 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<uint8_t> 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<IShader> 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<IShader> ShaderManager::loadFromFiles(const std::string &name,
callback);
}
E2D_LOG_DEBUG("Shader loaded: {}", name);
E2D_LOG_DEBUG("着色器已加载: {}", name);
return shader;
}
@ -212,7 +213,7 @@ Ptr<IShader> ShaderManager::loadFromFiles(const std::string &name,
*/
Ptr<IShader> 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<IShader> 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<IShader> 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<uint8_t> 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<IShader> 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<IShader> 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<IShader> 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<IShader> ShaderManager::loadFromSource(const std::string &name,
Ptr<IShader> 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<IShader> 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<IShader> 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<IShader> 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<IShader> ShaderManager::getBuiltin(const std::string &name) {
Ptr<IShader> 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<IShader> 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<IShader> 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<std::string>();
}
if (j.contains("version")) {
metadata.version = j["version"].get<std::string>();
}
if (j.contains("description")) {
metadata.description = j["description"].get<std::string>();
}
// 解析 uniforms 详细定义
if (j.contains("uniforms")) {
for (auto &[key, value] : j["uniforms"].items()) {
ShaderUniformDef def;
if (value.contains("type")) {
def.type = value["type"].get<std::string>();
}
if (value.contains("description")) {
def.description = value["description"].get<std::string>();
}
// 解析默认值
if (value.contains("default")) {
def.hasDefault = true;
if (def.type == "float") {
def.defaultValue = value["default"].get<float>();
} else if (def.type == "int") {
def.defaultInt = value["default"].get<int>();
} else if (def.type == "bool") {
def.defaultBool = value["default"].get<bool>();
} else if (def.type == "vec4" && value["default"].is_array()) {
auto arr = value["default"].get<std::vector<float>>();
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<std::vector<float>>();
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<std::string>();
}
if (value.contains("description")) {
def.description = value["description"].get<std::string>();
}
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<IShader> ShaderManager::loadFromMetadata(const std::string &jsonPath,
std::string vertRelativePath = opengl["vertex"].get<std::string>();
std::string fragRelativePath = opengl["fragment"].get<std::string>();
// 构建完整路径
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<IShader> 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<IShader> 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<IShader> 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<IShader> ShaderManager::loadFromCache(const std::string &name,
Ptr<IShader> 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<IShader> 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<std::string, ShaderUniformDef>
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<std::string, ShaderSamplerDef>
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<IShader> 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<IShader> shader,
const std::string &shaderName) {
if (!shader)
return;
// TODO: 从JSON中解析binding并设置
// 目前sampler绑定在submitBatch中通过setInt设置
}
} // namespace extra2d

View File

@ -14,7 +14,7 @@ namespace extra2d {
Ptr<IShader> ShaderPreset::Water(const WaterParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Water(const WaterParams &params) {
Ptr<IShader> ShaderPreset::Outline(const OutlineParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Outline(const OutlineParams &params) {
Ptr<IShader> ShaderPreset::Distortion(const DistortionParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Distortion(const DistortionParams &params) {
Ptr<IShader> ShaderPreset::Pixelate(const PixelateParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Pixelate(const PixelateParams &params) {
Ptr<IShader> ShaderPreset::Invert(const InvertParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Invert(const InvertParams &params) {
Ptr<IShader> ShaderPreset::Grayscale(const GrayscaleParams &params) {
Ptr<IShader> 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<IShader> ShaderPreset::Grayscale(const GrayscaleParams &params) {
Ptr<IShader> ShaderPreset::Blur(const BlurParams &params) {
Ptr<IShader> 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<IShader>
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<IShader> 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<IShader> 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<IShader> 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;
}

View File

@ -24,7 +24,7 @@ TextureAtlasPage::TextureAtlasPage(int width, int height)
// 初始化矩形打包根节点
root_ = std::make_unique<PackNode>(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("纹理图集已清空");
}
// ============================================================================

View File

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

View File

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

View File

@ -4,7 +4,6 @@
#include <extra2d/services/logger_service.h>
#include <glad/glad.h>
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++;

View File

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

View File

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

View File

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

View File

@ -88,7 +88,7 @@ void SceneManager::runWithScene(Ptr<Scene> 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();