Extra2D/Extra2D/include/extra2d/core/assets/Material.h

385 lines
8.2 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 <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