diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli index 5e7088617b..f9ead72ce4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli @@ -70,6 +70,8 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface) float4 baseMap = 0; float2 normalMap = 0; + // Each texture array handles a size permutation. + // e.g. it could be that tex array 0 handles 256x256 and tex array 1 handles 512x64, etc. switch(textureArrayIndex) { case 0: diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp index e5bf0bd9fa..472dbff5c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp @@ -301,23 +301,50 @@ namespace AZ return; } - if (material.IsValid()) + if (GetMaterialUsedByDecal(handle) == material) { - AZ_Assert(m_decalData.GetData(handle.GetIndex()).m_textureArrayIndex == DecalData::UnusedIndex, "Setting Material on a decal more than once is not currently supported."); - - const auto iter = m_materialToTextureArrayLookupTable.find(material); - if (iter != m_materialToTextureArrayLookupTable.end()) - { - // This material is already loaded and registered with this feature processor - iter->second.m_useCount++; - SetDecalTextureLocation(handle, iter->second.m_location); - return; - } - - // Material not loaded so queue it up for loading. - QueueMaterialLoadForDecal(material, handle); return; } + + const auto decalIndex = handle.GetIndex(); + + const bool isValidMaterialBeingUsedCurrently = m_decalData.GetData(decalIndex).m_textureArrayIndex != DecalData::UnusedIndex; + if (isValidMaterialBeingUsedCurrently) + { + RemoveMaterialFromDecal(decalIndex); + } + + if (!material.IsValid()) + { + return; + } + + const auto iter = m_materialToTextureArrayLookupTable.find(material); + if (iter != m_materialToTextureArrayLookupTable.end()) + { + // This material is already loaded and registered with this feature processor + iter->second.m_useCount++; + SetDecalTextureLocation(handle, iter->second.m_location); + return; + } + + // Material not loaded so queue it up for loading. + QueueMaterialLoadForDecal(material, handle); + } + + void DecalTextureArrayFeatureProcessor::RemoveMaterialFromDecal(const uint16_t decalIndex) + { + auto& decalData = m_decalData.GetData(decalIndex); + + DecalLocation decalLocation; + decalLocation.textureArrayIndex = decalData.m_textureArrayIndex; + decalLocation.textureIndex = decalData.m_textureIndex; + RemoveDecalFromTextureArrays(decalLocation); + + decalData.m_textureArrayIndex = DecalData::UnusedIndex; + decalData.m_textureIndex = DecalData::UnusedIndex; + + m_deviceBufferNeedsUpdate = true; } void DecalTextureArrayFeatureProcessor::CacheShaderIndices() diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h index 13a6682629..fd535bbe64 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h @@ -114,6 +114,7 @@ namespace AZ AZStd::optional AddMaterialToTextureArrays(const AZ::RPI::MaterialAsset* materialAsset); int FindTextureArrayWithSize(const RHI::Size& size) const; + void RemoveMaterialFromDecal(const uint16_t decalIndex); void SetDecalTextureLocation(const DecalHandle& handle, const DecalLocation location); void QueueMaterialLoadForDecal(const AZ::Data::AssetId material, const DecalHandle handle); bool RemoveDecalFromTextureArrays(const DecalLocation decalLocation); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/DecalComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/DecalComponentController.cpp index 5d16164d92..dd8266c1ca 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/DecalComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/DecalComponentController.cpp @@ -230,7 +230,7 @@ namespace AZ { DecalNotificationBus::Event(m_entityId, &DecalNotifications::OnMaterialChanged, m_configuration.m_materialAsset); - if (m_featureProcessor && m_configuration.m_materialAsset.GetId().IsValid()) + if (m_featureProcessor) { m_featureProcessor->SetDecalMaterial(m_handle, m_configuration.m_materialAsset.GetId()); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp index c5d61dd54a..f8865e8d34 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp @@ -192,7 +192,7 @@ namespace AZ u32 EditorDecalComponent::OnConfigurationChanged() { - BaseClass::OnConfigurationChanged(); + m_controller.ConfigurationChanged(); return Edit::PropertyRefreshLevels::AttributesAndValues; }