Extra2D/include/renderer/material.h

280 lines
6.9 KiB
C
Raw Permalink Normal View History

#pragma once
#include <renderer/rhi/rhi.h>
#include <renderer/shader.h>
#include <renderer/texture.h>
#include <types/ptr/ref_counted.h>
#include <types/ptr/intrusive_ptr.h>
#include <types/math/vec2.h>
#include <types/math/color.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace extra2d {
// 前向声明
class Material;
/**
* @brief
*/
enum class MaterialParamType : uint8_t {
Float, // 浮点数
Vec2, // 二维向量
Vec3, // 三维向量
Vec4, // 四维向量
Color, // 颜色
Mat4, // 4x4 矩阵
Texture // 纹理
};
/**
* @brief
* @param type
* @return
*/
inline uint32_t getMaterialParamSize(MaterialParamType type) {
switch (type) {
case MaterialParamType::Float: return sizeof(float);
case MaterialParamType::Vec2: return sizeof(float) * 2;
case MaterialParamType::Vec3: return sizeof(float) * 3;
case MaterialParamType::Vec4: return sizeof(float) * 4;
case MaterialParamType::Color: return sizeof(float) * 4;
case MaterialParamType::Mat4: return sizeof(float) * 16;
case MaterialParamType::Texture: return sizeof(uint32_t);
default: return 0;
}
}
/**
* @brief
*/
struct MaterialParamInfo {
MaterialParamType type;
uint32_t offset;
uint32_t size;
};
/**
* @brief
*/
struct TextureSlot {
Ptr<Texture> texture;
uint32_t slot;
std::string uniformName;
};
/**
* @brief
*
*
*/
class MaterialLayout : public RefCounted {
public:
/**
* @brief
*/
MaterialLayout();
/**
* @brief
* @param name
* @param type
*/
void addParam(const std::string& name, MaterialParamType type);
/**
* @brief
*/
void finalize();
/**
* @brief
* @param name
* @return nullptr
*/
const MaterialParamInfo* getParam(const std::string& name) const;
/**
* @brief
* @return
*/
uint32_t getBufferSize() const { return bufferSize_; }
/**
* @brief
* @return
*/
bool isFinalized() const { return finalized_; }
private:
// 使用vector保持参数添加顺序确保与着色器中的声明顺序一致
std::vector<std::pair<std::string, MaterialParamInfo>> params_;
std::unordered_map<std::string, size_t> paramIndexMap_; // 用于快速查找
uint32_t bufferSize_ = 0;
bool finalized_ = false;
};
/**
* @brief
*
* RHI
* -
* - UBO
* -
*
* 使
* @code
* // 创建自定义着色器
* auto shader = makePtr<Shader>();
* shader->loadFromFile("custom.vert", "custom.frag");
*
* // 创建材质布局
* auto layout = makePtr<MaterialLayout>();
* layout->addParam("uTintColor", MaterialParamType::Color);
* layout->addParam("uOpacity", MaterialParamType::Float);
* layout->finalize();
*
* // 创建材质
* auto material = makePtr<Material>();
* material->setShader(shader);
* material->setLayout(layout);
* material->setColor("uTintColor", Color::White);
* material->setFloat("uOpacity", 1.0f);
*
* // 设置纹理
* material->setTexture("uTexture", texture, 0);
* @endcode
*/
class Material : public RefCounted {
public:
/**
* @brief
*/
Material();
// ========================================
// 着色器和布局设置
// ========================================
/**
* @brief
* @param layout
*/
void setLayout(Ptr<MaterialLayout> layout);
/**
* @brief
* @param shader
*/
void setShader(Ptr<Shader> shader);
/**
* @brief
* @return
*/
Ptr<Shader> getShader() const { return shader_; }
/**
* @brief RHI 线
* @return RHI 线
*/
PipelineHandle getPipeline() const;
// ========================================
// 参数设置
// ========================================
/**
* @brief float
* @param name
* @param value
*/
void setFloat(const std::string& name, float value);
/**
* @brief vec2
* @param name
* @param value
*/
void setVec2(const std::string& name, const Vec2& value);
/**
* @brief vec4
* @param name
* @param x X
* @param y Y
* @param z Z
* @param w W
*/
void setVec4(const std::string& name, float x, float y, float z, float w);
/**
* @brief
* @param name
* @param value
*/
void setColor(const std::string& name, const Color& value);
/**
* @brief mat4
* @param name
* @param value
*/
void setMat4(const std::string& name, const float* value);
// ========================================
// 纹理管理
// ========================================
/**
* @brief
* @param uniformName uniform
* @param texture
* @param slot 0-15
*/
void setTexture(const std::string& uniformName, Ptr<Texture> texture, uint32_t slot);
/**
* @brief
* @return
*/
const std::vector<TextureSlot>& getTextures() const { return textures_; }
/**
* @brief
*/
void clearTextures();
// ========================================
// 数据访问
// ========================================
/**
* @brief
* @return
*/
const void* getData() const { return data_.data(); }
/**
* @brief
* @return
*/
uint32_t getDataSize() const { return static_cast<uint32_t>(data_.size()); }
/**
* @brief
* @return
*/
Ptr<MaterialLayout> getLayout() const { return layout_; }
private:
Ptr<MaterialLayout> layout_; // 材质布局
Ptr<Shader> shader_; // 着色器
std::vector<uint8_t> data_; // 材质数据UBO 缓冲)
std::vector<TextureSlot> textures_; // 纹理槽位列表
};
} // namespace extra2d