Extra2D/include/renderer/shader.h

180 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <core/color.h>
#include <core/types.h>
#include <graphics/opengl/gl_shader.h>
#include <functional>
#include <string>
#include <unordered_map>
namespace extra2d {
// ============================================================================
// Shader参数绑定回调
// ============================================================================
using ShaderBindCallback = std::function<void(GLShader &)>;
// ============================================================================
// Shader系统 - 管理所有Shader的加载、缓存和热重载
// ============================================================================
class ShaderSystem {
public:
// ------------------------------------------------------------------------
// 单例访问
// ------------------------------------------------------------------------
static ShaderSystem &getInstance();
// ------------------------------------------------------------------------
// 初始化和关闭
// ------------------------------------------------------------------------
bool init();
void shutdown();
// ------------------------------------------------------------------------
// Shader加载
// ------------------------------------------------------------------------
/**
* @brief 从文件加载Shader
* @param name Shader名称用于缓存
* @param vertPath 顶点着色器文件路径
* @param fragPath 片段着色器文件路径
* @return 加载的Shader失败返回nullptr
*/
Ptr<GLShader> loadFromFile(const std::string &name,
const std::string &vertPath,
const std::string &fragPath);
/**
* @brief 从源码字符串加载Shader
* @param name Shader名称用于缓存
* @param vertSource 顶点着色器源码
* @param fragSource 片段着色器源码
* @return 加载的Shader失败返回nullptr
*/
Ptr<GLShader> loadFromSource(const std::string &name,
const std::string &vertSource,
const std::string &fragSource);
/**
* @brief 从已编译的程序获取Shader
* @param name Shader名称
* @return 缓存的Shader不存在返回nullptr
*/
Ptr<GLShader> get(const std::string &name);
/**
* @brief 检查Shader是否存在
*/
bool has(const std::string &name) const;
// ------------------------------------------------------------------------
// Shader移除
// ------------------------------------------------------------------------
void remove(const std::string &name);
void clear();
// ------------------------------------------------------------------------
// 热重载支持
// ------------------------------------------------------------------------
/**
* @brief 启用/禁用文件监视
*/
void setFileWatching(bool enable);
bool isFileWatching() const { return fileWatching_; }
/**
* @brief 更新文件监视(在主循环中调用)
*/
void updateFileWatching();
/**
* @brief 重载指定Shader
*/
bool reload(const std::string &name);
/**
* @brief 重载所有Shader
*/
void reloadAll();
// ------------------------------------------------------------------------
// 内置Shader获取
// ------------------------------------------------------------------------
Ptr<GLShader> getBuiltinSpriteShader();
Ptr<GLShader> getBuiltinParticleShader();
Ptr<GLShader> getBuiltinPostProcessShader();
Ptr<GLShader> getBuiltinShapeShader();
// ------------------------------------------------------------------------
// 工具方法
// ------------------------------------------------------------------------
/**
* @brief 从文件读取文本内容
*/
static std::string readFile(const std::string &filepath);
/**
* @brief 获取Shader文件的最后修改时间
*/
static uint64_t getFileModifiedTime(const std::string &filepath);
private:
ShaderSystem() = default;
~ShaderSystem() = default;
ShaderSystem(const ShaderSystem &) = delete;
ShaderSystem &operator=(const ShaderSystem &) = delete;
struct ShaderInfo {
Ptr<GLShader> shader;
std::string vertPath;
std::string fragPath;
uint64_t vertModifiedTime;
uint64_t fragModifiedTime;
bool isBuiltin;
};
std::unordered_map<std::string, ShaderInfo> shaders_;
bool fileWatching_ = false;
float watchTimer_ = 0.0f;
static constexpr float WATCH_INTERVAL = 1.0f; // 检查间隔(秒)
// 内置Shader缓存
Ptr<GLShader> builtinSpriteShader_;
Ptr<GLShader> builtinParticleShader_;
Ptr<GLShader> builtinPostProcessShader_;
Ptr<GLShader> builtinShapeShader_;
bool loadBuiltinShaders();
void checkAndReload();
};
// ============================================================================
// Shader参数包装器 - 简化Uniform设置
// ============================================================================
class ShaderParams {
public:
explicit ShaderParams(GLShader &shader);
ShaderParams &setBool(const std::string &name, bool value);
ShaderParams &setInt(const std::string &name, int value);
ShaderParams &setFloat(const std::string &name, float value);
ShaderParams &setVec2(const std::string &name, const glm::vec2 &value);
ShaderParams &setVec3(const std::string &name, const glm::vec3 &value);
ShaderParams &setVec4(const std::string &name, const glm::vec4 &value);
ShaderParams &setMat4(const std::string &name, const glm::mat4 &value);
ShaderParams &setColor(const std::string &name, const Color &color);
private:
GLShader &shader_;
};
// ============================================================================
// 便捷宏
// ============================================================================
#define E2D_SHADER_SYSTEM() ::extra2d::ShaderSystem::getInstance()
} // namespace extra2d