222 lines
9.0 KiB
C++
222 lines
9.0 KiB
C++
#pragma once
|
|
|
|
#include <XCEngine/Core/Asset/IResource.h>
|
|
#include <XCEngine/Core/Asset/AssetRef.h>
|
|
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
|
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
#include <XCEngine/Resources/Texture/Texture.h>
|
|
|
|
#include "MaterialRenderState.h"
|
|
#include "engine/Runtime/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 <memory>
|
|
#include <vector>
|
|
|
|
namespace XCEngine {
|
|
namespace RHI {
|
|
class RHIBuffer;
|
|
}
|
|
namespace Resources {
|
|
|
|
enum class MaterialRenderQueue : Core::int32 {
|
|
Background = 1000,
|
|
Geometry = 2000,
|
|
AlphaTest = 2450,
|
|
Transparent = 3000,
|
|
Overlay = 4000
|
|
};
|
|
|
|
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 MaterialConstantFieldDesc {
|
|
Containers::String name;
|
|
MaterialPropertyType type = MaterialPropertyType::Float;
|
|
Core::uint32 offset = 0;
|
|
Core::uint32 size = 0;
|
|
Core::uint32 alignedSize = 0;
|
|
};
|
|
|
|
struct MaterialTagEntry {
|
|
Containers::String name;
|
|
Containers::String value;
|
|
};
|
|
|
|
struct PendingTextureLoadState {
|
|
IResource* resource = nullptr;
|
|
Containers::String errorMessage;
|
|
bool completed = false;
|
|
};
|
|
|
|
struct MaterialTextureBinding {
|
|
Containers::String name;
|
|
Core::uint32 slot = 0;
|
|
ResourceHandle<Texture> texture;
|
|
AssetRef textureRef;
|
|
Containers::String texturePath;
|
|
std::shared_ptr<PendingTextureLoadState> pendingLoad;
|
|
};
|
|
|
|
struct MaterialBufferBindingViewDesc {
|
|
Core::uint32 firstElement = 0;
|
|
Core::uint32 elementCount = 0;
|
|
Core::uint32 structureByteStride = 0;
|
|
};
|
|
|
|
struct MaterialBufferBinding {
|
|
Containers::String name;
|
|
RHI::RHIBuffer* buffer = nullptr;
|
|
MaterialBufferBindingViewDesc viewDesc = {};
|
|
};
|
|
|
|
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; }
|
|
bool HasRenderStateOverride() const { return m_hasRenderStateOverride; }
|
|
void SetRenderStateOverrideEnabled(bool enabled);
|
|
|
|
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 EnableKeyword(const Containers::String& keyword);
|
|
void DisableKeyword(const Containers::String& keyword);
|
|
void SetKeywordEnabled(const Containers::String& keyword, bool enabled);
|
|
bool IsKeywordEnabled(const Containers::String& keyword) const;
|
|
void ClearKeywords();
|
|
Core::uint32 GetKeywordCount() const { return static_cast<Core::uint32>(m_keywordSet.enabledKeywords.Size()); }
|
|
Containers::String GetKeyword(Core::uint32 index) const;
|
|
const ShaderKeywordSet& GetKeywordSet() const { return m_keywordSet; }
|
|
|
|
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);
|
|
void SetBuffer(const Containers::String& name, RHI::RHIBuffer* buffer);
|
|
void SetBuffer(
|
|
const Containers::String& name,
|
|
RHI::RHIBuffer* buffer,
|
|
const MaterialBufferBindingViewDesc& viewDesc);
|
|
void SetTextureAssetRef(const Containers::String& name,
|
|
const AssetRef& textureRef,
|
|
const Containers::String& texturePath = Containers::String());
|
|
void SetTexturePath(const Containers::String& name, const Containers::String& texturePath);
|
|
|
|
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;
|
|
RHI::RHIBuffer* GetBuffer(const Containers::String& name) const;
|
|
const MaterialBufferBinding* FindBufferBinding(const Containers::String& name) const;
|
|
Core::uint32 GetTextureBindingCount() const { return static_cast<Core::uint32>(m_textureBindings.Size()); }
|
|
Core::uint32 GetBufferBindingCount() const { return static_cast<Core::uint32>(m_bufferBindings.Size()); }
|
|
Containers::String GetTextureBindingName(Core::uint32 index) const;
|
|
AssetRef GetTextureBindingAssetRef(Core::uint32 index) const;
|
|
Containers::String GetTextureBindingPath(Core::uint32 index) const;
|
|
ResourceHandle<Texture> GetTextureBindingLoadedTexture(Core::uint32 index) const;
|
|
ResourceHandle<Texture> GetTextureBindingTexture(Core::uint32 index) const;
|
|
const Containers::Array<MaterialTextureBinding>& GetTextureBindings() const { return m_textureBindings; }
|
|
const Containers::Array<MaterialBufferBinding>& GetBufferBindings() const { return m_bufferBindings; }
|
|
std::vector<MaterialProperty> GetProperties() const;
|
|
|
|
const Containers::Array<Core::uint8>& GetConstantBufferData() const { return m_constantBufferData; }
|
|
const Containers::Array<MaterialConstantFieldDesc>& GetConstantLayout() const { return m_constantLayout; }
|
|
const MaterialConstantFieldDesc* FindConstantField(const Containers::String& name) const;
|
|
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();
|
|
void RemoveBufferBinding(const Containers::String& name);
|
|
void ClearBufferBindings();
|
|
|
|
private:
|
|
const ShaderPropertyDesc* FindShaderPropertyDesc(const Containers::String& name) const;
|
|
bool CanAssignPropertyType(const Containers::String& name, MaterialPropertyType type) const;
|
|
bool ResetPropertyToShaderDefault(const Containers::String& name);
|
|
void SyncShaderSchemaProperties(bool removeUnknownProperties);
|
|
void SyncShaderRuntimeBufferBindings(bool removeUnknownBindings);
|
|
void BeginAsyncTextureLoad(Core::uint32 index);
|
|
void ResolvePendingTextureBinding(Core::uint32 index);
|
|
void ResolvePendingTextureBindings();
|
|
void MarkChanged(bool updateConstantBuffer);
|
|
void UpdateMemorySize();
|
|
void SyncShaderSchemaKeywords(bool removeUnknownKeywords);
|
|
|
|
ResourceHandle<class Shader> m_shader;
|
|
Core::int32 m_renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
|
|
MaterialRenderState m_renderState;
|
|
bool m_hasRenderStateOverride = false;
|
|
Containers::Array<MaterialTagEntry> m_tags;
|
|
ShaderKeywordSet m_keywordSet;
|
|
Containers::HashMap<Containers::String, MaterialProperty> m_properties;
|
|
Containers::Array<MaterialConstantFieldDesc> m_constantLayout;
|
|
Containers::Array<Core::uint8> m_constantBufferData;
|
|
Containers::Array<MaterialTextureBinding> m_textureBindings;
|
|
Containers::Array<MaterialBufferBinding> m_bufferBindings;
|
|
Core::uint64 m_changeVersion = 1;
|
|
};
|
|
|
|
} // namespace Resources
|
|
} // namespace XCEngine
|