diff --git a/include/app/application.h b/include/app/application.h index fe63b42..24d5b5b 100644 --- a/include/app/application.h +++ b/include/app/application.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include #include diff --git a/include/core/string.h b/include/core/string.h deleted file mode 100644 index ddd51f5..0000000 --- a/include/core/string.h +++ /dev/null @@ -1,209 +0,0 @@ -#pragma once - -#include - -namespace extra2d { - -// ============================================================================ -// 字符串编码转换工具函数 -// 统一使用 std::string (UTF-8) 作为项目标准字符串类型 -// ============================================================================ - -// UTF-8 ↔ UTF-16 转换 -std::u16string utf8ToUtf16(const std::string& utf8); -std::string utf16ToUtf8(const std::u16string& utf16); - -// UTF-8 ↔ UTF-32 转换 -std::u32string utf8ToUtf32(const std::string& utf8); -std::string utf32ToUtf8(const std::u32string& utf32); - -// UTF-8 ↔ Wide String 转换 -std::wstring utf8ToWide(const std::string& utf8); -std::string wideToUtf8(const std::wstring& wide); - -// UTF-8 ↔ GBK/GB2312 转换(Windows 中文系统常用) -std::string utf8ToGbk(const std::string& utf8); -std::string gbkToUtf8(const std::string& gbk); - -// ============================================================================ -// 内联实现 -// ============================================================================ - -inline std::u16string utf8ToUtf16(const std::string& utf8) { - if (utf8.empty()) return std::u16string(); - - // UTF-8 → UTF-32 → UTF-16 (with surrogate pairs) - std::u32string u32 = utf8ToUtf32(utf8); - std::u16string result; - result.reserve(u32.size()); - - for (char32_t ch : u32) { - if (ch <= 0xFFFF) { - result.push_back(static_cast(ch)); - } else if (ch <= 0x10FFFF) { - // Surrogate pair - ch -= 0x10000; - result.push_back(static_cast(0xD800 | (ch >> 10))); - result.push_back(static_cast(0xDC00 | (ch & 0x3FF))); - } - } - - return result; -} - -inline std::string utf16ToUtf8(const std::u16string& utf16) { - if (utf16.empty()) return std::string(); - - // UTF-16 → UTF-32 → UTF-8 - std::u32string u32; - u32.reserve(utf16.size()); - - for (size_t i = 0; i < utf16.size(); ++i) { - char16_t cu = utf16[i]; - char32_t ch; - if (cu >= 0xD800 && cu <= 0xDBFF && i + 1 < utf16.size()) { - // High surrogate - char16_t cl = utf16[i + 1]; - if (cl >= 0xDC00 && cl <= 0xDFFF) { - ch = 0x10000 + ((static_cast(cu - 0xD800) << 10) | - (cl - 0xDC00)); - ++i; - } else { - ch = cu; // Invalid, pass through - } - } else { - ch = cu; - } - u32.push_back(ch); - } - - return utf32ToUtf8(u32); -} - -inline std::u32string utf8ToUtf32(const std::string& utf8) { - std::u32string result; - result.reserve(utf8.size()); - - const char* ptr = utf8.c_str(); - const char* end = ptr + utf8.size(); - - while (ptr < end) { - char32_t ch = 0; - unsigned char byte = static_cast(*ptr); - - if ((byte & 0x80) == 0) { - // 1-byte sequence - ch = byte; - ptr += 1; - } else if ((byte & 0xE0) == 0xC0) { - // 2-byte sequence - ch = (byte & 0x1F) << 6; - ch |= (static_cast(ptr[1]) & 0x3F); - ptr += 2; - } else if ((byte & 0xF0) == 0xE0) { - // 3-byte sequence - ch = (byte & 0x0F) << 12; - ch |= (static_cast(ptr[1]) & 0x3F) << 6; - ch |= (static_cast(ptr[2]) & 0x3F); - ptr += 3; - } else if ((byte & 0xF8) == 0xF0) { - // 4-byte sequence - ch = (byte & 0x07) << 18; - ch |= (static_cast(ptr[1]) & 0x3F) << 12; - ch |= (static_cast(ptr[2]) & 0x3F) << 6; - ch |= (static_cast(ptr[3]) & 0x3F); - ptr += 4; - } else { - // Invalid UTF-8, skip - ptr += 1; - continue; - } - - result.push_back(ch); - } - - return result; -} - -inline std::string utf32ToUtf8(const std::u32string& utf32) { - std::string result; - - for (char32_t ch : utf32) { - if (ch <= 0x7F) { - // 1-byte - result.push_back(static_cast(ch)); - } else if (ch <= 0x7FF) { - // 2-byte - result.push_back(static_cast(0xC0 | ((ch >> 6) & 0x1F))); - result.push_back(static_cast(0x80 | (ch & 0x3F))); - } else if (ch <= 0xFFFF) { - // 3-byte - result.push_back(static_cast(0xE0 | ((ch >> 12) & 0x0F))); - result.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); - result.push_back(static_cast(0x80 | (ch & 0x3F))); - } else if (ch <= 0x10FFFF) { - // 4-byte - result.push_back(static_cast(0xF0 | ((ch >> 18) & 0x07))); - result.push_back(static_cast(0x80 | ((ch >> 12) & 0x3F))); - result.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); - result.push_back(static_cast(0x80 | (ch & 0x3F))); - } - } - - return result; -} - -inline std::wstring utf8ToWide(const std::string& utf8) { - if (utf8.empty()) return std::wstring(); - - if constexpr (sizeof(wchar_t) == 4) { - // wchar_t is 32-bit (Linux/Switch): same as UTF-32 - std::u32string u32 = utf8ToUtf32(utf8); - return std::wstring(u32.begin(), u32.end()); - } else { - // wchar_t is 16-bit (Windows): same as UTF-16 - std::u16string u16 = utf8ToUtf16(utf8); - return std::wstring(u16.begin(), u16.end()); - } -} - -inline std::string wideToUtf8(const std::wstring& wide) { - if (wide.empty()) return std::string(); - - if constexpr (sizeof(wchar_t) == 4) { - std::u32string u32(wide.begin(), wide.end()); - return utf32ToUtf8(u32); - } else { - std::u16string u16(wide.begin(), wide.end()); - return utf16ToUtf8(u16); - } -} - -// GBK/GB2312 转换(Windows 平台实现) -// 注意:Windows 实现在 .cpp 文件中,避免头文件包含 windows.h 导致冲突 -#ifdef _WIN32 -// 前向声明,实现在 .cpp 文件中 -std::string utf8ToGbkImpl(const std::string& utf8); -std::string gbkToUtf8Impl(const std::string& gbk); - -inline std::string utf8ToGbk(const std::string& utf8) { - return utf8ToGbkImpl(utf8); -} - -inline std::string gbkToUtf8(const std::string& gbk) { - return gbkToUtf8Impl(gbk); -} -#else -// 非 Windows 平台,GBK 转换使用 iconv 或返回原字符串 -inline std::string utf8ToGbk(const std::string& utf8) { - // TODO: 使用 iconv 实现 - return utf8; -} - -inline std::string gbkToUtf8(const std::string& gbk) { - // TODO: 使用 iconv 实现 - return gbk; -} -#endif - -} // namespace extra2d diff --git a/include/extra2d.h b/include/extra2d.h index 4e4c50b..c1eab85 100644 --- a/include/extra2d.h +++ b/include/extra2d.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -26,7 +25,6 @@ #include #include #include -#include // Scene #include diff --git a/include/platform/window.h b/include/platform/window.h index b99912f..2d8ce33 100644 --- a/include/platform/window.h +++ b/include/platform/window.h @@ -1,9 +1,9 @@ #pragma once #include -#include #include #include +#include #include #include diff --git a/include/renderer/shader.h b/include/renderer/shader.h deleted file mode 100644 index 6115cff..0000000 --- a/include/renderer/shader.h +++ /dev/null @@ -1,179 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace extra2d { - -// ============================================================================ -// Shader参数绑定回调 -// ============================================================================ -using ShaderBindCallback = std::function; - -// ============================================================================ -// Shader系统 - 管理所有Shader的加载、缓存和热重载 -// ============================================================================ -class ShaderSystem { -public: - // ------------------------------------------------------------------------ - // 单例访问 - // ------------------------------------------------------------------------ - static ShaderSystem &getInstance(); - - // ------------------------------------------------------------------------ - // 初始化和关闭 - // ------------------------------------------------------------------------ - bool init(); - void shutdown(); - - // ------------------------------------------------------------------------ - // Shader加载 - // ------------------------------------------------------------------------ - - /** - * @brief 从文件加载Shader - * @param name Shader名称(用于缓存) - * @param vertPath 顶点着色器文件路径 - * @param fragPath 片段着色器文件路径 - * @return 加载的Shader,失败返回nullptr - */ - Ptr loadFromFile(const std::string &name, - const std::string &vertPath, - const std::string &fragPath); - - /** - * @brief 从源码字符串加载Shader - * @param name Shader名称(用于缓存) - * @param vertSource 顶点着色器源码 - * @param fragSource 片段着色器源码 - * @return 加载的Shader,失败返回nullptr - */ - Ptr loadFromSource(const std::string &name, - const std::string &vertSource, - const std::string &fragSource); - - /** - * @brief 从已编译的程序获取Shader - * @param name Shader名称 - * @return 缓存的Shader,不存在返回nullptr - */ - Ptr get(const std::string &name); - - /** - * @brief 检查Shader是否存在 - */ - bool has(const std::string &name) const; - - // ------------------------------------------------------------------------ - // Shader移除 - // ------------------------------------------------------------------------ - void remove(const std::string &name); - void clear(); - - // ------------------------------------------------------------------------ - // 热重载支持 - // ------------------------------------------------------------------------ - - /** - * @brief 启用/禁用文件监视 - */ - void setFileWatching(bool enable); - bool isFileWatching() const { return fileWatching_; } - - /** - * @brief 更新文件监视(在主循环中调用) - */ - void updateFileWatching(); - - /** - * @brief 重载指定Shader - */ - bool reload(const std::string &name); - - /** - * @brief 重载所有Shader - */ - void reloadAll(); - - // ------------------------------------------------------------------------ - // 内置Shader获取 - // ------------------------------------------------------------------------ - Ptr getBuiltinSpriteShader(); - Ptr getBuiltinParticleShader(); - Ptr getBuiltinPostProcessShader(); - Ptr getBuiltinShapeShader(); - - // ------------------------------------------------------------------------ - // 工具方法 - // ------------------------------------------------------------------------ - - /** - * @brief 从文件读取文本内容 - */ - static std::string readFile(const std::string &filepath); - - /** - * @brief 获取Shader文件的最后修改时间 - */ - static uint64_t getFileModifiedTime(const std::string &filepath); - -private: - ShaderSystem() = default; - ~ShaderSystem() = default; - ShaderSystem(const ShaderSystem &) = delete; - ShaderSystem &operator=(const ShaderSystem &) = delete; - - struct ShaderInfo { - Ptr shader; - std::string vertPath; - std::string fragPath; - uint64_t vertModifiedTime; - uint64_t fragModifiedTime; - bool isBuiltin; - }; - - std::unordered_map shaders_; - bool fileWatching_ = false; - float watchTimer_ = 0.0f; - static constexpr float WATCH_INTERVAL = 1.0f; // 检查间隔(秒) - - // 内置Shader缓存 - Ptr builtinSpriteShader_; - Ptr builtinParticleShader_; - Ptr builtinPostProcessShader_; - Ptr builtinShapeShader_; - - bool loadBuiltinShaders(); - void checkAndReload(); -}; - -// ============================================================================ -// Shader参数包装器 - 简化Uniform设置 -// ============================================================================ -class ShaderParams { -public: - explicit ShaderParams(GLShader &shader); - - ShaderParams &setBool(const std::string &name, bool value); - ShaderParams &setInt(const std::string &name, int value); - ShaderParams &setFloat(const std::string &name, float value); - ShaderParams &setVec2(const std::string &name, const glm::vec2 &value); - ShaderParams &setVec3(const std::string &name, const glm::vec3 &value); - ShaderParams &setVec4(const std::string &name, const glm::vec4 &value); - ShaderParams &setMat4(const std::string &name, const glm::mat4 &value); - ShaderParams &setColor(const std::string &name, const Color &color); - -private: - GLShader &shader_; -}; - -// ============================================================================ -// 便捷宏 -// ============================================================================ -#define E2D_SHADER_SYSTEM() ::extra2d::ShaderSystem::getInstance() - -} // namespace extra2d diff --git a/src/core/string.cpp b/src/core/string.cpp deleted file mode 100644 index 128089d..0000000 --- a/src/core/string.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#ifdef _WIN32 -#include - -namespace extra2d { - -std::string utf8ToGbkImpl(const std::string& utf8) { - if (utf8.empty()) return std::string(); - - // UTF-8 → Wide → GBK - int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0); - if (wideLen <= 0) return std::string(); - - std::wstring wide(wideLen - 1, 0); - MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &wide[0], wideLen); - - int gbkLen = WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1, nullptr, 0, nullptr, nullptr); - if (gbkLen <= 0) return std::string(); - - std::string gbk(gbkLen - 1, 0); - WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1, &gbk[0], gbkLen, nullptr, nullptr); - - return gbk; -} - -std::string gbkToUtf8Impl(const std::string& gbk) { - if (gbk.empty()) return std::string(); - - // GBK → Wide → UTF-8 - int wideLen = MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, nullptr, 0); - if (wideLen <= 0) return std::string(); - - std::wstring wide(wideLen - 1, 0); - MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, &wide[0], wideLen); - - int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, nullptr, 0, nullptr, nullptr); - if (utf8Len <= 0) return std::string(); - - std::string utf8(utf8Len - 1, 0); - WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, &utf8[0], utf8Len, nullptr, nullptr); - - return utf8; -} - -} // namespace extra2d - -#endif // _WIN32 diff --git a/src/graphics/opengl/gl_font_atlas.cpp b/src/graphics/opengl/gl_font_atlas.cpp index e91c63d..19ac639 100644 --- a/src/graphics/opengl/gl_font_atlas.cpp +++ b/src/graphics/opengl/gl_font_atlas.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #define STB_TRUETYPE_IMPLEMENTATION #include @@ -10,6 +10,54 @@ namespace extra2d { +// ============================================================================ +// UTF-8 到 UTF-32 转换(简化版) +// ============================================================================ +static std::u32string utf8ToUtf32(const std::string& utf8) { + std::u32string result; + result.reserve(utf8.size()); + + const char* ptr = utf8.c_str(); + const char* end = ptr + utf8.size(); + + while (ptr < end) { + char32_t ch = 0; + unsigned char byte = static_cast(*ptr); + + if ((byte & 0x80) == 0) { + // 1-byte sequence + ch = byte; + ptr += 1; + } else if ((byte & 0xE0) == 0xC0) { + // 2-byte sequence + ch = (byte & 0x1F) << 6; + ch |= (static_cast(ptr[1]) & 0x3F); + ptr += 2; + } else if ((byte & 0xF0) == 0xE0) { + // 3-byte sequence + ch = (byte & 0x0F) << 12; + ch |= (static_cast(ptr[1]) & 0x3F) << 6; + ch |= (static_cast(ptr[2]) & 0x3F); + ptr += 3; + } else if ((byte & 0xF8) == 0xF0) { + // 4-byte sequence + ch = (byte & 0x07) << 18; + ch |= (static_cast(ptr[1]) & 0x3F) << 12; + ch |= (static_cast(ptr[2]) & 0x3F) << 6; + ch |= (static_cast(ptr[3]) & 0x3F); + ptr += 4; + } else { + // Invalid UTF-8, skip + ptr += 1; + continue; + } + + result.push_back(ch); + } + + return result; +} + // ============================================================================ // 构造函数 - 初始化字体图集 // ============================================================================ diff --git a/src/graphics/opengl/gl_renderer.cpp b/src/graphics/opengl/gl_renderer.cpp index e98b0ee..372b720 100644 --- a/src/graphics/opengl/gl_renderer.cpp +++ b/src/graphics/opengl/gl_renderer.cpp @@ -1,8 +1,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -14,6 +14,54 @@ namespace extra2d { +// ============================================================================ +// UTF-8 到 UTF-32 转换(简化版) +// ============================================================================ +static std::u32string utf8ToUtf32(const std::string& utf8) { + std::u32string result; + result.reserve(utf8.size()); + + const char* ptr = utf8.c_str(); + const char* end = ptr + utf8.size(); + + while (ptr < end) { + char32_t ch = 0; + unsigned char byte = static_cast(*ptr); + + if ((byte & 0x80) == 0) { + // 1-byte sequence + ch = byte; + ptr += 1; + } else if ((byte & 0xE0) == 0xC0) { + // 2-byte sequence + ch = (byte & 0x1F) << 6; + ch |= (static_cast(ptr[1]) & 0x3F); + ptr += 2; + } else if ((byte & 0xF0) == 0xE0) { + // 3-byte sequence + ch = (byte & 0x0F) << 12; + ch |= (static_cast(ptr[1]) & 0x3F) << 6; + ch |= (static_cast(ptr[2]) & 0x3F); + ptr += 3; + } else if ((byte & 0xF8) == 0xF0) { + // 4-byte sequence + ch = (byte & 0x07) << 18; + ch |= (static_cast(ptr[1]) & 0x3F) << 12; + ch |= (static_cast(ptr[2]) & 0x3F) << 6; + ch |= (static_cast(ptr[3]) & 0x3F); + ptr += 4; + } else { + // Invalid UTF-8, skip + ptr += 1; + continue; + } + + result.push_back(ch); + } + + return result; +} + // 形状渲染着色器 - 支持顶点颜色批处理 (GLES 3.2) static const char *SHAPE_VERTEX_SHADER = R"( #version 300 es diff --git a/src/renderer/shader_system.cpp b/src/renderer/shader_system.cpp deleted file mode 100644 index 718b4d0..0000000 --- a/src/renderer/shader_system.cpp +++ /dev/null @@ -1,492 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -#ifdef _WIN32 -#include -#endif - -namespace extra2d { - -// ============================================================================ -// 内置Shader源码 -// ============================================================================ - -// 标准精灵着色器 (GLES 3.2) -static const char *BUILTIN_SPRITE_VERT = R"( -#version 300 es -precision highp float; -layout(location = 0) in vec2 a_position; -layout(location = 1) in vec2 a_texCoord; -layout(location = 2) in vec4 a_color; - -uniform mat4 u_viewProjection; -uniform mat4 u_model; - -out vec2 v_texCoord; -out vec4 v_color; - -void main() { - gl_Position = u_viewProjection * u_model * vec4(a_position, 0.0, 1.0); - v_texCoord = a_texCoord; - v_color = a_color; -} -)"; - -static const char *BUILTIN_SPRITE_FRAG = R"( -#version 300 es -precision highp float; -in vec2 v_texCoord; -in vec4 v_color; - -uniform sampler2D u_texture; -uniform float u_opacity; - -out vec4 fragColor; - -void main() { - vec4 texColor = texture(u_texture, v_texCoord); - fragColor = texColor * v_color; - fragColor.a *= u_opacity; - - if (fragColor.a < 0.01) { - discard; - } -} -)"; - -// 粒子着色器 (GLES 3.2) -static const char *BUILTIN_PARTICLE_VERT = R"( -#version 300 es -precision highp float; -layout(location = 0) in vec2 a_position; -layout(location = 1) in vec2 a_texCoord; -layout(location = 2) in vec4 a_color; -layout(location = 3) in float a_size; -layout(location = 4) in float a_rotation; - -uniform mat4 u_viewProjection; - -out vec2 v_texCoord; -out vec4 v_color; - -void main() { - float c = cos(a_rotation); - float s = sin(a_rotation); - mat2 rot = mat2(c, -s, s, c); - - vec2 pos = rot * a_position * a_size; - gl_Position = u_viewProjection * vec4(pos, 0.0, 1.0); - - v_texCoord = a_texCoord; - v_color = a_color; -} -)"; - -static const char *BUILTIN_PARTICLE_FRAG = R"( -#version 300 es -precision highp float; -in vec2 v_texCoord; -in vec4 v_color; - -uniform sampler2D u_texture; -uniform int u_textureEnabled; - -out vec4 fragColor; - -void main() { - vec4 color = v_color; - - if (u_textureEnabled > 0) { - color *= texture(u_texture, v_texCoord); - } - - // 圆形粒子 - vec2 center = v_texCoord - vec2(0.5); - float dist = length(center); - float alpha = 1.0 - smoothstep(0.4, 0.5, dist); - color.a *= alpha; - - if (color.a < 0.01) { - discard; - } - - fragColor = color; -} -)"; - -// 后处理着色器 (GLES 3.2) -static const char *BUILTIN_POSTPROCESS_VERT = R"( -#version 300 es -precision highp float; -layout(location = 0) in vec2 a_position; -layout(location = 1) in vec2 a_texCoord; - -out vec2 v_texCoord; - -void main() { - gl_Position = vec4(a_position, 0.0, 1.0); - v_texCoord = a_texCoord; -} -)"; - -static const char *BUILTIN_POSTPROCESS_FRAG = R"( -#version 300 es -precision highp float; -in vec2 v_texCoord; - -uniform sampler2D u_texture; -uniform vec2 u_resolution; -uniform float u_time; - -out vec4 fragColor; - -void main() { - fragColor = texture(u_texture, v_texCoord); -} -)"; - -// 形状渲染着色器 (GLES 3.2) -static const char *BUILTIN_SHAPE_VERT = R"( -#version 300 es -precision highp float; -layout(location = 0) in vec2 a_position; -layout(location = 1) in vec4 a_color; - -uniform mat4 u_viewProjection; - -out vec4 v_color; - -void main() { - gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0); - v_color = a_color; -} -)"; - -static const char *BUILTIN_SHAPE_FRAG = R"( -#version 300 es -precision highp float; -in vec4 v_color; - -out vec4 fragColor; - -void main() { - fragColor = v_color; -} -)"; - -// ============================================================================ -// ShaderSystem实现 -// ============================================================================ - -ShaderSystem &ShaderSystem::getInstance() { - static ShaderSystem instance; - return instance; -} - -bool ShaderSystem::init() { - E2D_INFO("初始化Shader系统..."); - - if (!loadBuiltinShaders()) { - E2D_ERROR("加载内置Shader失败!"); - return false; - } - - E2D_INFO("Shader系统初始化完成"); - return true; -} - -void ShaderSystem::shutdown() { - E2D_INFO("关闭Shader系统..."); - clear(); - - builtinSpriteShader_.reset(); - builtinParticleShader_.reset(); - builtinPostProcessShader_.reset(); - builtinShapeShader_.reset(); -} - -bool ShaderSystem::loadBuiltinShaders() { - // 加载精灵Shader - builtinSpriteShader_ = std::make_shared(); - if (!builtinSpriteShader_->compileFromSource(BUILTIN_SPRITE_VERT, - BUILTIN_SPRITE_FRAG)) { - E2D_ERROR("编译内置精灵Shader失败!"); - return false; - } - - // 加载粒子Shader - builtinParticleShader_ = std::make_shared(); - if (!builtinParticleShader_->compileFromSource(BUILTIN_PARTICLE_VERT, - BUILTIN_PARTICLE_FRAG)) { - E2D_ERROR("编译内置粒子Shader失败!"); - return false; - } - - // 加载后处理Shader - builtinPostProcessShader_ = std::make_shared(); - if (!builtinPostProcessShader_->compileFromSource(BUILTIN_POSTPROCESS_VERT, - BUILTIN_POSTPROCESS_FRAG)) { - E2D_ERROR("编译内置后处理Shader失败!"); - return false; - } - - // 加载形状Shader - builtinShapeShader_ = std::make_shared(); - if (!builtinShapeShader_->compileFromSource(BUILTIN_SHAPE_VERT, - BUILTIN_SHAPE_FRAG)) { - E2D_ERROR("编译内置形状Shader失败!"); - return false; - } - - E2D_INFO("内置Shader加载成功"); - return true; -} - -Ptr ShaderSystem::loadFromFile(const std::string &name, - const std::string &vertPath, - const std::string &fragPath) { - // 读取文件内容 - std::string vertSource = readFile(vertPath); - std::string fragSource = readFile(fragPath); - - if (vertSource.empty()) { - E2D_ERROR("无法读取顶点着色器文件: {}", vertPath); - return nullptr; - } - - if (fragSource.empty()) { - E2D_ERROR("无法读取片段着色器文件: {}", fragPath); - return nullptr; - } - - // 编译Shader - auto shader = std::make_shared(); - if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) { - E2D_ERROR("编译Shader '{}' 失败", name); - return nullptr; - } - - // 存储Shader信息 - ShaderInfo info; - info.shader = shader; - info.vertPath = vertPath; - info.fragPath = fragPath; - info.vertModifiedTime = getFileModifiedTime(vertPath); - info.fragModifiedTime = getFileModifiedTime(fragPath); - info.isBuiltin = false; - - shaders_[name] = std::move(info); - - E2D_INFO("加载Shader '{}' 成功", name); - return shader; -} - -Ptr ShaderSystem::loadFromSource(const std::string &name, - const std::string &vertSource, - const std::string &fragSource) { - auto shader = std::make_shared(); - if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) { - E2D_ERROR("编译Shader '{}' 失败", name); - return nullptr; - } - - ShaderInfo info; - info.shader = shader; - info.vertModifiedTime = 0; - info.fragModifiedTime = 0; - info.isBuiltin = false; - - shaders_[name] = std::move(info); - - E2D_INFO("加载Shader '{}' 成功", name); - return shader; -} - -Ptr ShaderSystem::get(const std::string &name) { - auto it = shaders_.find(name); - if (it != shaders_.end()) { - return it->second.shader; - } - return nullptr; -} - -bool ShaderSystem::has(const std::string &name) const { - return shaders_.find(name) != shaders_.end(); -} - -void ShaderSystem::remove(const std::string &name) { shaders_.erase(name); } - -void ShaderSystem::clear() { shaders_.clear(); } - -void ShaderSystem::setFileWatching(bool enable) { - fileWatching_ = enable; - if (enable) { - E2D_INFO("启用Shader文件监视"); - } else { - E2D_INFO("禁用Shader文件监视"); - } -} - -void ShaderSystem::updateFileWatching() { - if (!fileWatching_) - return; - - watchTimer_ += 0.016f; // 假设60fps - if (watchTimer_ >= WATCH_INTERVAL) { - watchTimer_ = 0.0f; - checkAndReload(); - } -} - -void ShaderSystem::checkAndReload() { - for (auto &[name, info] : shaders_) { - if (info.isBuiltin) - continue; - if (info.vertPath.empty() || info.fragPath.empty()) - continue; - - uint64_t vertTime = getFileModifiedTime(info.vertPath); - uint64_t fragTime = getFileModifiedTime(info.fragPath); - - if (vertTime > info.vertModifiedTime || fragTime > info.fragModifiedTime) { - E2D_INFO("检测到Shader '{}' 文件变化,正在重载...", name); - reload(name); - } - } -} - -bool ShaderSystem::reload(const std::string &name) { - auto it = shaders_.find(name); - if (it == shaders_.end()) { - E2D_ERROR("无法重载不存在的Shader '{}'", name); - return false; - } - - auto &info = it->second; - if (info.isBuiltin) { - E2D_WARN("无法重载内置Shader '{}'", name); - return false; - } - - if (info.vertPath.empty() || info.fragPath.empty()) { - E2D_ERROR("Shader '{}' 没有关联的文件路径", name); - return false; - } - - // 重新加载 - auto newShader = loadFromFile(name, info.vertPath, info.fragPath); - if (newShader) { - E2D_INFO("重载Shader '{}' 成功", name); - return true; - } - - return false; -} - -void ShaderSystem::reloadAll() { - for (const auto &[name, info] : shaders_) { - if (!info.isBuiltin) { - reload(name); - } - } -} - -Ptr ShaderSystem::getBuiltinSpriteShader() { - return builtinSpriteShader_; -} - -Ptr ShaderSystem::getBuiltinParticleShader() { - return builtinParticleShader_; -} - -Ptr ShaderSystem::getBuiltinPostProcessShader() { - return builtinPostProcessShader_; -} - -Ptr ShaderSystem::getBuiltinShapeShader() { - return builtinShapeShader_; -} - -std::string ShaderSystem::readFile(const std::string &filepath) { - std::ifstream file(filepath, std::ios::in | std::ios::binary); - if (!file.is_open()) { - return ""; - } - - std::stringstream buffer; - buffer << file.rdbuf(); - return buffer.str(); -} - -uint64_t ShaderSystem::getFileModifiedTime(const std::string &filepath) { -#ifdef _WIN32 - struct _stat64 statBuf; - if (_stat64(filepath.c_str(), &statBuf) == 0) { - return static_cast(statBuf.st_mtime); - } -#else - struct stat statBuf; - if (stat(filepath.c_str(), &statBuf) == 0) { - return static_cast(statBuf.st_mtime); - } -#endif - return 0; -} - -// ============================================================================ -// ShaderParams实现 -// ============================================================================ - -ShaderParams::ShaderParams(GLShader &shader) : shader_(shader) {} - -ShaderParams &ShaderParams::setBool(const std::string &name, bool value) { - shader_.setBool(name, value); - return *this; -} - -ShaderParams &ShaderParams::setInt(const std::string &name, int value) { - shader_.setInt(name, value); - return *this; -} - -ShaderParams &ShaderParams::setFloat(const std::string &name, float value) { - shader_.setFloat(name, value); - return *this; -} - -ShaderParams &ShaderParams::setVec2(const std::string &name, - const glm::vec2 &value) { - shader_.setVec2(name, value); - return *this; -} - -ShaderParams &ShaderParams::setVec3(const std::string &name, - const glm::vec3 &value) { - shader_.setVec3(name, value); - return *this; -} - -ShaderParams &ShaderParams::setVec4(const std::string &name, - const glm::vec4 &value) { - shader_.setVec4(name, value); - return *this; -} - -ShaderParams &ShaderParams::setMat4(const std::string &name, - const glm::mat4 &value) { - shader_.setMat4(name, value); - return *this; -} - -ShaderParams &ShaderParams::setColor(const std::string &name, - const Color &color) { - shader_.setVec4(name, glm::vec4(color.r, color.g, color.b, color.a)); - return *this; -} - -} // namespace extra2d