From 867013f6ebc397a995894c1a9aa156bba92f9f66 Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Sun, 15 Feb 2026 16:24:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor(shader):=20=E5=90=88=E5=B9=B6GLShaderN?= =?UTF-8?q?ew=E5=88=B0GLShader=E5=B9=B6=E4=BC=98=E5=8C=96=E7=9D=80?= =?UTF-8?q?=E8=89=B2=E5=99=A8=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除GLShaderNew类,将其功能合并到GLShader中 - 增加着色器缓存保存时的空二进制检查 - 添加更多调试日志信息 - 优化二进制数据获取的错误处理 --- .../extra2d/graphics/opengl/gl_shader.h | 203 ++++++++-- .../extra2d/graphics/opengl/gl_shader_new.h | 202 ---------- Extra2D/src/graphics/opengl/gl_shader.cpp | 373 ++++++++++++------ Extra2D/src/graphics/opengl/gl_shader_new.cpp | 325 --------------- Extra2D/src/graphics/render_module.cpp | 2 +- Extra2D/src/graphics/shader_cache.cpp | 10 +- Extra2D/src/graphics/shader_manager.cpp | 8 + 7 files changed, 451 insertions(+), 672 deletions(-) delete mode 100644 Extra2D/include/extra2d/graphics/opengl/gl_shader_new.h delete mode 100644 Extra2D/src/graphics/opengl/gl_shader_new.cpp diff --git a/Extra2D/include/extra2d/graphics/opengl/gl_shader.h b/Extra2D/include/extra2d/graphics/opengl/gl_shader.h index 2f63818..3b01db1 100644 --- a/Extra2D/include/extra2d/graphics/opengl/gl_shader.h +++ b/Extra2D/include/extra2d/graphics/opengl/gl_shader.h @@ -1,55 +1,196 @@ #pragma once +#include +#include #include - -#include #include -#include -#include -#include -#include +#include namespace extra2d { -// ============================================================================ -// OpenGL Shader 程序 -// ============================================================================ -class GLShader { +class GLShader : public IShader { public: + /** + * @brief 构造函数 + */ GLShader(); - ~GLShader(); - // 从源码编译 + /** + * @brief 析构函数 + */ + ~GLShader() override; + + /** + * @brief 绑定Shader程序 + */ + void bind() const override; + + /** + * @brief 解绑Shader程序 + */ + void unbind() const override; + + /** + * @brief 设置布尔类型uniform变量 + * @param name uniform变量名 + * @param value 布尔值 + */ + void setBool(const std::string& name, bool value) override; + + /** + * @brief 设置整数类型uniform变量 + * @param name uniform变量名 + * @param value 整数值 + */ + void setInt(const std::string& name, int value) override; + + /** + * @brief 设置浮点类型uniform变量 + * @param name uniform变量名 + * @param value 浮点值 + */ + void setFloat(const std::string& name, float value) override; + + /** + * @brief 设置二维向量类型uniform变量 + * @param name uniform变量名 + * @param value 二维向量值 + */ + void setVec2(const std::string& name, const glm::vec2& value) override; + + /** + * @brief 设置三维向量类型uniform变量 + * @param name uniform变量名 + * @param value 三维向量值 + */ + void setVec3(const std::string& name, const glm::vec3& value) override; + + /** + * @brief 设置四维向量类型uniform变量 + * @param name uniform变量名 + * @param value 四维向量值 + */ + void setVec4(const std::string& name, const glm::vec4& value) override; + + /** + * @brief 设置4x4矩阵类型uniform变量 + * @param name uniform变量名 + * @param value 4x4矩阵值 + */ + void setMat4(const std::string& name, const glm::mat4& value) override; + + /** + * @brief 设置颜色类型uniform变量 + * @param name uniform变量名 + * @param color 颜色值 + */ + void setColor(const std::string& name, const Color& color) override; + + /** + * @brief 检查Shader是否有效 + * @return 有效返回true,否则返回false + */ + bool isValid() const override { return programID_ != 0; } + + /** + * @brief 获取原生句柄(OpenGL程序ID) + * @return OpenGL程序ID + */ + uint32_t getNativeHandle() const override { return programID_; } + + /** + * @brief 获取Shader名称 + * @return Shader名称 + */ + const std::string& getName() const override { return name_; } + + /** + * @brief 设置Shader名称 + * @param name Shader名称 + */ + void setName(const std::string& name) override { name_ = name; } + + /** + * @brief 从源码编译Shader + * @param vertexSource 顶点着色器源码 + * @param fragmentSource 片段着色器源码 + * @return 编译成功返回true,失败返回false + */ bool compileFromSource(const char* vertexSource, const char* fragmentSource); - - // 从文件加载并编译 - bool compileFromFile(const std::string& vertexPath, const std::string& fragmentPath); - // 使用/激活 - void bind() const; - void unbind() const; + /** + * @brief 从二进制数据创建Shader + * @param binary 二进制数据 + * @return 创建成功返回true,失败返回false + */ + bool compileFromBinary(const std::vector& binary); - // Uniform 设置 - void setBool(const std::string& name, bool value); - void setInt(const std::string& name, int value); - void setFloat(const std::string& name, float value); - void setVec2(const std::string& name, const glm::vec2& value); - void setVec3(const std::string& name, const glm::vec3& value); - void setVec4(const std::string& name, const glm::vec4& value); - void setMat4(const std::string& name, const glm::mat4& value); + /** + * @brief 获取Shader二进制数据 + * @param outBinary 输出的二进制数据 + * @return 成功返回true,失败返回false + */ + bool getBinary(std::vector& outBinary); - // 获取程序 ID + /** + * @brief 获取OpenGL程序ID + * @return OpenGL程序ID + */ GLuint getProgramID() const { return programID_; } - // 检查是否有效 - bool isValid() const { return programID_ != 0; } - private: - GLuint programID_; + GLuint programID_ = 0; + std::string name_; std::unordered_map uniformCache_; + /** + * @brief 编译单个着色器 + * @param type 着色器类型 + * @param source 着色器源码 + * @return 着色器ID,失败返回0 + */ GLuint compileShader(GLenum type, const char* source); + + /** + * @brief 获取uniform位置 + * @param name uniform变量名 + * @return uniform位置 + */ GLint getUniformLocation(const std::string& name); }; +class GLShaderFactory : public IShaderFactory { +public: + /** + * @brief 从源码创建Shader + * @param name Shader名称 + * @param vertSource 顶点着色器源码 + * @param fragSource 片段着色器源码 + * @return 创建的Shader实例 + */ + Ptr createFromSource( + const std::string& name, + const std::string& vertSource, + const std::string& fragSource) override; + + /** + * @brief 从缓存二进制创建Shader + * @param name Shader名称 + * @param binary 编译后的二进制数据 + * @return 创建的Shader实例 + */ + Ptr createFromBinary( + const std::string& name, + const std::vector& binary) override; + + /** + * @brief 获取Shader的二进制数据 + * @param shader Shader实例 + * @param outBinary 输出的二进制数据 + * @return 成功返回true,失败返回false + */ + bool getShaderBinary(const IShader& shader, + std::vector& outBinary) override; +}; + } // namespace extra2d diff --git a/Extra2D/include/extra2d/graphics/opengl/gl_shader_new.h b/Extra2D/include/extra2d/graphics/opengl/gl_shader_new.h deleted file mode 100644 index a832af8..0000000 --- a/Extra2D/include/extra2d/graphics/opengl/gl_shader_new.h +++ /dev/null @@ -1,202 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace extra2d { - -// ============================================================================ -// OpenGL Shader实现 -// ============================================================================ -class GLShaderNew : public IShader { -public: - /** - * @brief 构造函数 - */ - GLShaderNew(); - - /** - * @brief 析构函数 - */ - ~GLShaderNew() override; - - /** - * @brief 绑定Shader程序 - */ - void bind() const override; - - /** - * @brief 解绑Shader程序 - */ - void unbind() const override; - - /** - * @brief 设置布尔类型uniform变量 - * @param name uniform变量名 - * @param value 布尔值 - */ - void setBool(const std::string& name, bool value) override; - - /** - * @brief 设置整数类型uniform变量 - * @param name uniform变量名 - * @param value 整数值 - */ - void setInt(const std::string& name, int value) override; - - /** - * @brief 设置浮点类型uniform变量 - * @param name uniform变量名 - * @param value 浮点值 - */ - void setFloat(const std::string& name, float value) override; - - /** - * @brief 设置二维向量类型uniform变量 - * @param name uniform变量名 - * @param value 二维向量值 - */ - void setVec2(const std::string& name, const glm::vec2& value) override; - - /** - * @brief 设置三维向量类型uniform变量 - * @param name uniform变量名 - * @param value 三维向量值 - */ - void setVec3(const std::string& name, const glm::vec3& value) override; - - /** - * @brief 设置四维向量类型uniform变量 - * @param name uniform变量名 - * @param value 四维向量值 - */ - void setVec4(const std::string& name, const glm::vec4& value) override; - - /** - * @brief 设置4x4矩阵类型uniform变量 - * @param name uniform变量名 - * @param value 4x4矩阵值 - */ - void setMat4(const std::string& name, const glm::mat4& value) override; - - /** - * @brief 设置颜色类型uniform变量 - * @param name uniform变量名 - * @param color 颜色值 - */ - void setColor(const std::string& name, const Color& color) override; - - /** - * @brief 检查Shader是否有效 - * @return 有效返回true,否则返回false - */ - bool isValid() const override { return programID_ != 0; } - - /** - * @brief 获取原生句柄(OpenGL程序ID) - * @return OpenGL程序ID - */ - uint32_t getNativeHandle() const override { return programID_; } - - /** - * @brief 获取Shader名称 - * @return Shader名称 - */ - const std::string& getName() const override { return name_; } - - /** - * @brief 设置Shader名称 - * @param name Shader名称 - */ - void setName(const std::string& name) override { name_ = name; } - - /** - * @brief 从源码编译Shader - * @param vertexSource 顶点着色器源码 - * @param fragmentSource 片段着色器源码 - * @return 编译成功返回true,失败返回false - */ - bool compileFromSource(const char* vertexSource, const char* fragmentSource); - - /** - * @brief 从二进制数据创建Shader - * @param binary 二进制数据 - * @return 创建成功返回true,失败返回false - */ - bool compileFromBinary(const std::vector& binary); - - /** - * @brief 获取Shader二进制数据 - * @param outBinary 输出的二进制数据 - * @return 成功返回true,失败返回false - */ - bool getBinary(std::vector& outBinary); - - /** - * @brief 获取OpenGL程序ID - * @return OpenGL程序ID - */ - GLuint getProgramID() const { return programID_; } - -private: - GLuint programID_ = 0; - std::string name_; - std::unordered_map uniformCache_; - - /** - * @brief 编译单个着色器 - * @param type 着色器类型 - * @param source 着色器源码 - * @return 着色器ID,失败返回0 - */ - GLuint compileShader(GLenum type, const char* source); - - /** - * @brief 获取uniform位置 - * @param name uniform变量名 - * @return uniform位置 - */ - GLint getUniformLocation(const std::string& name); -}; - -// ============================================================================ -// OpenGL Shader工厂 -// ============================================================================ -class GLShaderFactory : public IShaderFactory { -public: - /** - * @brief 从源码创建Shader - * @param name Shader名称 - * @param vertSource 顶点着色器源码 - * @param fragSource 片段着色器源码 - * @return 创建的Shader实例 - */ - Ptr createFromSource( - const std::string& name, - const std::string& vertSource, - const std::string& fragSource) override; - - /** - * @brief 从缓存二进制创建Shader - * @param name Shader名称 - * @param binary 编译后的二进制数据 - * @return 创建的Shader实例 - */ - Ptr createFromBinary( - const std::string& name, - const std::vector& binary) override; - - /** - * @brief 获取Shader的二进制数据 - * @param shader Shader实例 - * @param outBinary 输出的二进制数据 - * @return 成功返回true,失败返回false - */ - bool getShaderBinary(const IShader& shader, - std::vector& outBinary) override; -}; - -} // namespace extra2d diff --git a/Extra2D/src/graphics/opengl/gl_shader.cpp b/Extra2D/src/graphics/opengl/gl_shader.cpp index fa8bb2f..16b839e 100644 --- a/Extra2D/src/graphics/opengl/gl_shader.cpp +++ b/Extra2D/src/graphics/opengl/gl_shader.cpp @@ -1,105 +1,45 @@ #include #include -#include -#include namespace extra2d { /** * @brief 构造函数,初始化着色器程序ID为0 */ -GLShader::GLShader() : programID_(0) {} +GLShader::GLShader() : programID_(0) { +} /** * @brief 析构函数,删除OpenGL着色器程序 */ GLShader::~GLShader() { - if (programID_ != 0) { - glDeleteProgram(programID_); - } + if (programID_ != 0) { + glDeleteProgram(programID_); + programID_ = 0; + } } /** - * @brief 从源代码编译着色器程序 - * @param vertexSource 顶点着色器源代码 - * @param fragmentSource 片段着色器源代码 - * @return 编译成功返回true,失败返回false + * @brief 绑定Shader程序 */ -bool GLShader::compileFromSource(const char *vertexSource, - const char *fragmentSource) { - GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource); - if (vertexShader == 0) - return false; - - GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource); - if (fragmentShader == 0) { - glDeleteShader(vertexShader); - return false; - } - - programID_ = glCreateProgram(); - glAttachShader(programID_, vertexShader); - glAttachShader(programID_, fragmentShader); - glLinkProgram(programID_); - - GLint success; - glGetProgramiv(programID_, GL_LINK_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetProgramInfoLog(programID_, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader program linking failed: {}", infoLog); - glDeleteProgram(programID_); - programID_ = 0; - } - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - return success == GL_TRUE; +void GLShader::bind() const { + glUseProgram(programID_); } /** - * @brief 从文件编译着色器程序 - * @param vertexPath 顶点着色器文件路径 - * @param fragmentPath 片段着色器文件路径 - * @return 编译成功返回true,失败返回false + * @brief 解绑Shader程序 */ -bool GLShader::compileFromFile(const std::string &vertexPath, - const std::string &fragmentPath) { - std::ifstream vShaderFile(vertexPath); - std::ifstream fShaderFile(fragmentPath); - - if (!vShaderFile.is_open() || !fShaderFile.is_open()) { - E2D_LOG_ERROR("Failed to open shader files: {}, {}", vertexPath, - fragmentPath); - return false; - } - - std::stringstream vShaderStream, fShaderStream; - vShaderStream << vShaderFile.rdbuf(); - fShaderStream << fShaderFile.rdbuf(); - - return compileFromSource(vShaderStream.str().c_str(), - fShaderStream.str().c_str()); +void GLShader::unbind() const { + glUseProgram(0); } -/** - * @brief 绑定(使用)当前着色器程序 - */ -void GLShader::bind() const { glUseProgram(programID_); } - -/** - * @brief 解绑当前着色器程序 - */ -void GLShader::unbind() const { glUseProgram(0); } - /** * @brief 设置布尔类型uniform变量 * @param name uniform变量名 * @param value 布尔值 */ -void GLShader::setBool(const std::string &name, bool value) { - glUniform1i(getUniformLocation(name), value ? 1 : 0); +void GLShader::setBool(const std::string& name, bool value) { + glUniform1i(getUniformLocation(name), value ? 1 : 0); } /** @@ -107,8 +47,8 @@ void GLShader::setBool(const std::string &name, bool value) { * @param name uniform变量名 * @param value 整数值 */ -void GLShader::setInt(const std::string &name, int value) { - glUniform1i(getUniformLocation(name), value); +void GLShader::setInt(const std::string& name, int value) { + glUniform1i(getUniformLocation(name), value); } /** @@ -116,8 +56,8 @@ void GLShader::setInt(const std::string &name, int value) { * @param name uniform变量名 * @param value 浮点值 */ -void GLShader::setFloat(const std::string &name, float value) { - glUniform1f(getUniformLocation(name), value); +void GLShader::setFloat(const std::string& name, float value) { + glUniform1f(getUniformLocation(name), value); } /** @@ -125,8 +65,8 @@ void GLShader::setFloat(const std::string &name, float value) { * @param name uniform变量名 * @param value 二维向量值 */ -void GLShader::setVec2(const std::string &name, const glm::vec2 &value) { - glUniform2fv(getUniformLocation(name), 1, &value[0]); +void GLShader::setVec2(const std::string& name, const glm::vec2& value) { + glUniform2fv(getUniformLocation(name), 1, &value[0]); } /** @@ -134,8 +74,8 @@ void GLShader::setVec2(const std::string &name, const glm::vec2 &value) { * @param name uniform变量名 * @param value 三维向量值 */ -void GLShader::setVec3(const std::string &name, const glm::vec3 &value) { - glUniform3fv(getUniformLocation(name), 1, &value[0]); +void GLShader::setVec3(const std::string& name, const glm::vec3& value) { + glUniform3fv(getUniformLocation(name), 1, &value[0]); } /** @@ -143,8 +83,8 @@ void GLShader::setVec3(const std::string &name, const glm::vec3 &value) { * @param name uniform变量名 * @param value 四维向量值 */ -void GLShader::setVec4(const std::string &name, const glm::vec4 &value) { - glUniform4fv(getUniformLocation(name), 1, &value[0]); +void GLShader::setVec4(const std::string& name, const glm::vec4& value) { + glUniform4fv(getUniformLocation(name), 1, &value[0]); } /** @@ -152,48 +92,257 @@ void GLShader::setVec4(const std::string &name, const glm::vec4 &value) { * @param name uniform变量名 * @param value 4x4矩阵值 */ -void GLShader::setMat4(const std::string &name, const glm::mat4 &value) { - glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &value[0][0]); +void GLShader::setMat4(const std::string& name, const glm::mat4& value) { + glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &value[0][0]); +} + +/** + * @brief 设置颜色类型uniform变量 + * @param name uniform变量名 + * @param color 颜色值 + */ +void GLShader::setColor(const std::string& name, const Color& color) { + glUniform4f(getUniformLocation(name), color.r, color.g, color.b, color.a); +} + +/** + * @brief 从源码编译Shader + * @param vertexSource 顶点着色器源码 + * @param fragmentSource 片段着色器源码 + * @return 编译成功返回true,失败返回false + */ +bool GLShader::compileFromSource(const char* vertexSource, const char* fragmentSource) { + GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource); + if (vertexShader == 0) { + return false; + } + + GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource); + if (fragmentShader == 0) { + glDeleteShader(vertexShader); + return false; + } + + if (programID_ != 0) { + glDeleteProgram(programID_); + uniformCache_.clear(); + } + + programID_ = glCreateProgram(); + glAttachShader(programID_, vertexShader); + glAttachShader(programID_, fragmentShader); + glLinkProgram(programID_); + + GLint success; + glGetProgramiv(programID_, GL_LINK_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetProgramInfoLog(programID_, 512, nullptr, infoLog); + E2D_LOG_ERROR("Shader program linking failed: {}", infoLog); + glDeleteProgram(programID_); + programID_ = 0; + } + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + return success == GL_TRUE; +} + +/** + * @brief 从二进制数据创建Shader + * @param binary 二进制数据 + * @return 创建成功返回true,失败返回false + */ +bool GLShader::compileFromBinary(const std::vector& binary) { + if (binary.empty()) { + E2D_LOG_ERROR("Binary data is empty"); + return false; + } + + GLint numFormats = 0; + glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numFormats); + if (numFormats == 0) { + E2D_LOG_ERROR("Program binary formats not supported"); + return false; + } + + if (programID_ != 0) { + glDeleteProgram(programID_); + uniformCache_.clear(); + } + + programID_ = glCreateProgram(); + + GLenum binaryFormat = 0; + glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, reinterpret_cast(&binaryFormat)); + + glProgramBinary(programID_, binaryFormat, binary.data(), static_cast(binary.size())); + + GLint success = 0; + glGetProgramiv(programID_, GL_LINK_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetProgramInfoLog(programID_, 512, nullptr, infoLog); + E2D_LOG_ERROR("Failed to load shader from binary: {}", infoLog); + glDeleteProgram(programID_); + programID_ = 0; + return false; + } + + return true; +} + +/** + * @brief 获取Shader二进制数据 + * @param outBinary 输出的二进制数据 + * @return 成功返回true,失败返回false + */ +bool GLShader::getBinary(std::vector& outBinary) { + if (programID_ == 0) { + E2D_LOG_WARN("Cannot get binary: shader program is 0"); + return false; + } + + GLint binaryLength = 0; + glGetProgramiv(programID_, GL_PROGRAM_BINARY_LENGTH, &binaryLength); + + E2D_LOG_DEBUG("Shader binary length: {}", binaryLength); + + if (binaryLength <= 0) { + E2D_LOG_WARN("Shader binary length is 0 or negative"); + return false; + } + + outBinary.resize(binaryLength); + + GLenum binaryFormat = 0; + GLsizei actualLength = 0; + glGetProgramBinary(programID_, binaryLength, &actualLength, &binaryFormat, outBinary.data()); + + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + E2D_LOG_ERROR("glGetProgramBinary failed with error: {}", err); + outBinary.clear(); + return false; + } + + if (actualLength == 0) { + E2D_LOG_WARN("glGetProgramBinary returned 0 bytes"); + outBinary.clear(); + return false; + } + + if (actualLength != binaryLength) { + outBinary.resize(actualLength); + } + + E2D_LOG_DEBUG("Shader binary retrieved: {} bytes, format: {}", actualLength, binaryFormat); + return true; } /** * @brief 编译单个着色器 - * @param type 着色器类型(GL_VERTEX_SHADER或GL_FRAGMENT_SHADER) - * @param source 着色器源代码 - * @return 编译成功返回着色器ID,失败返回0 + * @param type 着色器类型 + * @param source 着色器源码 + * @return 着色器ID,失败返回0 */ -GLuint GLShader::compileShader(GLenum type, const char *source) { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, nullptr); - glCompileShader(shader); +GLuint GLShader::compileShader(GLenum type, const char* source) { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, nullptr); + glCompileShader(shader); - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetShaderInfoLog(shader, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader compilation failed: {}", infoLog); - glDeleteShader(shader); - return 0; - } + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetShaderInfoLog(shader, 512, nullptr, infoLog); + E2D_LOG_ERROR("Shader compilation failed: {}", infoLog); + glDeleteShader(shader); + return 0; + } - return shader; + return shader; } /** - * @brief 获取uniform变量位置,使用缓存避免重复查询 + * @brief 获取uniform位置 * @param name uniform变量名 * @return uniform位置 */ -GLint GLShader::getUniformLocation(const std::string &name) { - auto it = uniformCache_.find(name); - if (it != uniformCache_.end()) { - return it->second; - } +GLint GLShader::getUniformLocation(const std::string& name) { + auto it = uniformCache_.find(name); + if (it != uniformCache_.end()) { + return it->second; + } - GLint location = glGetUniformLocation(programID_, name.c_str()); - uniformCache_[name] = location; - return location; + GLint location = glGetUniformLocation(programID_, name.c_str()); + uniformCache_[name] = location; + return location; +} + +// ============================================================================ +// GLShaderFactory 实现 +// ============================================================================ + +/** + * @brief 从源码创建Shader + * @param name Shader名称 + * @param vertSource 顶点着色器源码 + * @param fragSource 片段着色器源码 + * @return 创建的Shader实例 + */ +Ptr GLShaderFactory::createFromSource( + const std::string& name, + const std::string& vertSource, + const std::string& fragSource) { + + auto shader = std::make_shared(); + shader->setName(name); + + if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) { + E2D_LOG_ERROR("Failed to compile shader from source: {}", name); + return nullptr; + } + + return shader; +} + +/** + * @brief 从缓存二进制创建Shader + * @param name Shader名称 + * @param binary 编译后的二进制数据 + * @return 创建的Shader实例 + */ +Ptr GLShaderFactory::createFromBinary( + const std::string& name, + const std::vector& binary) { + + auto shader = std::make_shared(); + shader->setName(name); + + if (!shader->compileFromBinary(binary)) { + E2D_LOG_ERROR("Failed to create shader from binary: {}", name); + return nullptr; + } + + return shader; +} + +/** + * @brief 获取Shader的二进制数据 + * @param shader Shader实例 + * @param outBinary 输出的二进制数据 + * @return 成功返回true,失败返回false + */ +bool GLShaderFactory::getShaderBinary(const IShader& shader, std::vector& outBinary) { + const GLShader* glShader = dynamic_cast(&shader); + if (!glShader) { + E2D_LOG_ERROR("Shader is not a GLShader instance"); + return false; + } + + return const_cast(glShader)->getBinary(outBinary); } } // namespace extra2d diff --git a/Extra2D/src/graphics/opengl/gl_shader_new.cpp b/Extra2D/src/graphics/opengl/gl_shader_new.cpp deleted file mode 100644 index 2ca141c..0000000 --- a/Extra2D/src/graphics/opengl/gl_shader_new.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include -#include - -namespace extra2d { - -/** - * @brief 构造函数,初始化着色器程序ID为0 - */ -GLShaderNew::GLShaderNew() : programID_(0) { -} - -/** - * @brief 析构函数,删除OpenGL着色器程序 - */ -GLShaderNew::~GLShaderNew() { - if (programID_ != 0) { - glDeleteProgram(programID_); - programID_ = 0; - } -} - -/** - * @brief 绑定Shader程序 - */ -void GLShaderNew::bind() const { - glUseProgram(programID_); -} - -/** - * @brief 解绑Shader程序 - */ -void GLShaderNew::unbind() const { - glUseProgram(0); -} - -/** - * @brief 设置布尔类型uniform变量 - * @param name uniform变量名 - * @param value 布尔值 - */ -void GLShaderNew::setBool(const std::string& name, bool value) { - glUniform1i(getUniformLocation(name), value ? 1 : 0); -} - -/** - * @brief 设置整数类型uniform变量 - * @param name uniform变量名 - * @param value 整数值 - */ -void GLShaderNew::setInt(const std::string& name, int value) { - glUniform1i(getUniformLocation(name), value); -} - -/** - * @brief 设置浮点类型uniform变量 - * @param name uniform变量名 - * @param value 浮点值 - */ -void GLShaderNew::setFloat(const std::string& name, float value) { - glUniform1f(getUniformLocation(name), value); -} - -/** - * @brief 设置二维向量类型uniform变量 - * @param name uniform变量名 - * @param value 二维向量值 - */ -void GLShaderNew::setVec2(const std::string& name, const glm::vec2& value) { - glUniform2fv(getUniformLocation(name), 1, &value[0]); -} - -/** - * @brief 设置三维向量类型uniform变量 - * @param name uniform变量名 - * @param value 三维向量值 - */ -void GLShaderNew::setVec3(const std::string& name, const glm::vec3& value) { - glUniform3fv(getUniformLocation(name), 1, &value[0]); -} - -/** - * @brief 设置四维向量类型uniform变量 - * @param name uniform变量名 - * @param value 四维向量值 - */ -void GLShaderNew::setVec4(const std::string& name, const glm::vec4& value) { - glUniform4fv(getUniformLocation(name), 1, &value[0]); -} - -/** - * @brief 设置4x4矩阵类型uniform变量 - * @param name uniform变量名 - * @param value 4x4矩阵值 - */ -void GLShaderNew::setMat4(const std::string& name, const glm::mat4& value) { - glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &value[0][0]); -} - -/** - * @brief 设置颜色类型uniform变量 - * @param name uniform变量名 - * @param color 颜色值 - */ -void GLShaderNew::setColor(const std::string& name, const Color& color) { - glUniform4f(getUniformLocation(name), color.r, color.g, color.b, color.a); -} - -/** - * @brief 从源码编译Shader - * @param vertexSource 顶点着色器源码 - * @param fragmentSource 片段着色器源码 - * @return 编译成功返回true,失败返回false - */ -bool GLShaderNew::compileFromSource(const char* vertexSource, const char* fragmentSource) { - GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource); - if (vertexShader == 0) { - return false; - } - - GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource); - if (fragmentShader == 0) { - glDeleteShader(vertexShader); - return false; - } - - if (programID_ != 0) { - glDeleteProgram(programID_); - uniformCache_.clear(); - } - - programID_ = glCreateProgram(); - glAttachShader(programID_, vertexShader); - glAttachShader(programID_, fragmentShader); - glLinkProgram(programID_); - - GLint success; - glGetProgramiv(programID_, GL_LINK_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetProgramInfoLog(programID_, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader program linking failed: {}", infoLog); - glDeleteProgram(programID_); - programID_ = 0; - } - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - return success == GL_TRUE; -} - -/** - * @brief 从二进制数据创建Shader - * @param binary 二进制数据 - * @return 创建成功返回true,失败返回false - */ -bool GLShaderNew::compileFromBinary(const std::vector& binary) { - if (binary.empty()) { - E2D_LOG_ERROR("Binary data is empty"); - return false; - } - - GLint numFormats = 0; - glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numFormats); - if (numFormats == 0) { - E2D_LOG_ERROR("Program binary formats not supported"); - return false; - } - - if (programID_ != 0) { - glDeleteProgram(programID_); - uniformCache_.clear(); - } - - programID_ = glCreateProgram(); - - GLenum binaryFormat = 0; - glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, reinterpret_cast(&binaryFormat)); - - glProgramBinary(programID_, binaryFormat, binary.data(), static_cast(binary.size())); - - GLint success = 0; - glGetProgramiv(programID_, GL_LINK_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetProgramInfoLog(programID_, 512, nullptr, infoLog); - E2D_LOG_ERROR("Failed to load shader from binary: {}", infoLog); - glDeleteProgram(programID_); - programID_ = 0; - return false; - } - - return true; -} - -/** - * @brief 获取Shader二进制数据 - * @param outBinary 输出的二进制数据 - * @return 成功返回true,失败返回false - */ -bool GLShaderNew::getBinary(std::vector& outBinary) { - if (programID_ == 0) { - return false; - } - - GLint binaryLength = 0; - glGetProgramiv(programID_, GL_PROGRAM_BINARY_LENGTH, &binaryLength); - - if (binaryLength <= 0) { - return false; - } - - outBinary.resize(binaryLength); - - GLenum binaryFormat = 0; - glGetProgramBinary(programID_, binaryLength, nullptr, &binaryFormat, outBinary.data()); - - return true; -} - -/** - * @brief 编译单个着色器 - * @param type 着色器类型 - * @param source 着色器源码 - * @return 着色器ID,失败返回0 - */ -GLuint GLShaderNew::compileShader(GLenum type, const char* source) { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, nullptr); - glCompileShader(shader); - - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetShaderInfoLog(shader, 512, nullptr, infoLog); - E2D_LOG_ERROR("Shader compilation failed: {}", infoLog); - glDeleteShader(shader); - return 0; - } - - return shader; -} - -/** - * @brief 获取uniform位置 - * @param name uniform变量名 - * @return uniform位置 - */ -GLint GLShaderNew::getUniformLocation(const std::string& name) { - auto it = uniformCache_.find(name); - if (it != uniformCache_.end()) { - return it->second; - } - - GLint location = glGetUniformLocation(programID_, name.c_str()); - uniformCache_[name] = location; - return location; -} - -// ============================================================================ -// GLShaderFactory 实现 -// ============================================================================ - -/** - * @brief 从源码创建Shader - * @param name Shader名称 - * @param vertSource 顶点着色器源码 - * @param fragSource 片段着色器源码 - * @return 创建的Shader实例 - */ -Ptr GLShaderFactory::createFromSource( - const std::string& name, - const std::string& vertSource, - const std::string& fragSource) { - - auto shader = std::make_shared(); - shader->setName(name); - - if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) { - E2D_LOG_ERROR("Failed to compile shader from source: {}", name); - return nullptr; - } - - return shader; -} - -/** - * @brief 从缓存二进制创建Shader - * @param name Shader名称 - * @param binary 编译后的二进制数据 - * @return 创建的Shader实例 - */ -Ptr GLShaderFactory::createFromBinary( - const std::string& name, - const std::vector& binary) { - - auto shader = std::make_shared(); - shader->setName(name); - - if (!shader->compileFromBinary(binary)) { - E2D_LOG_ERROR("Failed to create shader from binary: {}", name); - return nullptr; - } - - return shader; -} - -/** - * @brief 获取Shader的二进制数据 - * @param shader Shader实例 - * @param outBinary 输出的二进制数据 - * @return 成功返回true,失败返回false - */ -bool GLShaderFactory::getShaderBinary(const IShader& shader, std::vector& outBinary) { - const GLShaderNew* glShader = dynamic_cast(&shader); - if (!glShader) { - E2D_LOG_ERROR("Shader is not a GLShaderNew instance"); - return false; - } - - return const_cast(glShader)->getBinary(outBinary); -} - -} // namespace extra2d diff --git a/Extra2D/src/graphics/render_module.cpp b/Extra2D/src/graphics/render_module.cpp index 7fa96bb..11b9ad3 100644 --- a/Extra2D/src/graphics/render_module.cpp +++ b/Extra2D/src/graphics/render_module.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/Extra2D/src/graphics/shader_cache.cpp b/Extra2D/src/graphics/shader_cache.cpp index 1ead6a9..b77c61d 100644 --- a/Extra2D/src/graphics/shader_cache.cpp +++ b/Extra2D/src/graphics/shader_cache.cpp @@ -107,10 +107,18 @@ Ptr ShaderCache::loadCache(const std::string& name) { */ bool ShaderCache::saveCache(const ShaderCacheEntry& entry) { if (!initialized_) { + E2D_LOG_WARN("ShaderCache not initialized, cannot save cache"); + return false; + } + + if (entry.binary.empty()) { + E2D_LOG_WARN("Shader binary is empty, skipping cache save for: {}", entry.name); return false; } std::string cachePath = getCachePath(entry.name); + E2D_LOG_DEBUG("Saving shader cache to: {} ({} bytes)", cachePath, entry.binary.size()); + std::ofstream file(cachePath, std::ios::binary); if (!file.is_open()) { E2D_LOG_ERROR("Failed to create cache file: {}", cachePath); @@ -123,7 +131,7 @@ bool ShaderCache::saveCache(const ShaderCacheEntry& entry) { cacheMap_[entry.name] = entry; saveCacheIndex(); - E2D_LOG_DEBUG("Shader cache saved: {}", entry.name); + E2D_LOG_INFO("Shader cache saved: {} ({} bytes)", entry.name, entry.binary.size()); return true; } diff --git a/Extra2D/src/graphics/shader_manager.cpp b/Extra2D/src/graphics/shader_manager.cpp index 7d95d70..b15552d 100644 --- a/Extra2D/src/graphics/shader_manager.cpp +++ b/Extra2D/src/graphics/shader_manager.cpp @@ -135,6 +135,7 @@ Ptr ShaderManager::loadFromFiles(const std::string& name, Ptr shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource); if (!shader) { + E2D_LOG_DEBUG("No valid cache found, compiling shader from source: {}", name); shader = factory_->createFromSource(name, result.vertSource, result.fragSource); if (!shader) { E2D_LOG_ERROR("Failed to create shader from source: {}", name); @@ -143,12 +144,15 @@ Ptr ShaderManager::loadFromFiles(const std::string& name, std::vector binary; if (factory_->getShaderBinary(*shader, binary)) { + E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size()); ShaderCacheEntry entry; entry.name = name; entry.sourceHash = sourceHash; entry.binary = binary; entry.dependencies = result.dependencies; ShaderCache::getInstance().saveCache(entry); + } else { + E2D_LOG_WARN("Failed to get shader binary for: {}", name); } } @@ -205,6 +209,7 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string& path) { Ptr shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource); if (!shader) { + E2D_LOG_DEBUG("No valid cache found, compiling shader from source: {}", name); shader = factory_->createFromSource(name, result.vertSource, result.fragSource); if (!shader) { E2D_LOG_ERROR("Failed to create shader from source: {}", name); @@ -213,12 +218,15 @@ Ptr ShaderManager::loadFromCombinedFile(const std::string& path) { std::vector binary; if (factory_->getShaderBinary(*shader, binary)) { + E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size()); ShaderCacheEntry entry; entry.name = name; entry.sourceHash = sourceHash; entry.binary = binary; entry.dependencies = result.dependencies; ShaderCache::getInstance().saveCache(entry); + } else { + E2D_LOG_WARN("Failed to get shader binary for: {}", name); } }