#include #include #include #include #include #include #ifdef _WIN32 #include #endif namespace easy2d { // ============================================================================ // 内置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 easy2d