refactor(shader): 合并GLShaderNew到GLShader并优化着色器缓存逻辑
- 删除GLShaderNew类,将其功能合并到GLShader中 - 增加着色器缓存保存时的空二进制检查 - 添加更多调试日志信息 - 优化二进制数据获取的错误处理
This commit is contained in:
parent
78680138c2
commit
867013f6eb
|
|
@ -1,55 +1,196 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <extra2d/core/color.h>
|
||||||
|
#include <extra2d/graphics/shader_interface.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <glm/mat4x4.hpp>
|
#include <vector>
|
||||||
#include <glm/vec2.hpp>
|
|
||||||
#include <glm/vec3.hpp>
|
|
||||||
#include <glm/vec4.hpp>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
// ============================================================================
|
class GLShader : public IShader {
|
||||||
// OpenGL Shader 程序
|
|
||||||
// ============================================================================
|
|
||||||
class GLShader {
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数
|
||||||
|
*/
|
||||||
GLShader();
|
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 compileFromSource(const char* vertexSource, const char* fragmentSource);
|
||||||
|
|
||||||
// 从文件加载并编译
|
/**
|
||||||
bool compileFromFile(const std::string& vertexPath, const std::string& fragmentPath);
|
* @brief 从二进制数据创建Shader
|
||||||
|
* @param binary 二进制数据
|
||||||
|
* @return 创建成功返回true,失败返回false
|
||||||
|
*/
|
||||||
|
bool compileFromBinary(const std::vector<uint8_t>& binary);
|
||||||
|
|
||||||
// 使用/激活
|
/**
|
||||||
void bind() const;
|
* @brief 获取Shader二进制数据
|
||||||
void unbind() const;
|
* @param outBinary 输出的二进制数据
|
||||||
|
* @return 成功返回true,失败返回false
|
||||||
|
*/
|
||||||
|
bool getBinary(std::vector<uint8_t>& outBinary);
|
||||||
|
|
||||||
// Uniform 设置
|
/**
|
||||||
void setBool(const std::string& name, bool value);
|
* @brief 获取OpenGL程序ID
|
||||||
void setInt(const std::string& name, int value);
|
* @return OpenGL程序ID
|
||||||
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);
|
|
||||||
|
|
||||||
// 获取程序 ID
|
|
||||||
GLuint getProgramID() const { return programID_; }
|
GLuint getProgramID() const { return programID_; }
|
||||||
|
|
||||||
// 检查是否有效
|
|
||||||
bool isValid() const { return programID_ != 0; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint programID_;
|
GLuint programID_ = 0;
|
||||||
|
std::string name_;
|
||||||
std::unordered_map<std::string, GLint> uniformCache_;
|
std::unordered_map<std::string, GLint> uniformCache_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 编译单个着色器
|
||||||
|
* @param type 着色器类型
|
||||||
|
* @param source 着色器源码
|
||||||
|
* @return 着色器ID,失败返回0
|
||||||
|
*/
|
||||||
GLuint compileShader(GLenum type, const char* source);
|
GLuint compileShader(GLenum type, const char* source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取uniform位置
|
||||||
|
* @param name uniform变量名
|
||||||
|
* @return uniform位置
|
||||||
|
*/
|
||||||
GLint getUniformLocation(const std::string& name);
|
GLint getUniformLocation(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GLShaderFactory : public IShaderFactory {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 从源码创建Shader
|
||||||
|
* @param name Shader名称
|
||||||
|
* @param vertSource 顶点着色器源码
|
||||||
|
* @param fragSource 片段着色器源码
|
||||||
|
* @return 创建的Shader实例
|
||||||
|
*/
|
||||||
|
Ptr<IShader> createFromSource(
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& vertSource,
|
||||||
|
const std::string& fragSource) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从缓存二进制创建Shader
|
||||||
|
* @param name Shader名称
|
||||||
|
* @param binary 编译后的二进制数据
|
||||||
|
* @return 创建的Shader实例
|
||||||
|
*/
|
||||||
|
Ptr<IShader> createFromBinary(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<uint8_t>& binary) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取Shader的二进制数据
|
||||||
|
* @param shader Shader实例
|
||||||
|
* @param outBinary 输出的二进制数据
|
||||||
|
* @return 成功返回true,失败返回false
|
||||||
|
*/
|
||||||
|
bool getShaderBinary(const IShader& shader,
|
||||||
|
std::vector<uint8_t>& outBinary) override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,202 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <extra2d/core/color.h>
|
|
||||||
#include <extra2d/graphics/shader_interface.h>
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
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<uint8_t>& binary);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取Shader二进制数据
|
|
||||||
* @param outBinary 输出的二进制数据
|
|
||||||
* @return 成功返回true,失败返回false
|
|
||||||
*/
|
|
||||||
bool getBinary(std::vector<uint8_t>& outBinary);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取OpenGL程序ID
|
|
||||||
* @return OpenGL程序ID
|
|
||||||
*/
|
|
||||||
GLuint getProgramID() const { return programID_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLuint programID_ = 0;
|
|
||||||
std::string name_;
|
|
||||||
std::unordered_map<std::string, GLint> 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<IShader> createFromSource(
|
|
||||||
const std::string& name,
|
|
||||||
const std::string& vertSource,
|
|
||||||
const std::string& fragSource) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从缓存二进制创建Shader
|
|
||||||
* @param name Shader名称
|
|
||||||
* @param binary 编译后的二进制数据
|
|
||||||
* @return 创建的Shader实例
|
|
||||||
*/
|
|
||||||
Ptr<IShader> createFromBinary(
|
|
||||||
const std::string& name,
|
|
||||||
const std::vector<uint8_t>& binary) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取Shader的二进制数据
|
|
||||||
* @param shader Shader实例
|
|
||||||
* @param outBinary 输出的二进制数据
|
|
||||||
* @return 成功返回true,失败返回false
|
|
||||||
*/
|
|
||||||
bool getShaderBinary(const IShader& shader,
|
|
||||||
std::vector<uint8_t>& outBinary) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#include <extra2d/graphics/opengl/gl_shader.h>
|
#include <extra2d/graphics/opengl/gl_shader.h>
|
||||||
#include <extra2d/utils/logger.h>
|
#include <extra2d/utils/logger.h>
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 构造函数,初始化着色器程序ID为0
|
* @brief 构造函数,初始化着色器程序ID为0
|
||||||
*/
|
*/
|
||||||
GLShader::GLShader() : programID_(0) {}
|
GLShader::GLShader() : programID_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 析构函数,删除OpenGL着色器程序
|
* @brief 析构函数,删除OpenGL着色器程序
|
||||||
|
|
@ -16,82 +15,23 @@ GLShader::GLShader() : programID_(0) {}
|
||||||
GLShader::~GLShader() {
|
GLShader::~GLShader() {
|
||||||
if (programID_ != 0) {
|
if (programID_ != 0) {
|
||||||
glDeleteProgram(programID_);
|
glDeleteProgram(programID_);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从源代码编译着色器程序
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
programID_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
|
|
||||||
return success == GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从文件编译着色器程序
|
* @brief 绑定Shader程序
|
||||||
* @param vertexPath 顶点着色器文件路径
|
|
||||||
* @param fragmentPath 片段着色器文件路径
|
|
||||||
* @return 编译成功返回true,失败返回false
|
|
||||||
*/
|
*/
|
||||||
bool GLShader::compileFromFile(const std::string &vertexPath,
|
void GLShader::bind() const {
|
||||||
const std::string &fragmentPath) {
|
glUseProgram(programID_);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绑定(使用)当前着色器程序
|
* @brief 解绑Shader程序
|
||||||
*/
|
*/
|
||||||
void GLShader::bind() const { glUseProgram(programID_); }
|
void GLShader::unbind() const {
|
||||||
|
glUseProgram(0);
|
||||||
/**
|
}
|
||||||
* @brief 解绑当前着色器程序
|
|
||||||
*/
|
|
||||||
void GLShader::unbind() const { glUseProgram(0); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置布尔类型uniform变量
|
* @brief 设置布尔类型uniform变量
|
||||||
|
|
@ -156,11 +96,156 @@ void GLShader::setMat4(const std::string &name, const glm::mat4 &value) {
|
||||||
glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &value[0][0]);
|
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<uint8_t>& 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<GLint*>(&binaryFormat));
|
||||||
|
|
||||||
|
glProgramBinary(programID_, binaryFormat, binary.data(), static_cast<GLsizei>(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<uint8_t>& 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 编译单个着色器
|
* @brief 编译单个着色器
|
||||||
* @param type 着色器类型(GL_VERTEX_SHADER或GL_FRAGMENT_SHADER)
|
* @param type 着色器类型
|
||||||
* @param source 着色器源代码
|
* @param source 着色器源码
|
||||||
* @return 编译成功返回着色器ID,失败返回0
|
* @return 着色器ID,失败返回0
|
||||||
*/
|
*/
|
||||||
GLuint GLShader::compileShader(GLenum type, const char* source) {
|
GLuint GLShader::compileShader(GLenum type, const char* source) {
|
||||||
GLuint shader = glCreateShader(type);
|
GLuint shader = glCreateShader(type);
|
||||||
|
|
@ -181,7 +266,7 @@ GLuint GLShader::compileShader(GLenum type, const char *source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取uniform变量位置,使用缓存避免重复查询
|
* @brief 获取uniform位置
|
||||||
* @param name uniform变量名
|
* @param name uniform变量名
|
||||||
* @return uniform位置
|
* @return uniform位置
|
||||||
*/
|
*/
|
||||||
|
|
@ -196,4 +281,68 @@ GLint GLShader::getUniformLocation(const std::string &name) {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// GLShaderFactory 实现
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从源码创建Shader
|
||||||
|
* @param name Shader名称
|
||||||
|
* @param vertSource 顶点着色器源码
|
||||||
|
* @param fragSource 片段着色器源码
|
||||||
|
* @return 创建的Shader实例
|
||||||
|
*/
|
||||||
|
Ptr<IShader> GLShaderFactory::createFromSource(
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& vertSource,
|
||||||
|
const std::string& fragSource) {
|
||||||
|
|
||||||
|
auto shader = std::make_shared<GLShader>();
|
||||||
|
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<IShader> GLShaderFactory::createFromBinary(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<uint8_t>& binary) {
|
||||||
|
|
||||||
|
auto shader = std::make_shared<GLShader>();
|
||||||
|
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<uint8_t>& outBinary) {
|
||||||
|
const GLShader* glShader = dynamic_cast<const GLShader*>(&shader);
|
||||||
|
if (!glShader) {
|
||||||
|
E2D_LOG_ERROR("Shader is not a GLShader instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return const_cast<GLShader*>(glShader)->getBinary(outBinary);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,325 +0,0 @@
|
||||||
#include <extra2d/graphics/opengl/gl_shader_new.h>
|
|
||||||
#include <extra2d/utils/logger.h>
|
|
||||||
|
|
||||||
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<uint8_t>& 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<GLint*>(&binaryFormat));
|
|
||||||
|
|
||||||
glProgramBinary(programID_, binaryFormat, binary.data(), static_cast<GLsizei>(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<uint8_t>& 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<IShader> GLShaderFactory::createFromSource(
|
|
||||||
const std::string& name,
|
|
||||||
const std::string& vertSource,
|
|
||||||
const std::string& fragSource) {
|
|
||||||
|
|
||||||
auto shader = std::make_shared<GLShaderNew>();
|
|
||||||
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<IShader> GLShaderFactory::createFromBinary(
|
|
||||||
const std::string& name,
|
|
||||||
const std::vector<uint8_t>& binary) {
|
|
||||||
|
|
||||||
auto shader = std::make_shared<GLShaderNew>();
|
|
||||||
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<uint8_t>& outBinary) {
|
|
||||||
const GLShaderNew* glShader = dynamic_cast<const GLShaderNew*>(&shader);
|
|
||||||
if (!glShader) {
|
|
||||||
E2D_LOG_ERROR("Shader is not a GLShaderNew instance");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return const_cast<GLShaderNew*>(glShader)->getBinary(outBinary);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <extra2d/graphics/render_module.h>
|
#include <extra2d/graphics/render_module.h>
|
||||||
#include <extra2d/config/module_registry.h>
|
#include <extra2d/config/module_registry.h>
|
||||||
#include <extra2d/graphics/opengl/gl_shader_new.h>
|
#include <extra2d/graphics/opengl/gl_shader.h>
|
||||||
#include <extra2d/graphics/shader_manager.h>
|
#include <extra2d/graphics/shader_manager.h>
|
||||||
#include <extra2d/platform/iwindow.h>
|
#include <extra2d/platform/iwindow.h>
|
||||||
#include <extra2d/utils/logger.h>
|
#include <extra2d/utils/logger.h>
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,18 @@ Ptr<ShaderCacheEntry> ShaderCache::loadCache(const std::string& name) {
|
||||||
*/
|
*/
|
||||||
bool ShaderCache::saveCache(const ShaderCacheEntry& entry) {
|
bool ShaderCache::saveCache(const ShaderCacheEntry& entry) {
|
||||||
if (!initialized_) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cachePath = getCachePath(entry.name);
|
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);
|
std::ofstream file(cachePath, std::ios::binary);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
E2D_LOG_ERROR("Failed to create cache file: {}", cachePath);
|
E2D_LOG_ERROR("Failed to create cache file: {}", cachePath);
|
||||||
|
|
@ -123,7 +131,7 @@ bool ShaderCache::saveCache(const ShaderCacheEntry& entry) {
|
||||||
cacheMap_[entry.name] = entry;
|
cacheMap_[entry.name] = entry;
|
||||||
saveCacheIndex();
|
saveCacheIndex();
|
||||||
|
|
||||||
E2D_LOG_DEBUG("Shader cache saved: {}", entry.name);
|
E2D_LOG_INFO("Shader cache saved: {} ({} bytes)", entry.name, entry.binary.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ Ptr<IShader> ShaderManager::loadFromFiles(const std::string& name,
|
||||||
Ptr<IShader> shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
Ptr<IShader> shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
||||||
|
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
|
E2D_LOG_DEBUG("No valid cache found, compiling shader from source: {}", name);
|
||||||
shader = factory_->createFromSource(name, result.vertSource, result.fragSource);
|
shader = factory_->createFromSource(name, result.vertSource, result.fragSource);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
E2D_LOG_ERROR("Failed to create shader from source: {}", name);
|
E2D_LOG_ERROR("Failed to create shader from source: {}", name);
|
||||||
|
|
@ -143,12 +144,15 @@ Ptr<IShader> ShaderManager::loadFromFiles(const std::string& name,
|
||||||
|
|
||||||
std::vector<uint8_t> binary;
|
std::vector<uint8_t> binary;
|
||||||
if (factory_->getShaderBinary(*shader, binary)) {
|
if (factory_->getShaderBinary(*shader, binary)) {
|
||||||
|
E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size());
|
||||||
ShaderCacheEntry entry;
|
ShaderCacheEntry entry;
|
||||||
entry.name = name;
|
entry.name = name;
|
||||||
entry.sourceHash = sourceHash;
|
entry.sourceHash = sourceHash;
|
||||||
entry.binary = binary;
|
entry.binary = binary;
|
||||||
entry.dependencies = result.dependencies;
|
entry.dependencies = result.dependencies;
|
||||||
ShaderCache::getInstance().saveCache(entry);
|
ShaderCache::getInstance().saveCache(entry);
|
||||||
|
} else {
|
||||||
|
E2D_LOG_WARN("Failed to get shader binary for: {}", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,6 +209,7 @@ Ptr<IShader> ShaderManager::loadFromCombinedFile(const std::string& path) {
|
||||||
Ptr<IShader> shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
Ptr<IShader> shader = loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
||||||
|
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
|
E2D_LOG_DEBUG("No valid cache found, compiling shader from source: {}", name);
|
||||||
shader = factory_->createFromSource(name, result.vertSource, result.fragSource);
|
shader = factory_->createFromSource(name, result.vertSource, result.fragSource);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
E2D_LOG_ERROR("Failed to create shader from source: {}", name);
|
E2D_LOG_ERROR("Failed to create shader from source: {}", name);
|
||||||
|
|
@ -213,12 +218,15 @@ Ptr<IShader> ShaderManager::loadFromCombinedFile(const std::string& path) {
|
||||||
|
|
||||||
std::vector<uint8_t> binary;
|
std::vector<uint8_t> binary;
|
||||||
if (factory_->getShaderBinary(*shader, binary)) {
|
if (factory_->getShaderBinary(*shader, binary)) {
|
||||||
|
E2D_LOG_DEBUG("Got shader binary, size: {} bytes", binary.size());
|
||||||
ShaderCacheEntry entry;
|
ShaderCacheEntry entry;
|
||||||
entry.name = name;
|
entry.name = name;
|
||||||
entry.sourceHash = sourceHash;
|
entry.sourceHash = sourceHash;
|
||||||
entry.binary = binary;
|
entry.binary = binary;
|
||||||
entry.dependencies = result.dependencies;
|
entry.dependencies = result.dependencies;
|
||||||
ShaderCache::getInstance().saveCache(entry);
|
ShaderCache::getInstance().saveCache(entry);
|
||||||
|
} else {
|
||||||
|
E2D_LOG_WARN("Failed to get shader binary for: {}", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue