Refactor material system (#382)
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2022 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
|
||||
|
||||
#include <Nazara/Graphics/PropertyHandler/OptionValuePropertyHandler.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Graphics/MaterialInstance.hpp>
|
||||
#include <type_traits>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool OptionValuePropertyHandler::NeedsUpdateOnValueUpdate(std::size_t updatedPropertyIndex) const
|
||||
{
|
||||
return m_propertyIndex == updatedPropertyIndex;
|
||||
}
|
||||
|
||||
void OptionValuePropertyHandler::Setup(const Material& material, const ShaderReflection& reflection)
|
||||
{
|
||||
m_propertyIndex = MaterialSettings::InvalidPropertyIndex;
|
||||
|
||||
const MaterialSettings& settings = material.GetSettings();
|
||||
|
||||
std::size_t propertyIndex = settings.FindValueProperty(m_propertyName);
|
||||
if (propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const auto& valueProperty = settings.GetValueProperty(propertyIndex);
|
||||
|
||||
if (const ShaderReflection::OptionData* optionData = reflection.GetOptionByName(m_optionName))
|
||||
{
|
||||
// TODO: Check if option type matches property type
|
||||
NazaraAssert(optionData->hash != 0, "unexpected option hash");
|
||||
m_optionHash = optionData->hash;
|
||||
m_propertyIndex = propertyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void OptionValuePropertyHandler::Update(MaterialInstance& materialInstance) const
|
||||
{
|
||||
if (m_propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const MaterialSettings::Value& value = materialInstance.GetValueProperty(m_propertyIndex);
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (!std::is_same_v<T, MaterialPropertyNoValue>)
|
||||
{
|
||||
constexpr MaterialPropertyType PropertyType = TypeToMaterialPropertyType_v<T>;
|
||||
|
||||
using BufferType = typename MaterialPropertyTypeInfo<PropertyType>::BufferType;
|
||||
|
||||
materialInstance.UpdateOptionValue(m_optionHash, MaterialPropertyTypeInfo<PropertyType>::EncodeToOption(arg));
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("value properties must have a default value");
|
||||
}, value);
|
||||
}
|
||||
}
|
||||
21
src/Nazara/Graphics/PropertyHandler/PropertyHandler.cpp
Normal file
21
src/Nazara/Graphics/PropertyHandler/PropertyHandler.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2022 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
|
||||
|
||||
#include <Nazara/Graphics/PropertyHandler/PropertyHandler.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
PropertyHandler::~PropertyHandler() = default;
|
||||
|
||||
bool PropertyHandler::NeedsUpdateOnTextureUpdate(std::size_t /*updatedTexturePropertyIndex*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyHandler::NeedsUpdateOnValueUpdate(std::size_t /*updatedValuePropertyIndex*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2022 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
|
||||
|
||||
#include <Nazara/Graphics/PropertyHandler/TexturePropertyHandler.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Graphics/MaterialInstance.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool TexturePropertyHandler::NeedsUpdateOnTextureUpdate(std::size_t updatedPropertyIndex) const
|
||||
{
|
||||
return m_propertyIndex == updatedPropertyIndex;
|
||||
}
|
||||
|
||||
void TexturePropertyHandler::Setup(const Material& material, const ShaderReflection& reflection)
|
||||
{
|
||||
m_propertyIndex = MaterialSettings::InvalidPropertyIndex;
|
||||
|
||||
const MaterialSettings& settings = material.GetSettings();
|
||||
|
||||
std::size_t propertyIndex = settings.FindTextureProperty(m_propertyName);
|
||||
if (propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const auto& textureProperty = settings.GetTextureProperty(propertyIndex);
|
||||
|
||||
m_textureIndex = material.FindTextureByTag(m_samplerTag);
|
||||
if (m_textureIndex == Material::InvalidIndex)
|
||||
return;
|
||||
|
||||
const auto& textureData = material.GetTextureData(m_textureIndex);
|
||||
if (textureProperty.type != textureData.imageType)
|
||||
{
|
||||
// TODO: Use EnumToString to show image type as string
|
||||
NazaraError("unmatching texture type: material property is of type " +
|
||||
std::to_string(UnderlyingCast(textureProperty.type)) +
|
||||
" but shader sampler is of type " +
|
||||
std::to_string(UnderlyingCast(textureData.imageType)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_propertyIndex = propertyIndex;
|
||||
|
||||
m_optionHash = 0;
|
||||
if (const ShaderReflection::OptionData* optionData = reflection.GetOptionByName(m_optionName))
|
||||
{
|
||||
if (IsPrimitiveType(optionData->type) && std::get<nzsl::Ast::PrimitiveType>(optionData->type) == nzsl::Ast::PrimitiveType::Boolean)
|
||||
{
|
||||
NazaraAssert(optionData->hash != 0, "unexpected option hash");
|
||||
m_optionHash = optionData->hash;
|
||||
}
|
||||
else
|
||||
NazaraError("option " + m_optionName + " is not a boolean option (got " + ToString(optionData->type) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
void TexturePropertyHandler::Update(MaterialInstance& materialInstance) const
|
||||
{
|
||||
if (m_propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const std::shared_ptr<Texture>& texture = materialInstance.GetTextureProperty(m_propertyIndex);
|
||||
const std::shared_ptr<TextureSampler>& sampler = Graphics::Instance()->GetSamplerCache().Get(materialInstance.GetTextureSamplerProperty(m_propertyIndex));
|
||||
|
||||
materialInstance.UpdateTextureBinding(m_textureIndex, texture, sampler);
|
||||
if (m_optionHash != 0)
|
||||
materialInstance.UpdateOptionValue(m_optionHash, texture != nullptr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2022 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
|
||||
|
||||
#include <Nazara/Graphics/PropertyHandler/UniformValuePropertyHandler.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Graphics/MaterialInstance.hpp>
|
||||
#include <type_traits>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool UniformValuePropertyHandler::NeedsUpdateOnValueUpdate(std::size_t updatedPropertyIndex) const
|
||||
{
|
||||
return m_propertyIndex == updatedPropertyIndex;
|
||||
}
|
||||
|
||||
void UniformValuePropertyHandler::Setup(const Material& material, const ShaderReflection& reflection)
|
||||
{
|
||||
m_propertyIndex = MaterialSettings::InvalidPropertyIndex;
|
||||
|
||||
const MaterialSettings& settings = material.GetSettings();
|
||||
|
||||
std::size_t propertyIndex = settings.FindValueProperty(m_propertyName);
|
||||
if (propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const auto& valueProperty = settings.GetValueProperty(propertyIndex);
|
||||
|
||||
m_uniformBlockIndex = material.FindUniformBlockByTag(m_blockTag);
|
||||
if (m_uniformBlockIndex == Material::InvalidIndex)
|
||||
return;
|
||||
|
||||
const auto& uniformBlockData = material.GetUniformBlockData(m_uniformBlockIndex);
|
||||
|
||||
const ShaderReflection::StructData* structData = reflection.GetStructByIndex(uniformBlockData.structIndex);
|
||||
NazaraAssert(structData, "invalid struct index " + std::to_string(uniformBlockData.structIndex));
|
||||
|
||||
auto it = structData->members.find(m_memberTag);
|
||||
if (it == structData->members.end())
|
||||
return;
|
||||
|
||||
m_offset = it->second.offset;
|
||||
m_size = it->second.size;
|
||||
m_propertyIndex = propertyIndex;
|
||||
|
||||
// TODO: Check if member type matches property type
|
||||
}
|
||||
|
||||
void UniformValuePropertyHandler::Update(MaterialInstance& materialInstance) const
|
||||
{
|
||||
if (m_propertyIndex == MaterialSettings::InvalidPropertyIndex)
|
||||
return;
|
||||
|
||||
const MaterialSettings::Value& value = materialInstance.GetValueProperty(m_propertyIndex);
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (!std::is_same_v<T, MaterialPropertyNoValue>)
|
||||
{
|
||||
constexpr MaterialPropertyType PropertyType = TypeToMaterialPropertyType_v<T>;
|
||||
|
||||
using BufferType = typename MaterialPropertyTypeInfo<PropertyType>::BufferType;
|
||||
|
||||
BufferType value = MaterialPropertyTypeInfo<PropertyType>::EncodeToBuffer(arg);
|
||||
assert(sizeof(value) == m_size);
|
||||
materialInstance.UpdateUniformBufferData(m_uniformBlockIndex, m_offset, m_size, &value);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("value properties must have a default value");
|
||||
}, value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user