385 lines
8.2 KiB
C++
385 lines
8.2 KiB
C++
#pragma once
|
||
|
||
#include <extra2d/core/assets/Asset.h>
|
||
#include <extra2d/core/math_types.h>
|
||
#include <extra2d/gfx/GFXDef.h>
|
||
#include <unordered_map>
|
||
#include <variant>
|
||
#include <vector>
|
||
|
||
namespace extra2d {
|
||
|
||
namespace gfx {
|
||
class Shader;
|
||
class PipelineState;
|
||
}
|
||
|
||
/**
|
||
* @brief 宏定义记录
|
||
*/
|
||
using MacroRecord = std::unordered_map<std::string, i32>;
|
||
|
||
/**
|
||
* @brief 材质属性变体类型
|
||
*/
|
||
using MaterialPropertyVariant = std::variant<
|
||
std::monostate,
|
||
float,
|
||
i32,
|
||
Vec2,
|
||
Vec3,
|
||
Vec4,
|
||
Color,
|
||
std::vector<float>,
|
||
std::vector<i32>,
|
||
std::vector<Vec2>,
|
||
std::vector<Vec3>,
|
||
std::vector<Vec4>,
|
||
std::vector<Color>>;
|
||
|
||
/**
|
||
* @brief Pass 重载信息
|
||
*/
|
||
struct PassOverrides {
|
||
gfx::RasterizerState rasterizerState;
|
||
gfx::DepthStencilState depthStencilState;
|
||
gfx::BlendState blendState;
|
||
|
||
void reset() {
|
||
rasterizerState = gfx::RasterizerState{};
|
||
depthStencilState = gfx::DepthStencilState{};
|
||
blendState = gfx::BlendState{};
|
||
}
|
||
};
|
||
|
||
/**
|
||
* @brief 材质初始化信息
|
||
*/
|
||
struct MaterialInfo {
|
||
std::string effectName;
|
||
u32 technique{0};
|
||
MacroRecord defines;
|
||
PassOverrides states;
|
||
};
|
||
|
||
/**
|
||
* @brief 渲染 Pass
|
||
*/
|
||
class Pass {
|
||
public:
|
||
Pass();
|
||
~Pass();
|
||
|
||
/**
|
||
* @brief 初始化 Pass
|
||
* @param shader 着色器
|
||
* @return 成功返回 true
|
||
*/
|
||
bool initialize(gfx::Shader* shader);
|
||
|
||
/**
|
||
* @brief 销毁 Pass
|
||
*/
|
||
void destroy();
|
||
|
||
/**
|
||
* @brief 设置 uniform 值
|
||
* @param name 名称
|
||
* @param value 值
|
||
*/
|
||
void setUniform(const std::string& name, const MaterialPropertyVariant& value);
|
||
|
||
/**
|
||
* @brief 获取 uniform 值
|
||
* @param name 名称
|
||
* @return 值
|
||
*/
|
||
const MaterialPropertyVariant* getUniform(const std::string& name) const;
|
||
|
||
/**
|
||
* @brief 设置管线状态
|
||
* @param state 管线状态
|
||
*/
|
||
void setPipelineState(gfx::PipelineState* state);
|
||
|
||
/**
|
||
* @brief 获取管线状态
|
||
* @return 管线状态
|
||
*/
|
||
gfx::PipelineState* getPipelineState() const;
|
||
|
||
/**
|
||
* @brief 获取着色器
|
||
* @return 着色器
|
||
*/
|
||
gfx::Shader* getShader() const;
|
||
|
||
/**
|
||
* @brief 设置混合状态
|
||
* @param state 混合状态
|
||
*/
|
||
void setBlendState(const gfx::BlendState& state);
|
||
|
||
/**
|
||
* @brief 获取混合状态
|
||
* @return 混合状态
|
||
*/
|
||
const gfx::BlendState& getBlendState() const;
|
||
|
||
/**
|
||
* @brief 设置深度模板状态
|
||
* @param state 深度模板状态
|
||
*/
|
||
void setDepthStencilState(const gfx::DepthStencilState& state);
|
||
|
||
/**
|
||
* @brief 获取深度模板状态
|
||
* @return 深度模板状态
|
||
*/
|
||
const gfx::DepthStencilState& getDepthStencilState() const;
|
||
|
||
/**
|
||
* @brief 设置光栅化状态
|
||
* @param state 光栅化状态
|
||
*/
|
||
void setRasterizerState(const gfx::RasterizerState& state);
|
||
|
||
/**
|
||
* @brief 获取光栅化状态
|
||
* @return 光栅化状态
|
||
*/
|
||
const gfx::RasterizerState& getRasterizerState() const;
|
||
|
||
/**
|
||
* @brief 获取哈希值
|
||
* @return 哈希值
|
||
*/
|
||
size_t getHash() const;
|
||
|
||
private:
|
||
gfx::Shader* shader_{nullptr};
|
||
gfx::PipelineState* pipelineState_{nullptr};
|
||
|
||
gfx::BlendState blendState_;
|
||
gfx::DepthStencilState depthStencilState_;
|
||
gfx::RasterizerState rasterizerState_;
|
||
|
||
std::unordered_map<std::string, MaterialPropertyVariant> uniforms_;
|
||
size_t hash_{0};
|
||
};
|
||
|
||
/**
|
||
* @brief 材质类
|
||
*
|
||
* 管理渲染材质,包含着色器和渲染状态。
|
||
* 参考 Cocos Creator 的 Material 设计。
|
||
*/
|
||
class Material : public Asset {
|
||
public:
|
||
/**
|
||
* @brief 创建材质
|
||
* @return 材质引用
|
||
*/
|
||
static Ref<Material> create();
|
||
|
||
/**
|
||
* @brief 构造函数
|
||
*/
|
||
Material();
|
||
|
||
/**
|
||
* @brief 析构函数
|
||
*/
|
||
~Material() override;
|
||
|
||
/**
|
||
* @brief 初始化材质
|
||
* @param info 材质信息
|
||
* @return 成功返回 true
|
||
*/
|
||
bool initialize(const MaterialInfo& info);
|
||
|
||
/**
|
||
* @brief 重置材质
|
||
* @param info 材质信息
|
||
*/
|
||
void reset(const MaterialInfo& info);
|
||
|
||
/**
|
||
* @brief 销毁材质
|
||
* @return 成功返回 true
|
||
*/
|
||
bool destroy() override;
|
||
|
||
// ==================== 属性设置 ====================
|
||
|
||
/**
|
||
* @brief 设置属性值
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引(默认所有 Pass)
|
||
*/
|
||
void setProperty(const std::string& name, const MaterialPropertyVariant& value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置浮点属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyFloat(const std::string& name, float value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置整数属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyInt(const std::string& name, i32 value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置 Vec2 属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyVec2(const std::string& name, const Vec2& value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置 Vec3 属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyVec3(const std::string& name, const Vec3& value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置 Vec4 属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyVec4(const std::string& name, const Vec4& value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 设置颜色属性
|
||
* @param name 属性名
|
||
* @param value 值
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void setPropertyColor(const std::string& name, const Color& value, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 获取属性值
|
||
* @param name 属性名
|
||
* @param passIdx Pass 索引
|
||
* @return 属性值
|
||
*/
|
||
const MaterialPropertyVariant* getProperty(const std::string& name, i32 passIdx = -1) const;
|
||
|
||
// ==================== Pass 管理 ====================
|
||
|
||
/**
|
||
* @brief 获取 Pass 数量
|
||
* @return Pass 数量
|
||
*/
|
||
size_t getPassCount() const;
|
||
|
||
/**
|
||
* @brief 获取 Pass
|
||
* @param index 索引
|
||
* @return Pass 指针
|
||
*/
|
||
Pass* getPass(size_t index);
|
||
|
||
/**
|
||
* @brief 获取所有 Pass
|
||
* @return Pass 列表
|
||
*/
|
||
const std::vector<Ref<Pass>>& getPasses() const;
|
||
|
||
/**
|
||
* @brief 添加 Pass
|
||
* @param pass Pass
|
||
*/
|
||
void addPass(Ref<Pass> pass);
|
||
|
||
// ==================== 状态重载 ====================
|
||
|
||
/**
|
||
* @brief 重载管线状态
|
||
* @param overrides 重载信息
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void overridePipelineStates(const PassOverrides& overrides, i32 passIdx = -1);
|
||
|
||
/**
|
||
* @brief 重编译着色器
|
||
* @param defines 宏定义
|
||
* @param passIdx Pass 索引
|
||
*/
|
||
void recompileShaders(const MacroRecord& defines, i32 passIdx = -1);
|
||
|
||
// ==================== 属性访问器 ====================
|
||
|
||
/**
|
||
* @brief 设置 Effect 名称
|
||
* @param name 名称
|
||
*/
|
||
void setEffectName(const std::string& name);
|
||
|
||
/**
|
||
* @brief 获取 Effect 名称
|
||
* @return 名称
|
||
*/
|
||
const std::string& getEffectName() const;
|
||
|
||
/**
|
||
* @brief 设置 Technique 索引
|
||
* @param index 索引
|
||
*/
|
||
void setTechniqueIndex(u32 index);
|
||
|
||
/**
|
||
* @brief 获取 Technique 索引
|
||
* @return 索引
|
||
*/
|
||
u32 getTechniqueIndex() const;
|
||
|
||
/**
|
||
* @brief 获取哈希值
|
||
* @return 哈希值
|
||
*/
|
||
size_t getHash() const;
|
||
|
||
/**
|
||
* @brief 复制材质
|
||
* @param other 源材质
|
||
*/
|
||
void copy(const Material* other);
|
||
|
||
/**
|
||
* @brief 重置 uniform 为默认值
|
||
*/
|
||
void resetUniforms();
|
||
|
||
protected:
|
||
/**
|
||
* @brief 更新哈希值
|
||
*/
|
||
void updateHash();
|
||
|
||
private:
|
||
std::string effectName_;
|
||
u32 techniqueIndex_{0};
|
||
|
||
std::vector<Ref<Pass>> passes_;
|
||
std::vector<MacroRecord> defines_;
|
||
std::vector<PassOverrides> states_;
|
||
|
||
std::unordered_map<std::string, MaterialPropertyVariant> properties_;
|
||
size_t hash_{0};
|
||
};
|
||
|
||
} // namespace extra2d
|