Extra2D/include/renderer/material.h

248 lines
5.9 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 <types/ptr/ref_counted.h>
#include <types/ptr/intrusive_ptr.h>
#include <types/math/vec2.h>
#include <types/math/color.h>
#include <renderer/render_types.h>
#include <renderer/shader.h>
#include <renderer/uniform_buffer.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace extra2d {
// 前向声明
class Material;
class Texture;
/**
* @brief 材质参数信息
*/
struct MaterialParamInfo {
MaterialParamType type;
uint32_t offset;
uint32_t size;
};
/**
* @brief 纹理槽位信息
*/
struct TextureSlot {
Handle<Texture> handle;
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:
std::unordered_map<std::string, MaterialParamInfo> params_;
uint32_t bufferSize_ = 0;
bool finalized_ = false;
};
/**
* @brief 材质类
*
* 作为着色器和纹理的中间层,管理:
* - 着色器程序
* - 材质参数(通过 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", textureHandle, 0);
*
* // 注册到渲染器
* MaterialHandle handle = renderer->registerMaterial(material);
* @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 设置 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 value 值
*/
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, Handle<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 应用材质
*
* 绑定着色器、上传 UBO 数据
* @param uboManager UBO 管理器
*/
void apply(UniformBufferManager& uboManager);
private:
Ptr<MaterialLayout> layout_; // 材质布局
Ptr<Shader> shader_; // 着色器
std::vector<uint8_t> data_; // 材质数据UBO 缓冲)
std::vector<TextureSlot> textures_; // 纹理槽位列表
};
} // namespace extra2d