// 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 #include #include #include #include namespace Nz { template class Vector2; template class Vector3; template class Vector4; template struct TypeToMaterialPropertyType { static_assert(AlwaysFalse(), "T is not a valid type for material property"); }; template<> struct TypeToMaterialPropertyType { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Bool; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Bool2; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Bool3; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Bool4; }; template<> struct TypeToMaterialPropertyType { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Color; }; template<> struct TypeToMaterialPropertyType { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Float; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Float2; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Float3; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Float4; }; template<> struct TypeToMaterialPropertyType { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Int; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Int2; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Int3; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::Int4; }; template<> struct TypeToMaterialPropertyType { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::UInt; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::UInt2; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::UInt3; }; template<> struct TypeToMaterialPropertyType> { static constexpr MaterialPropertyType PropertyType = MaterialPropertyType::UInt4; }; template struct MaterialPropertyTypeInfo { }; template struct MaterialPropertyTypeInfoPrimitive { using Type = T; using BufferType = T; using OptionType = T; static Type DecodeFromBuffer(BufferType value) { return value; } static Type DecodeFromOption(OptionType value) { return value; } static BufferType EncodeToBuffer(Type value) { return value; } static OptionType EncodeToOption(Type value) { return value; } }; template struct MaterialPropertyTypeInfoVector; template struct MaterialPropertyTypeInfoVector { using Type = Vector2; using BufferType = nzsl::Vector2; using OptionType = nzsl::Vector2; static Type DecodeFromBuffer(BufferType value) { return { value.x(), value.y() }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y }; } }; template struct MaterialPropertyTypeInfoVector { using Type = Vector3; using BufferType = nzsl::Vector3; using OptionType = nzsl::Vector3; static Type DecodeFromBuffer(BufferType value) { return { value.x(), value.y(), value.z() }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y(), value.z() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y, value.z }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y, value.z }; } }; template struct MaterialPropertyTypeInfoVector { using Type = Vector4; using BufferType = nzsl::Vector4; using OptionType = nzsl::Vector4; static Type DecodeFromBuffer(BufferType value) { return { value.x(), value.y(), value.z(), value.w() }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y(), value.z(), value.w() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y, value.z, value.w }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y, value.z, value.w }; } }; template<> struct MaterialPropertyTypeInfo { using Type = bool; using BufferType = UInt32; using OptionType = bool; static Type DecodeFromBuffer(BufferType value) { return value != 0; } static Type DecodeFromOption(OptionType value) { return value; } static BufferType EncodeToBuffer(Type value) { return value; } static OptionType EncodeToOption(Type value) { return value; } }; template<> struct MaterialPropertyTypeInfo { using Type = Vector2; using BufferType = nzsl::Vector2u32; using OptionType = nzsl::Vector2; static Type DecodeFromBuffer(BufferType value) { return { value.x() != 0, value.y() != 0 }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y }; } }; template<> struct MaterialPropertyTypeInfo { using Type = Vector3; using BufferType = nzsl::Vector3u32; using OptionType = nzsl::Vector3; static Type DecodeFromBuffer(BufferType value) { return { value.x() != 0, value.y() != 0, value.z() != 0 }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y(), value.z() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y, value.z }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y, value.z }; } }; template<> struct MaterialPropertyTypeInfo { using Type = Vector4; using BufferType = nzsl::Vector4u32; using OptionType = nzsl::Vector4; static Type DecodeFromBuffer(BufferType value) { return { value.x() != 0, value.y() != 0, value.z() != 0, value.w() != 0}; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y(), value.z(), value.w() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.x, value.y, value.z, value.w }; } static OptionType EncodeToOption(Type value) { return OptionType{ value.x, value.y, value.z, value.w }; } }; template<> struct MaterialPropertyTypeInfo { using Type = Color; using BufferType = nzsl::Vector4f32; using OptionType = nzsl::Vector4f32; static Type DecodeFromBuffer(BufferType value) { return { value.x(), value.y(), value.z(), value.w() }; } static Type DecodeFromOption(OptionType value) { return { value.x(), value.y(), value.z(), value.w() }; } static BufferType EncodeToBuffer(Type value) { return BufferType{ value.r, value.g, value.b, value.a }; } static OptionType EncodeToOption(Type value) { return BufferType{ value.r, value.g, value.b, value.a }; } }; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoPrimitive {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoPrimitive {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoPrimitive {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; template<> struct MaterialPropertyTypeInfo : MaterialPropertyTypeInfoVector {}; inline void MaterialSettings::AddPass(std::size_t passIndex, MaterialPass materialPass) { if (passIndex >= m_materialPasses.size()) m_materialPasses.resize(passIndex + 1); m_materialPasses[passIndex] = std::move(materialPass); } inline void MaterialSettings::AddPropertyHandler(std::unique_ptr propertyHandler) { m_propertyHandlers.emplace_back(std::move(propertyHandler)); } inline void MaterialSettings::AddTextureProperty(std::string propertyName, ImageType propertyType) { auto& textureProperty = m_textureProperties.emplace_back(); textureProperty.name = std::move(propertyName); textureProperty.type = propertyType; } inline void MaterialSettings::AddTextureProperty(std::string propertyName, ImageType propertyType, std::shared_ptr defaultTexture) { if (defaultTexture && defaultTexture->GetType() != propertyType) throw std::runtime_error("default texture type doesn't match property image type"); auto& textureProperty = m_textureProperties.emplace_back(); textureProperty.name = std::move(propertyName); textureProperty.type = propertyType; textureProperty.defaultTexture = std::move(defaultTexture); } inline void MaterialSettings::AddTextureProperty(std::string propertyName, ImageType propertyType, std::shared_ptr defaultTexture, const TextureSamplerInfo& defaultSamplerInfo) { if (defaultTexture && defaultTexture->GetType() != propertyType) throw std::runtime_error("default texture type doesn't match property image type"); auto& textureProperty = m_textureProperties.emplace_back(); textureProperty.name = std::move(propertyName); textureProperty.type = propertyType; textureProperty.defaultTexture = std::move(defaultTexture); textureProperty.defaultSamplerInfo = defaultSamplerInfo; } inline void MaterialSettings::AddValueProperty(std::string propertyName, MaterialPropertyType propertyType, Value defaultValue) { std::visit([&](auto&& arg) { using T = std::decay_t; if constexpr (!std::is_same_v) { constexpr MaterialPropertyType valueType = TypeToMaterialPropertyType_v; if (propertyType != valueType) throw std::runtime_error("default value type doesn't match property type"); } else throw std::runtime_error("value properties must have a default value"); }, defaultValue); auto& valueProperty = m_valueProperties.emplace_back(); valueProperty.name = std::move(propertyName); valueProperty.type = propertyType; valueProperty.defaultValue = std::move(defaultValue); } inline std::size_t MaterialSettings::FindTextureProperty(std::string_view propertyName) const { for (std::size_t i = 0; i < m_textureProperties.size(); ++i) { if (m_textureProperties[i].name == propertyName) return i; } return InvalidPropertyIndex; } inline std::size_t MaterialSettings::FindValueProperty(std::string_view propertyName) const { for (std::size_t i = 0; i < m_valueProperties.size(); ++i) { if (m_valueProperties[i].name == propertyName) return i; } return InvalidPropertyIndex; } inline const MaterialPass* MaterialSettings::GetPass(std::size_t passIndex) const { if (passIndex > m_materialPasses.size() || !m_materialPasses[passIndex].has_value()) return nullptr; return &m_materialPasses[passIndex].value(); } inline const std::vector>& MaterialSettings::GetPasses() const { return m_materialPasses; } inline const std::vector>& MaterialSettings::GetPropertyHandlers() const { return m_propertyHandlers; } inline auto MaterialSettings::GetTextureProperty(std::size_t texturePropertyIndex) const -> const TextureProperty& { assert(texturePropertyIndex < m_textureProperties.size()); return m_textureProperties[texturePropertyIndex]; } inline std::size_t MaterialSettings::GetTexturePropertyCount() const { return m_textureProperties.size(); } inline auto MaterialSettings::GetValueProperty(std::size_t valuePropertyIndex) const -> const ValueProperty& { assert(valuePropertyIndex < m_valueProperties.size()); return m_valueProperties[valuePropertyIndex]; } inline std::size_t MaterialSettings::GetValuePropertyCount() const { return m_valueProperties.size(); } template void MaterialSettings::AddValueProperty(std::string propertyName) { return AddValueProperty(std::move(propertyName), TypeToMaterialPropertyType_v); } template void MaterialSettings::AddValueProperty(std::string propertyName, U&& defaultValue) { constexpr std::size_t TypeIndex = TypeListFind; auto& valueProperty = m_valueProperties.emplace_back(); valueProperty.name = std::move(propertyName); valueProperty.type = TypeToMaterialPropertyType_v; valueProperty.defaultValue.emplace(std::forward(defaultValue)); } } #include