293 lines
9.2 KiB
C++
293 lines
9.2 KiB
C++
#pragma once
|
||
|
||
#include <extra2d/core/types.h>
|
||
#include <glm/glm.hpp>
|
||
#include <glm/gtc/type_ptr.hpp>
|
||
#include <string>
|
||
#include <unordered_map>
|
||
#include <vector>
|
||
|
||
namespace extra2d {
|
||
|
||
// ============================================================================
|
||
// Shader加载结果
|
||
// ============================================================================
|
||
struct ShaderLoadResult {
|
||
bool success = false;
|
||
std::string errorMessage;
|
||
std::string vertSource;
|
||
std::string fragSource;
|
||
std::vector<std::string> dependencies;
|
||
};
|
||
|
||
// ============================================================================
|
||
// Shader Uniform 定义
|
||
// ============================================================================
|
||
struct ShaderUniformDef {
|
||
std::string type;
|
||
std::string description;
|
||
float defaultValue = 0.0f; // 默认值(用于float类型)
|
||
float defaultVec4[4] = {0, 0, 0, 0}; // 默认值(用于vec4类型)
|
||
float defaultMat4[16] = {
|
||
1, 0, 0, 0, 0, 1, 0, 0,
|
||
0, 0, 1, 0, 0, 0, 0, 1}; // 默认值(用于mat4类型,默认单位矩阵)
|
||
int defaultInt = 0; // 默认值(用于int类型)
|
||
bool defaultBool = false; // 默认值(用于bool类型)
|
||
bool hasDefault = false; // 是否有默认值
|
||
};
|
||
|
||
// ============================================================================
|
||
// Shader Uniform 值类型
|
||
// ============================================================================
|
||
struct ShaderUniformValue {
|
||
enum class Type { Float, Int, Bool, Vec2, Vec3, Vec4, Mat4 } type;
|
||
|
||
union {
|
||
float f[16]; // 足够存储 mat4
|
||
int i;
|
||
bool b;
|
||
} data;
|
||
|
||
// 构造函数
|
||
ShaderUniformValue() : type(Type::Float) { data.f[0] = 0; }
|
||
ShaderUniformValue(float v) : type(Type::Float) { data.f[0] = v; }
|
||
ShaderUniformValue(int v) : type(Type::Int) { data.i = v; }
|
||
ShaderUniformValue(bool v) : type(Type::Bool) { data.b = v; }
|
||
ShaderUniformValue(const glm::vec2 &v) : type(Type::Vec2) {
|
||
data.f[0] = v.x;
|
||
data.f[1] = v.y;
|
||
}
|
||
ShaderUniformValue(const glm::vec3 &v) : type(Type::Vec3) {
|
||
data.f[0] = v.x;
|
||
data.f[1] = v.y;
|
||
data.f[2] = v.z;
|
||
}
|
||
ShaderUniformValue(const glm::vec4 &v) : type(Type::Vec4) {
|
||
data.f[0] = v.x;
|
||
data.f[1] = v.y;
|
||
data.f[2] = v.z;
|
||
data.f[3] = v.w;
|
||
}
|
||
ShaderUniformValue(const glm::mat4 &m) : type(Type::Mat4) {
|
||
const float *ptr = glm::value_ptr(m);
|
||
for (int i = 0; i < 16; ++i)
|
||
data.f[i] = ptr[i];
|
||
}
|
||
};
|
||
|
||
// Uniform 值映射表
|
||
using UniformValueMap = std::unordered_map<std::string, ShaderUniformValue>;
|
||
|
||
// ============================================================================
|
||
// Shader Sampler 定义
|
||
// ============================================================================
|
||
struct ShaderSamplerDef {
|
||
std::string type;
|
||
std::string description;
|
||
};
|
||
|
||
// ============================================================================
|
||
// Shader元数据
|
||
// ============================================================================
|
||
struct ShaderMetadata {
|
||
std::string name;
|
||
std::string category;
|
||
std::string version;
|
||
std::string description;
|
||
std::string vertPath;
|
||
std::string fragPath;
|
||
std::string combinedPath;
|
||
uint64_t lastModified = 0;
|
||
std::vector<std::string> defines;
|
||
std::unordered_map<std::string, std::string> uniforms;
|
||
std::unordered_map<std::string, ShaderUniformDef> uniformDefs;
|
||
std::unordered_map<std::string, ShaderSamplerDef> samplerDefs;
|
||
};
|
||
|
||
// ============================================================================
|
||
// ShaderLoader接口 - 支持多种文件格式加载
|
||
// ============================================================================
|
||
class IShaderLoader {
|
||
public:
|
||
virtual ~IShaderLoader() = default;
|
||
|
||
/**
|
||
* @brief 从分离文件加载Shader (.vert + .frag)
|
||
* @param name Shader名称
|
||
* @param vertPath 顶点着色器文件路径
|
||
* @param fragPath 片段着色器文件路径
|
||
* @return 加载结果
|
||
*/
|
||
virtual ShaderLoadResult
|
||
loadFromSeparateFiles(const std::string &name, const std::string &vertPath,
|
||
const std::string &fragPath) = 0;
|
||
|
||
/**
|
||
* @brief 从组合文件加载Shader (.shader)
|
||
* @param path 组合Shader文件路径
|
||
* @return 加载结果
|
||
*/
|
||
virtual ShaderLoadResult loadFromCombinedFile(const std::string &path) = 0;
|
||
|
||
/**
|
||
* @brief 从源码字符串加载Shader
|
||
* @param vertSource 顶点着色器源码
|
||
* @param fragSource 片段着色器源码
|
||
* @return 加载结果
|
||
*/
|
||
virtual ShaderLoadResult loadFromSource(const std::string &vertSource,
|
||
const std::string &fragSource) = 0;
|
||
|
||
/**
|
||
* @brief 处理Shader源码中的#include指令
|
||
* @param source 原始源码
|
||
* @param baseDir 基础目录
|
||
* @param outDependencies 输出依赖列表
|
||
* @return 处理后的源码
|
||
*/
|
||
virtual std::string
|
||
processIncludes(const std::string &source, const std::string &baseDir,
|
||
std::vector<std::string> &outDependencies) = 0;
|
||
|
||
/**
|
||
* @brief 应用预处理器定义
|
||
* @param source 原始源码
|
||
* @param defines 预处理器定义列表
|
||
* @return 处理后的源码
|
||
*/
|
||
virtual std::string applyDefines(const std::string &source,
|
||
const std::vector<std::string> &defines) = 0;
|
||
|
||
/**
|
||
* @brief 获取Shader元数据
|
||
* @param path Shader文件路径
|
||
* @return 元数据
|
||
*/
|
||
virtual ShaderMetadata getMetadata(const std::string &path) = 0;
|
||
};
|
||
|
||
// ============================================================================
|
||
// 默认ShaderLoader实现
|
||
// ============================================================================
|
||
class ShaderLoader : public IShaderLoader {
|
||
public:
|
||
ShaderLoader();
|
||
~ShaderLoader() override = default;
|
||
|
||
/**
|
||
* @brief 从分离文件加载Shader (.vert + .frag)
|
||
* @param name Shader名称
|
||
* @param vertPath 顶点着色器文件路径
|
||
* @param fragPath 片段着色器文件路径
|
||
* @return 加载结果
|
||
*/
|
||
ShaderLoadResult loadFromSeparateFiles(const std::string &name,
|
||
const std::string &vertPath,
|
||
const std::string &fragPath) override;
|
||
|
||
/**
|
||
* @brief 从组合文件加载Shader (.shader)
|
||
* @param path 组合Shader文件路径
|
||
* @return 加载结果
|
||
*/
|
||
ShaderLoadResult loadFromCombinedFile(const std::string &path) override;
|
||
|
||
/**
|
||
* @brief 从源码字符串加载Shader
|
||
* @param vertSource 顶点着色器源码
|
||
* @param fragSource 片段着色器源码
|
||
* @return 加载结果
|
||
*/
|
||
ShaderLoadResult loadFromSource(const std::string &vertSource,
|
||
const std::string &fragSource) override;
|
||
|
||
/**
|
||
* @brief 处理Shader源码中的#include指令
|
||
* @param source 原始源码
|
||
* @param baseDir 基础目录
|
||
* @param outDependencies 输出依赖列表
|
||
* @return 处理后的源码
|
||
*/
|
||
std::string
|
||
processIncludes(const std::string &source, const std::string &baseDir,
|
||
std::vector<std::string> &outDependencies) override;
|
||
|
||
/**
|
||
* @brief 应用预处理器定义
|
||
* @param source 原始源码
|
||
* @param defines 预处理器定义列表
|
||
* @return 处理后的源码
|
||
*/
|
||
std::string applyDefines(const std::string &source,
|
||
const std::vector<std::string> &defines) override;
|
||
|
||
/**
|
||
* @brief 获取Shader元数据
|
||
* @param path Shader文件路径
|
||
* @return 元数据
|
||
*/
|
||
ShaderMetadata getMetadata(const std::string &path) override;
|
||
|
||
/**
|
||
* @brief 添加include搜索路径
|
||
* @param path 搜索路径
|
||
*/
|
||
void addIncludePath(const std::string &path);
|
||
|
||
/**
|
||
* @brief 读取文件内容
|
||
* @param filepath 文件路径
|
||
* @return 文件内容字符串
|
||
*/
|
||
static std::string readFile(const std::string &filepath);
|
||
|
||
/**
|
||
* @brief 获取文件修改时间
|
||
* @param filepath 文件路径
|
||
* @return 修改时间戳
|
||
*/
|
||
static uint64_t getFileModifiedTime(const std::string &filepath);
|
||
|
||
/**
|
||
* @brief 检查文件是否存在
|
||
* @param filepath 文件路径
|
||
* @return 存在返回true,否则返回false
|
||
*/
|
||
static bool fileExists(const std::string &filepath);
|
||
|
||
private:
|
||
std::vector<std::string> includePaths_;
|
||
std::unordered_map<std::string, std::string> includeCache_;
|
||
|
||
/**
|
||
* @brief 解析组合Shader文件
|
||
* @param content 文件内容
|
||
* @param outVert 输出顶点着色器源码
|
||
* @param outFrag 输出片段着色器源码
|
||
* @param outMetadata 输出元数据
|
||
* @return 解析成功返回true,失败返回false
|
||
*/
|
||
bool parseCombinedFile(const std::string &content, std::string &outVert,
|
||
std::string &outFrag, ShaderMetadata &outMetadata);
|
||
|
||
/**
|
||
* @brief 解析元数据JSON块
|
||
* @param jsonContent JSON内容
|
||
* @param outMetadata 输出元数据
|
||
* @return 解析成功返回true,失败返回false
|
||
*/
|
||
bool parseMetadata(const std::string &jsonContent,
|
||
ShaderMetadata &outMetadata);
|
||
|
||
/**
|
||
* @brief 查找include文件路径
|
||
* @param includeName include文件名
|
||
* @param baseDir 基础目录
|
||
* @return 找到的完整路径,未找到返回空字符串
|
||
*/
|
||
std::string findIncludeFile(const std::string &includeName,
|
||
const std::string &baseDir);
|
||
};
|
||
|
||
} // namespace extra2d
|