NazaraEngine/include/Nazara/Graphics/MaterialInstance.hpp

172 lines
7.2 KiB
C++

// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_GRAPHICS_MATERIALINSTANCE_HPP
#define NAZARA_GRAPHICS_MATERIALINSTANCE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/MaterialSettings.hpp>
#include <Nazara/Graphics/TransferInterface.hpp>
#include <Nazara/Renderer/RenderBufferView.hpp>
#include <Nazara/Renderer/ShaderBinding.hpp>
#include <Nazara/Utils/FunctionRef.hpp>
#include <NZSL/Ast/ConstantValue.hpp>
#include <memory>
#include <unordered_map>
#include <vector>
namespace Nz
{
struct NAZARA_GRAPHICS_API MaterialInstanceParams : ResourceParameters
{
MaterialLightingType lightingType = MaterialLightingType::None;
bool IsValid() const;
};
class Material;
class MaterialInstance;
class MaterialPipeline;
class Texture;
using MaterialInstanceLibrary = ObjectLibrary<MaterialInstance>;
using MaterialInstanceLoader = ResourceLoader<MaterialInstance, MaterialInstanceParams>;
using MaterialInstanceManager = ResourceManager<MaterialInstance, MaterialInstanceParams>;
using MaterialInstanceSaver = ResourceSaver<MaterialInstance, MaterialInstanceParams>;
class NAZARA_GRAPHICS_API MaterialInstance : public Resource, public TransferInterface
{
struct CopyToken {};
public:
using Params = MaterialInstanceParams;
MaterialInstance(std::shared_ptr<const Material> parent);
MaterialInstance(const MaterialInstance&) = delete;
MaterialInstance(const MaterialInstance& material, CopyToken);
MaterialInstance(MaterialInstance&&) = delete;
~MaterialInstance();
inline std::shared_ptr<MaterialInstance> Clone() const;
void DisablePass(std::string_view passName);
inline void DisablePass(std::size_t passIndex);
void EnablePass(std::string_view passName, bool enable = true);
inline void EnablePass(std::size_t passIndex, bool enable = true);
void FillShaderBinding(std::vector<ShaderBinding::Binding>& bindings) const;
inline std::size_t FindTextureProperty(std::string_view propertyName) const;
inline std::size_t FindValueProperty(std::string_view propertyName) const;
inline const std::shared_ptr<const Material>& GetParentMaterial() const;
inline MaterialPassFlags GetPassFlags(std::size_t passIndex) const;
const std::shared_ptr<MaterialPipeline>& GetPipeline(std::size_t passIndex) const;
inline const std::shared_ptr<Texture>* GetTextureProperty(std::string_view propertyName) const;
inline const std::shared_ptr<Texture>& GetTextureProperty(std::size_t textureIndex) const;
inline const std::shared_ptr<Texture>& GetTexturePropertyOverride(std::size_t textureIndex) const;
inline const TextureSamplerInfo* GetTextureSamplerProperty(std::string_view propertyName) const;
inline const TextureSamplerInfo& GetTextureSamplerProperty(std::size_t textureIndex) const;
inline const MaterialSettings::Value* GetValueProperty(std::string_view propertyName) const;
inline const MaterialSettings::Value& GetValueProperty(std::size_t valueIndex) const;
inline const MaterialSettings::Value& GetValuePropertyOverride(std::size_t valueIndex) const;
bool HasPass(std::string_view passName) const;
inline bool HasPass(std::size_t passIndex) const;
void OnTransfer(RenderFrame& renderFrame, CommandBufferBuilder& builder) override;
inline void SetTextureProperty(std::string_view propertyName, std::shared_ptr<Texture> texture);
inline void SetTextureProperty(std::string_view propertyName, std::shared_ptr<Texture> texture, const TextureSamplerInfo& samplerInfo);
void SetTextureProperty(std::size_t textureIndex, std::shared_ptr<Texture> texture);
void SetTextureProperty(std::size_t textureIndex, std::shared_ptr<Texture> texture, const TextureSamplerInfo& samplerInfo);
inline void SetTextureSamplerProperty(std::string_view propertyName, const TextureSamplerInfo& samplerInfo);
void SetTextureSamplerProperty(std::size_t textureIndex, const TextureSamplerInfo& samplerInfo);
inline void SetValueProperty(std::string_view propertyName, const MaterialSettings::Value& value);
void SetValueProperty(std::size_t valueIndex, const MaterialSettings::Value& value);
void UpdateOptionValue(UInt32 optionHash, const nzsl::Ast::ConstantSingleValue& value);
void UpdatePassFlags(std::string_view passName, MaterialPassFlags materialFlags);
inline void UpdatePassFlags(std::size_t passName, MaterialPassFlags materialFlags);
void UpdatePassStates(std::string_view passName, FunctionRef<bool(RenderStates&)> stateUpdater);
template<typename F> void UpdatePassStates(std::size_t passIndex, F&& stateUpdater);
void UpdateTextureBinding(std::size_t textureBinding, std::shared_ptr<Texture> texture, std::shared_ptr<TextureSampler> textureSampler);
void UpdateUniformBufferData(std::size_t uniformBufferIndex, std::size_t offset, std::size_t size, const void* data);
MaterialInstance& operator=(const MaterialInstance&) = delete;
MaterialInstance& operator=(MaterialInstance&&) = delete;
static constexpr std::size_t InvalidPropertyIndex = MaterialSettings::InvalidPropertyIndex;
static std::shared_ptr<MaterialInstance> LoadFromFile(const std::filesystem::path& filePath, const MaterialInstanceParams& params = MaterialInstanceParams());
static std::shared_ptr<MaterialInstance> LoadFromMemory(const void* data, std::size_t size, const MaterialInstanceParams& params = MaterialInstanceParams());
static std::shared_ptr<MaterialInstance> LoadFromStream(Stream& stream, const MaterialInstanceParams& params = MaterialInstanceParams());
NazaraSignal(OnMaterialInstancePipelineInvalidated, const MaterialInstance* /*matInstance*/, std::size_t /*passIndex*/);
NazaraSignal(OnMaterialInstanceShaderBindingInvalidated, const MaterialInstance* /*matInstance*/);
private:
inline void InvalidatePassPipeline(std::size_t passIndex);
inline void InvalidateShaderBinding();
struct PassShader
{
std::shared_ptr<UberShader> shader;
NazaraSlot(UberShader, OnShaderUpdated, onShaderUpdated);
};
struct PassData
{
mutable MaterialPipelineInfo pipelineInfo;
mutable std::shared_ptr<MaterialPipeline> pipeline;
std::vector<PassShader> shaders;
MaterialPassFlags flags;
bool enabled = false;
};
struct TextureBinding
{
std::shared_ptr<Texture> texture;
std::shared_ptr<TextureSampler> sampler;
};
struct TextureProperty
{
std::shared_ptr<Texture> texture;
TextureSamplerInfo samplerInfo;
};
struct UniformBuffer
{
std::size_t bufferIndex;
std::vector<UInt8> values;
RenderBufferView bufferView;
bool dataInvalidated = true;
};
std::shared_ptr<const Material> m_parent;
std::unordered_map<UInt32, nzsl::Ast::ConstantSingleValue> m_optionValuesOverride;
std::vector<MaterialSettings::Value> m_valueOverride;
std::vector<PassData> m_passes;
std::vector<TextureBinding> m_textureBinding;
std::vector<TextureProperty> m_textureOverride;
std::vector<UniformBuffer> m_uniformBuffers;
const MaterialSettings& m_materialSettings;
};
}
#include <Nazara/Graphics/MaterialInstance.inl>
#endif // NAZARA_GRAPHICS_MATERIALINSTANCE_HPP