// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/Color.h"
#include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Types/StringView.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Scripting/ScriptingObjectReference.h"
#include "Engine/Content/Assets/Texture.h"
#include "Engine/Content/AssetReference.h"
class MaterialInstance;
class MaterialParams;
class GPUContext;
class GPUTextureView;
class RenderBuffers;
struct MaterialParamsLink
{
MaterialParams* This;
MaterialParamsLink* Up;
MaterialParamsLink* Down;
};
///
/// The material parameter types.
///
API_ENUM() enum class MaterialParameterType : byte
{
///
/// The invalid type.
///
Invalid = 0,
///
/// The bool.
///
Bool = 1,
///
/// The integer.
///
Integer = 2,
///
/// The float.
///
Float = 3,
///
/// The vector2
///
Vector2 = 4,
///
/// The vector3.
///
Vector3 = 5,
///
/// The vector4.
///
Vector4 = 6,
///
/// The color.
///
Color = 7,
///
/// The texture.
///
Texture = 8,
///
/// The cube texture.
///
CubeTexture = 9,
///
/// The normal map texture.
///
NormalMap = 10,
///
/// The scene texture.
///
SceneTexture = 11,
///
/// The GPU texture (created from code).
///
GPUTexture = 12,
///
/// The matrix.
///
Matrix = 13,
///
/// The GPU texture array (created from code).
///
GPUTextureArray = 14,
///
/// The GPU volume texture (created from code).
///
GPUTextureVolume = 15,
///
/// The GPU cube texture (created from code).
///
GPUTextureCube = 16,
///
/// The RGBA channel selection mask.
///
ChannelMask = 17,
///
/// The gameplay global.
///
GameplayGlobal = 18,
///
/// The texture sampler derived from texture group settings.
///
TextureGroupSampler = 19,
///
/// The Global SDF (textures and constants).
///
GlobalSDF = 20,
};
///
/// Structure of serialized material parameter data.
///
struct SerializedMaterialParam
{
MaterialParameterType Type;
Guid ID;
bool IsPublic;
bool Override;
String Name;
String ShaderName;
union
{
bool AsBool;
int32 AsInteger;
float AsFloat;
Float2 AsFloat2;
Float3 AsFloat3;
Color AsColor;
Guid AsGuid;
byte AsData[16 * 4];
};
byte RegisterIndex;
uint16 Offset;
SerializedMaterialParam()
{
}
};
///
/// Material variable object. Allows to modify material parameter value at runtime.
///
API_CLASS(NoSpawn) class FLAXENGINE_API MaterialParameter : public ScriptingObject
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(MaterialParameter, ScriptingObject);
friend MaterialParams;
friend MaterialInstance;
private:
Guid _paramId;
MaterialParameterType _type = MaterialParameterType::Invalid;
bool _isPublic;
bool _override;
byte _registerIndex;
uint16 _offset;
union
{
bool _asBool;
int32 _asInteger;
float _asFloat;
Float2 _asVector2;
Float3 _asVector3;
Color _asColor;
byte AsData[16 * 4];
};
AssetReference _asAsset;
ScriptingObjectReference _asGPUTexture;
String _name;
public:
MaterialParameter(const MaterialParameter& other)
: MaterialParameter()
{
#if !BUILD_RELEASE
CRASH; // Not used
#endif
}
MaterialParameter& operator=(const MaterialParameter& other)
{
#if !BUILD_RELEASE
CRASH; // Not used
#endif
return *this;
}
public:
///
/// Gets the parameter ID (not the parameter instance Id but the original parameter ID).
///
API_PROPERTY() FORCE_INLINE Guid GetParameterID() const
{
return _paramId;
}
///
/// Gets the parameter type.
///
API_PROPERTY() FORCE_INLINE MaterialParameterType GetParameterType() const
{
return _type;
}
///
/// Gets the parameter name.
///
API_PROPERTY() FORCE_INLINE const String& GetName() const
{
return _name;
}
///
/// Returns true is parameter is public visible.
///
API_PROPERTY() FORCE_INLINE bool IsPublic() const
{
return _isPublic;
}
///
/// Returns true is parameter is overriding the value.
///
API_PROPERTY() FORCE_INLINE bool IsOverride() const
{
return _override;
}
///
/// Sets the value override mode.
///
API_PROPERTY() void SetIsOverride(bool value)
{
_override = value;
}
///
/// Gets the parameter resource graphics pipeline binding register index.
///
FORCE_INLINE byte GetRegister() const
{
return _registerIndex;
}
///
/// Gets the parameter binding offset since the start of the constant buffer.
///
FORCE_INLINE uint16 GetBindOffset() const
{
return _offset;
}
public:
///
/// Gets the value of the parameter.
///
/// The value.
API_PROPERTY() Variant GetValue() const;
///
/// Sets the value of the parameter.
///
/// The value.
API_PROPERTY() void SetValue(const Variant& value);
public:
///
/// The material parameter binding metadata.
///
struct BindMeta
{
///
/// The GPU commands context.
///
GPUContext* Context;
///
/// The pointer to the constants buffer in the memory.
///
Span Constants;
///
/// The input scene color. It's optional and used in forward/postFx rendering.
///
GPUTextureView* Input;
///
/// The scene buffers. It's optional and used in forward/postFx rendering.
///
const RenderBuffers* Buffers;
///
/// True if parameters can sample depth buffer.
///
bool CanSampleDepth;
///
/// True if parameters can sample GBuffer.
///
bool CanSampleGBuffer;
};
///
/// Binds the parameter to the pipeline.
///
/// The bind meta.
void Bind(BindMeta& meta) const;
bool HasContentLoaded() const;
private:
void clone(const MaterialParameter* param);
public:
bool operator==(const MaterialParameter& other) const;
// [Object]
String ToString() const override;
};
///
/// The collection of material parameters.
///
class FLAXENGINE_API MaterialParams : public Array
{
friend MaterialInstance;
private:
int32 _versionHash = 0;
public:
MaterialParameter* Get(const Guid& id);
MaterialParameter* Get(const StringView& name);
int32 Find(const Guid& id);
int32 Find(const StringView& name);
public:
///
/// Gets the parameters version hash. Every time the parameters are modified (loaded, edited, etc.) the hash changes. Can be used to sync instanced parameters collection.
///
int32 GetVersionHash() const;
public:
///
/// Binds the parameters to the pipeline.
///
/// The parameters binding link. Used to support per-parameter override.
/// The bind meta.
static void Bind(MaterialParamsLink* link, MaterialParameter::BindMeta& meta);
///
/// Clones the parameters list.
///
/// The result container.
void Clone(MaterialParams& result);
///
/// Releases the whole data.
///
void Dispose();
///
/// Loads material parameters from the stream.
///
/// The stream with data.
/// True if cannot load parameters for the file.
bool Load(ReadStream* stream);
///
/// Saves material parameters to the stream.
///
/// The stream with data.
void Save(WriteStream* stream);
///
/// Saves the material parameters to the stream.
///
/// The stream with data.
/// The array of parameters.
static void Save(WriteStream* stream, const Array* params);
///
/// Saves the material parameters to the bytes container.
///
/// The output data.
/// The array of parameters.
static void Save(BytesContainer& data, const Array* params);
public:
#if USE_EDITOR
///
/// Gets the asset references (see Asset.GetReferences for more info).
///
/// The output.
void GetReferences(Array& output) const;
#endif
bool HasContentLoaded() const;
private:
void UpdateHash();
};