Files
XCEngine/engine/include/XCEngine/Resources/Material/Material.h

224 lines
7.6 KiB
C++

#pragma once
#include <XCEngine/Core/Asset/IResource.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <XCEngine/Resources/Texture/Texture.h>
#include <XCEngine/Resources/Shader/Shader.h>
#include <XCEngine/Core/Containers/HashMap.h>
#include <XCEngine/Core/Types.h>
#include <XCEngine/Core/Math/Vector2.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Vector4.h>
#include <cstring>
#include <vector>
namespace XCEngine {
namespace Resources {
enum class MaterialRenderQueue : Core::int32 {
Background = 1000,
Geometry = 2000,
AlphaTest = 2450,
Transparent = 3000,
Overlay = 4000
};
enum class MaterialCullMode : Core::uint8 {
None = 0,
Front = 1,
Back = 2
};
enum class MaterialComparisonFunc : Core::uint8 {
Never = 0,
Less = 1,
Equal = 2,
LessEqual = 3,
Greater = 4,
NotEqual = 5,
GreaterEqual = 6,
Always = 7
};
enum class MaterialBlendOp : Core::uint8 {
Add = 0,
Subtract = 1,
ReverseSubtract = 2,
Min = 3,
Max = 4
};
enum class MaterialBlendFactor : Core::uint8 {
Zero = 0,
One = 1,
SrcColor = 2,
InvSrcColor = 3,
SrcAlpha = 4,
InvSrcAlpha = 5,
DstAlpha = 6,
InvDstAlpha = 7,
DstColor = 8,
InvDstColor = 9,
SrcAlphaSat = 10,
BlendFactor = 11,
InvBlendFactor = 12,
Src1Color = 13,
InvSrc1Color = 14,
Src1Alpha = 15,
InvSrc1Alpha = 16
};
struct MaterialRenderState {
bool blendEnable = false;
MaterialBlendFactor srcBlend = MaterialBlendFactor::One;
MaterialBlendFactor dstBlend = MaterialBlendFactor::Zero;
MaterialBlendFactor srcBlendAlpha = MaterialBlendFactor::One;
MaterialBlendFactor dstBlendAlpha = MaterialBlendFactor::Zero;
MaterialBlendOp blendOp = MaterialBlendOp::Add;
MaterialBlendOp blendOpAlpha = MaterialBlendOp::Add;
Core::uint8 colorWriteMask = 0xF;
bool depthTestEnable = true;
bool depthWriteEnable = true;
MaterialComparisonFunc depthFunc = MaterialComparisonFunc::Less;
MaterialCullMode cullMode = MaterialCullMode::None;
bool operator==(const MaterialRenderState& other) const {
return blendEnable == other.blendEnable &&
srcBlend == other.srcBlend &&
dstBlend == other.dstBlend &&
srcBlendAlpha == other.srcBlendAlpha &&
dstBlendAlpha == other.dstBlendAlpha &&
blendOp == other.blendOp &&
blendOpAlpha == other.blendOpAlpha &&
colorWriteMask == other.colorWriteMask &&
depthTestEnable == other.depthTestEnable &&
depthWriteEnable == other.depthWriteEnable &&
depthFunc == other.depthFunc &&
cullMode == other.cullMode;
}
bool operator!=(const MaterialRenderState& other) const {
return !(*this == other);
}
};
enum class MaterialPropertyType {
Float, Float2, Float3, Float4,
Int, Int2, Int3, Int4,
Bool, Texture, Cubemap
};
struct MaterialProperty {
Containers::String name;
MaterialPropertyType type;
union Value {
float floatValue[4];
Core::int32 intValue[4];
bool boolValue;
Value() { memset(this, 0, sizeof(Value)); }
} value;
Core::uint32 refCount = 0;
MaterialProperty() : type(MaterialPropertyType::Float), refCount(0) {}
};
struct MaterialTagEntry {
Containers::String name;
Containers::String value;
};
struct MaterialTextureBinding {
Containers::String name;
Core::uint32 slot = 0;
ResourceHandle<Texture> texture;
};
class Material : public IResource {
public:
Material();
virtual ~Material() override;
ResourceType GetType() const override { return ResourceType::Material; }
const Containers::String& GetName() const override { return m_name; }
const Containers::String& GetPath() const override { return m_path; }
ResourceGUID GetGUID() const override { return m_guid; }
bool IsValid() const override { return m_isValid; }
size_t GetMemorySize() const override { return m_memorySize; }
void Release() override;
void SetShader(const ResourceHandle<class Shader>& shader);
class Shader* GetShader() const { return m_shader.Get(); }
void SetRenderQueue(Core::int32 renderQueue);
void SetRenderQueue(MaterialRenderQueue renderQueue);
Core::int32 GetRenderQueue() const { return m_renderQueue; }
void SetRenderState(const MaterialRenderState& renderState);
const MaterialRenderState& GetRenderState() const { return m_renderState; }
void SetShaderPass(const Containers::String& shaderPass);
const Containers::String& GetShaderPass() const { return m_shaderPass; }
void SetTag(const Containers::String& name, const Containers::String& value);
Containers::String GetTag(const Containers::String& name) const;
bool HasTag(const Containers::String& name) const;
void RemoveTag(const Containers::String& name);
void ClearTags();
Core::uint32 GetTagCount() const { return static_cast<Core::uint32>(m_tags.Size()); }
Containers::String GetTagName(Core::uint32 index) const;
Containers::String GetTagValue(Core::uint32 index) const;
const Containers::Array<MaterialTagEntry>& GetTags() const { return m_tags; }
void SetFloat(const Containers::String& name, float value);
void SetFloat2(const Containers::String& name, const Math::Vector2& value);
void SetFloat3(const Containers::String& name, const Math::Vector3& value);
void SetFloat4(const Containers::String& name, const Math::Vector4& value);
void SetInt(const Containers::String& name, Core::int32 value);
void SetBool(const Containers::String& name, bool value);
void SetTexture(const Containers::String& name, const ResourceHandle<Texture>& texture);
float GetFloat(const Containers::String& name) const;
Math::Vector2 GetFloat2(const Containers::String& name) const;
Math::Vector3 GetFloat3(const Containers::String& name) const;
Math::Vector4 GetFloat4(const Containers::String& name) const;
Core::int32 GetInt(const Containers::String& name) const;
bool GetBool(const Containers::String& name) const;
ResourceHandle<Texture> GetTexture(const Containers::String& name) const;
Core::uint32 GetTextureBindingCount() const { return static_cast<Core::uint32>(m_textureBindings.Size()); }
Containers::String GetTextureBindingName(Core::uint32 index) const;
ResourceHandle<Texture> GetTextureBindingTexture(Core::uint32 index) const;
const Containers::Array<MaterialTextureBinding>& GetTextureBindings() const { return m_textureBindings; }
std::vector<MaterialProperty> GetProperties() const;
const Containers::Array<Core::uint8>& GetConstantBufferData() const { return m_constantBufferData; }
void UpdateConstantBuffer();
Core::uint64 GetChangeVersion() const { return m_changeVersion; }
void RecalculateMemorySize();
bool HasProperty(const Containers::String& name) const;
void RemoveProperty(const Containers::String& name);
void ClearAllProperties();
private:
void MarkChanged(bool updateConstantBuffer);
void UpdateMemorySize();
ResourceHandle<class Shader> m_shader;
Core::int32 m_renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
MaterialRenderState m_renderState;
Containers::String m_shaderPass;
Containers::Array<MaterialTagEntry> m_tags;
Containers::HashMap<Containers::String, MaterialProperty> m_properties;
Containers::Array<Core::uint8> m_constantBufferData;
Containers::Array<MaterialTextureBinding> m_textureBindings;
Core::uint64 m_changeVersion = 1;
};
} // namespace Resources
} // namespace XCEngine