Merge branch 'development' of https://github.com/o3de/o3de into TerrainMaterialsFix
This commit is contained in:
+170
-63
@@ -8,21 +8,19 @@
|
||||
|
||||
#include <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <GradientSignal/Ebuses/GradientRequestBus.h>
|
||||
#include <SurfaceData/SurfaceDataProviderRequestBus.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
|
||||
|
||||
#include <GradientSignal/Ebuses/GradientRequestBus.h>
|
||||
#include <SurfaceData/SurfaceDataProviderRequestBus.h>
|
||||
#include <TerrainSystem/TerrainSystemBus.h>
|
||||
|
||||
namespace Terrain
|
||||
@@ -38,15 +36,14 @@ namespace Terrain
|
||||
|
||||
if (auto edit = serialize->GetEditContext())
|
||||
{
|
||||
edit->Class<TerrainSurfaceMaterialMapping>("Terrain Surface Gradient Mapping", "Mapping between a surface and a material.")
|
||||
edit->Class<TerrainSurfaceMaterialMapping>("Terrain surface gradient mapping", "Mapping between a surface and a material.")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show)
|
||||
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", "Surface type to map to a material.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material Asset", "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface tag", "Surface type to map to a material.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material asset", "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -60,7 +57,8 @@ namespace Terrain
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<TerrainSurfaceMaterialsListConfig, AZ::ComponentConfig>()
|
||||
->Version(1)
|
||||
->Version(2)
|
||||
->Field("DefaultMaterial", &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial)
|
||||
->Field("Mappings", &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials);
|
||||
|
||||
AZ::EditContext* edit = serialize->GetEditContext();
|
||||
@@ -68,10 +66,13 @@ namespace Terrain
|
||||
{
|
||||
edit->Class<TerrainSurfaceMaterialsListConfig>(
|
||||
"Terrain Surface Material List Component", "Provide mapping between surfaces and render materials.")
|
||||
->SetDynamicEditDataProvider(&TerrainSurfaceMaterialsListConfig::GetDynamicData)
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial,
|
||||
"Default Material", "The default material to fall back to where no other material surface mappings exist.")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials,
|
||||
"Material Mappings", "Maps surfaces to materials.");
|
||||
@@ -79,6 +80,26 @@ namespace Terrain
|
||||
}
|
||||
}
|
||||
|
||||
TerrainSurfaceMaterialsListConfig::TerrainSurfaceMaterialsListConfig()
|
||||
{
|
||||
m_hideSurfaceTagData.m_attributes.push_back(
|
||||
{
|
||||
AZ::Edit::Attributes::Visibility,
|
||||
aznew AZ::Edit::AttributeData<AZ::Crc32>(AZ::Edit::PropertyVisibility::Hide)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const AZ::Edit::ElementData* TerrainSurfaceMaterialsListConfig::GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& )
|
||||
{
|
||||
const TerrainSurfaceMaterialsListConfig* owner = reinterpret_cast<const TerrainSurfaceMaterialsListConfig*>(handlerPtr);
|
||||
if (elementPtr == &owner->m_defaultSurfaceMaterial.m_surfaceTag)
|
||||
{
|
||||
return &owner->m_hideSurfaceTagData;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainMaterialProviderService"));
|
||||
@@ -116,15 +137,21 @@ namespace Terrain
|
||||
{
|
||||
m_cachedAabb = AZ::Aabb::CreateNull();
|
||||
|
||||
auto checkLoadMaterial = [&](TerrainSurfaceMaterialMapping& material)
|
||||
{
|
||||
if (material.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
material.m_active = false;
|
||||
material.m_materialAsset.QueueLoad();
|
||||
AZ::Data::AssetBus::MultiHandler::BusConnect(material.m_materialAsset.GetId());
|
||||
}
|
||||
};
|
||||
|
||||
// Set all the materials as inactive and start loading.
|
||||
checkLoadMaterial(m_configuration.m_defaultSurfaceMaterial);
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
surfaceMaterialMapping.m_active = false;
|
||||
surfaceMaterialMapping.m_materialAsset.QueueLoad();
|
||||
AZ::Data::AssetBus::MultiHandler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId());
|
||||
}
|
||||
checkLoadMaterial(surfaceMaterialMapping);
|
||||
}
|
||||
|
||||
// Announce initial shape using OnShapeChanged
|
||||
@@ -135,24 +162,35 @@ namespace Terrain
|
||||
{
|
||||
TerrainAreaMaterialRequestBus::Handler::BusDisconnect();
|
||||
|
||||
auto checkResetMaterial = [&](TerrainSurfaceMaterialMapping& material)
|
||||
{
|
||||
if (material.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect(material.m_materialAsset.GetId());
|
||||
material.m_materialAsset.Release();
|
||||
material.m_materialInstance.reset();
|
||||
material.m_activeMaterialAssetId = AZ::Data::AssetId();
|
||||
}
|
||||
};
|
||||
|
||||
checkResetMaterial(m_configuration.m_defaultSurfaceMaterial);
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId());
|
||||
surfaceMaterialMapping.m_materialAsset.Release();
|
||||
surfaceMaterialMapping.m_materialInstance.reset();
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId();
|
||||
}
|
||||
checkResetMaterial(surfaceMaterialMapping);
|
||||
}
|
||||
|
||||
HandleMaterialStateChanges();
|
||||
}
|
||||
|
||||
int TerrainSurfaceMaterialsListComponent::CountMaterialIDInstances(AZ::Data::AssetId id) const
|
||||
int TerrainSurfaceMaterialsListComponent::CountMaterialIdInstances(AZ::Data::AssetId id) const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (m_configuration.m_defaultSurfaceMaterial.m_activeMaterialAssetId == id)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
for (const auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_activeMaterialAssetId == id)
|
||||
@@ -169,28 +207,63 @@ namespace Terrain
|
||||
bool anyMaterialIsActive = false;
|
||||
bool anyMaterialWasAlreadyActive = false;
|
||||
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
const bool wasPreviouslyActive = surfaceMaterialMapping.m_active;
|
||||
const bool isNowActive = (surfaceMaterialMapping.m_materialInstance != nullptr);
|
||||
// Handle default material first
|
||||
auto& defaultMaterial = m_configuration.m_defaultSurfaceMaterial;
|
||||
|
||||
if (wasPreviouslyActive)
|
||||
{
|
||||
anyMaterialWasAlreadyActive = true;
|
||||
}
|
||||
const bool wasPreviouslyActive = defaultMaterial.m_active;
|
||||
defaultMaterial.m_active = (defaultMaterial.m_materialInstance != nullptr);
|
||||
|
||||
if (isNowActive)
|
||||
{
|
||||
anyMaterialIsActive = true;
|
||||
}
|
||||
|
||||
surfaceMaterialMapping.m_active = isNowActive;
|
||||
|
||||
if (!wasPreviouslyActive && !isNowActive)
|
||||
anyMaterialWasAlreadyActive = wasPreviouslyActive;
|
||||
anyMaterialIsActive = defaultMaterial.m_active;
|
||||
|
||||
if (!wasPreviouslyActive && !defaultMaterial.m_active)
|
||||
{
|
||||
// A material has been assigned but has not yet completed loading.
|
||||
}
|
||||
else if (!wasPreviouslyActive && isNowActive)
|
||||
else if (!wasPreviouslyActive && defaultMaterial.m_active)
|
||||
{
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialCreated, GetEntityId(),
|
||||
defaultMaterial.m_materialInstance);
|
||||
defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId();
|
||||
}
|
||||
else if (wasPreviouslyActive && !defaultMaterial.m_active)
|
||||
{
|
||||
// Don't disconnect from the AssetBus if this material is mapped more than once.
|
||||
if (CountMaterialIdInstances(defaultMaterial.m_activeMaterialAssetId) == 1)
|
||||
{
|
||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect(defaultMaterial.m_activeMaterialAssetId);
|
||||
}
|
||||
defaultMaterial = {};
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialDestroyed, GetEntityId());
|
||||
}
|
||||
else if (defaultMaterial.m_materialInstance->GetAssetId() != defaultMaterial.m_activeMaterialAssetId ||
|
||||
defaultMaterial.m_materialInstance->GetCurrentChangeId() != defaultMaterial.m_previousChangeId)
|
||||
{
|
||||
defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId();
|
||||
defaultMaterial.m_activeMaterialAssetId = defaultMaterial.m_materialInstance->GetAssetId();
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialChanged, GetEntityId(), defaultMaterial.m_materialInstance);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
const bool wasPreviouslyActive = surfaceMaterialMapping.m_active;
|
||||
surfaceMaterialMapping.m_active = surfaceMaterialMapping.m_materialInstance != nullptr;
|
||||
|
||||
anyMaterialWasAlreadyActive = anyMaterialWasAlreadyActive || wasPreviouslyActive;
|
||||
anyMaterialIsActive = anyMaterialIsActive || surfaceMaterialMapping.m_active;
|
||||
|
||||
if (!wasPreviouslyActive && !surfaceMaterialMapping.m_active)
|
||||
{
|
||||
// A material has been assigned but has not yet completed loading.
|
||||
}
|
||||
else if (!wasPreviouslyActive && surfaceMaterialMapping.m_active)
|
||||
{
|
||||
// Remember the asset id so we can disconnect from the AssetBus if the material asset is removed.
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialAsset.GetId();
|
||||
@@ -199,27 +272,47 @@ namespace Terrain
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingCreated, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag,
|
||||
surfaceMaterialMapping.m_materialInstance);
|
||||
|
||||
surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId();
|
||||
surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag;
|
||||
}
|
||||
else if (wasPreviouslyActive && !isNowActive)
|
||||
else if (wasPreviouslyActive && !surfaceMaterialMapping.m_active)
|
||||
{
|
||||
// Don't disconnect from the AssetBus if this material is mapped more than once.
|
||||
if (CountMaterialIDInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1)
|
||||
if (CountMaterialIdInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1)
|
||||
{
|
||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId);
|
||||
}
|
||||
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId();
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = {};
|
||||
surfaceMaterialMapping.m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID;
|
||||
surfaceMaterialMapping.m_previousTag = {};
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingDestroyed, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingChanged, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag,
|
||||
surfaceMaterialMapping.m_materialInstance);
|
||||
if (surfaceMaterialMapping.m_previousTag != surfaceMaterialMapping.m_surfaceTag)
|
||||
{
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingTagChanged, GetEntityId(),
|
||||
surfaceMaterialMapping.m_previousTag,
|
||||
surfaceMaterialMapping.m_surfaceTag);
|
||||
surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag;
|
||||
}
|
||||
if (surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_activeMaterialAssetId ||
|
||||
surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId() != surfaceMaterialMapping.m_previousChangeId)
|
||||
{
|
||||
surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId();
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialInstance->GetAssetId();
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingMaterialChanged, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag,
|
||||
surfaceMaterialMapping.m_materialInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,14 +383,28 @@ namespace Terrain
|
||||
void TerrainSurfaceMaterialsListComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
// Find the missing material instance with the correct id.
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
auto checkUpdateMaterialAsset = [](TerrainSurfaceMaterialMapping& mapping, const AZ::Data::Asset<AZ::Data::AssetData>& asset) -> bool
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId() == asset.GetId() &&
|
||||
(!surfaceMaterialMapping.m_materialInstance ||
|
||||
surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_materialAsset.GetId()))
|
||||
if (mapping.m_materialAsset.GetId() == asset.GetId() &&
|
||||
(!mapping.m_materialInstance || mapping.m_materialInstance->GetAssetId() != mapping.m_materialAsset.GetId()))
|
||||
{
|
||||
surfaceMaterialMapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(surfaceMaterialMapping.m_materialAsset);
|
||||
surfaceMaterialMapping.m_materialAsset.Release();
|
||||
mapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(mapping.m_materialAsset);
|
||||
mapping.m_materialAsset.Release();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// First check the default material
|
||||
if (!checkUpdateMaterialAsset(m_configuration.m_defaultSurfaceMaterial, asset))
|
||||
{
|
||||
// If the default materail wasn't updated, then check all the surface material mappings.
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (checkUpdateMaterialAsset(surfaceMaterialMapping, asset))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
HandleMaterialStateChanges();
|
||||
|
||||
+20
-7
@@ -8,15 +8,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
#include <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
|
||||
#include <LmbrCentral/Shape/ShapeComponentBus.h>
|
||||
|
||||
#include <SurfaceData/SurfaceDataTypes.h>
|
||||
#include <TerrainRenderer/TerrainAreaMaterialRequestBus.h>
|
||||
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
template<typename, typename>
|
||||
@@ -27,16 +30,20 @@ namespace Terrain
|
||||
{
|
||||
struct TerrainSurfaceMaterialMapping final
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(TerrainSurfaceMaterialMapping, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(TerrainSurfaceMaterialMapping, "{37D2A586-CDDD-4FB7-A7D6-0B4CC575AB8C}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SurfaceData::SurfaceTag m_surfaceTag;
|
||||
AZ::Data::AssetId m_activeMaterialAssetId;
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialAsset;
|
||||
AZ::Data::Instance<AZ::RPI::Material> m_materialInstance;
|
||||
|
||||
AZ::Data::AssetId m_activeMaterialAssetId;
|
||||
AZ::RPI::Material::ChangeId m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID;
|
||||
|
||||
// Surface tags not used by default material
|
||||
SurfaceData::SurfaceTag m_surfaceTag;
|
||||
SurfaceData::SurfaceTag m_previousTag;
|
||||
|
||||
bool m_active = false;
|
||||
};
|
||||
|
||||
@@ -47,7 +54,13 @@ namespace Terrain
|
||||
AZ_RTTI(TerrainSurfaceMaterialsListConfig, "{68A1CB1B-C835-4C3A-8D1C-08692E07711A}", AZ::ComponentConfig);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
TerrainSurfaceMaterialsListConfig();
|
||||
|
||||
TerrainSurfaceMaterialMapping m_defaultSurfaceMaterial;
|
||||
AZStd::vector<TerrainSurfaceMaterialMapping> m_surfaceMaterials;
|
||||
private:
|
||||
static const AZ::Edit::ElementData* GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& elementType);
|
||||
AZ::Edit::ElementData m_hideSurfaceTagData;
|
||||
};
|
||||
|
||||
class TerrainSurfaceMaterialsListComponent
|
||||
@@ -78,7 +91,7 @@ namespace Terrain
|
||||
|
||||
private:
|
||||
void HandleMaterialStateChanges();
|
||||
int CountMaterialIDInstances(AZ::Data::AssetId id) const;
|
||||
int CountMaterialIdInstances(AZ::Data::AssetId id) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ShapeComponentNotificationsBus
|
||||
|
||||
@@ -45,6 +45,27 @@ namespace Terrain
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! The default surface material has been assigned and loaded
|
||||
virtual void OnTerrainDefaultSurfaceMaterialCreated(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] AZ::Data::Instance<AZ::RPI::Material> material)
|
||||
{
|
||||
}
|
||||
|
||||
//! The default surface material has been unassigned
|
||||
virtual void OnTerrainDefaultSurfaceMaterialDestroyed(
|
||||
[[maybe_unused]] AZ::EntityId entityId)
|
||||
{
|
||||
}
|
||||
|
||||
//! The default surface material has been changed to a different material
|
||||
virtual void OnTerrainDefaultSurfaceMaterialChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] AZ::Data::Instance<AZ::RPI::Material> newMaterial)
|
||||
{
|
||||
}
|
||||
|
||||
//! A loaded material mapped to a valid surface tag has been created
|
||||
virtual void OnTerrainSurfaceMaterialMappingCreated(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface,
|
||||
@@ -52,19 +73,30 @@ namespace Terrain
|
||||
{
|
||||
}
|
||||
|
||||
//! Either the material or surface tag was unassigned, making this mapping invalid
|
||||
virtual void OnTerrainSurfaceMaterialMappingDestroyed(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnTerrainSurfaceMaterialMappingChanged(
|
||||
//! The surface tag has changed to tag for an existing material
|
||||
virtual void OnTerrainSurfaceMaterialMappingTagChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag oldSurface,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag newSurface)
|
||||
{
|
||||
}
|
||||
|
||||
//! The material has changed for an existing surface tag
|
||||
virtual void OnTerrainSurfaceMaterialMappingMaterialChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface,
|
||||
[[maybe_unused]] AZ::Data::Instance<AZ::RPI::Material> material)
|
||||
{
|
||||
}
|
||||
|
||||
//! The bounds of this set of surface material mappings has changed
|
||||
virtual void OnTerrainSurfaceMaterialMappingRegionChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] const AZ::Aabb& oldRegion,
|
||||
|
||||
@@ -106,6 +106,8 @@ namespace Terrain
|
||||
return;
|
||||
}
|
||||
|
||||
InitializePassthroughDetailMaterial();
|
||||
|
||||
ClipmapBoundsDescriptor desc;
|
||||
desc.m_clipmapUpdateMultiple = 1;
|
||||
desc.m_clipToWorldScale = DetailTextureScale;
|
||||
@@ -260,20 +262,73 @@ namespace Terrain
|
||||
m_dirtyDetailRegion.AddAabb(dirtyRegion);
|
||||
}
|
||||
}
|
||||
|
||||
bool TerrainDetailMaterialManager::ForSurfaceTag(DetailMaterialListRegion& materialRegion,
|
||||
SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback)
|
||||
{
|
||||
for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces)
|
||||
{
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
callback(surface);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, MaterialInstance material)
|
||||
{
|
||||
DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions);
|
||||
AZ_Error("TerrainDetailMaterialManager", materialRegion.m_defaultDetailMaterialId == InvalidDetailMaterailId,
|
||||
"Default detail material created but was already set for this region.");
|
||||
|
||||
materialRegion.m_defaultDetailMaterialId = CreateOrUpdateDetailMaterial(material);
|
||||
m_detailMaterials.GetData(materialRegion.m_defaultDetailMaterialId).refCount++;
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId)
|
||||
{
|
||||
DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions);
|
||||
if (materialRegion == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialDestroyed() called for region that doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId);
|
||||
materialRegion->m_defaultDetailMaterialId = InvalidDetailMaterailId;
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, MaterialInstance newMaterial)
|
||||
{
|
||||
DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions);
|
||||
if (materialRegion == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialChanged() called for region that doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update existing entry or create a new material entry
|
||||
uint16_t materialId = CreateOrUpdateDetailMaterial(newMaterial);
|
||||
if (materialRegion->m_defaultDetailMaterialId != materialId)
|
||||
{
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId);
|
||||
materialRegion->m_defaultDetailMaterialId = materialId;
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material)
|
||||
{
|
||||
DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions);
|
||||
|
||||
// Validate that the surface tag is new
|
||||
for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces)
|
||||
ForSurfaceTag(materialRegion, surfaceTag, [](DetailMaterialSurface&)
|
||||
{
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag.");
|
||||
});
|
||||
|
||||
uint16_t detailMaterialId = CreateOrUpdateDetailMaterial(material);
|
||||
materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, detailMaterialId });
|
||||
@@ -284,52 +339,71 @@ namespace Terrain
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag)
|
||||
{
|
||||
DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions);
|
||||
|
||||
for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces)
|
||||
|
||||
[[maybe_unused]] bool found = ForSurfaceTag(materialRegion, surfaceTag,
|
||||
[&](DetailMaterialSurface& surface)
|
||||
{
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
|
||||
if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag)
|
||||
{
|
||||
AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back());
|
||||
}
|
||||
materialRegion.m_materialsForSurfaces.pop_back();
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
return;
|
||||
if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag)
|
||||
{
|
||||
AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back());
|
||||
}
|
||||
materialRegion.m_materialsForSurfaces.pop_back();
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
return;
|
||||
});
|
||||
|
||||
AZ_Error(TerrainDetailMaterialManagerName, found, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed().");
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingMaterialChanged(
|
||||
AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material)
|
||||
{
|
||||
DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions);
|
||||
if (materialRegion == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for region that doesn't exist.");
|
||||
return;
|
||||
}
|
||||
AZ_Error(TerrainDetailMaterialManagerName, false, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed().");
|
||||
|
||||
// Update existing entry or create a new material entry
|
||||
uint16_t materialId = CreateOrUpdateDetailMaterial(material);
|
||||
|
||||
[[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, surfaceTag,
|
||||
[&](DetailMaterialSurface& surface)
|
||||
{
|
||||
if (surface.m_detailMaterialId != materialId)
|
||||
{
|
||||
// Updated material was a different asset than the old material, decrement ref count and
|
||||
// delete if no other surface tags are using it.
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
surface.m_detailMaterialId = materialId;
|
||||
}
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion->m_region);
|
||||
});
|
||||
|
||||
AZ_Assert(found, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for tag that doesn't exist.");
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material)
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingTagChanged(
|
||||
AZ::EntityId entityId, SurfaceData::SurfaceTag oldTag, SurfaceData::SurfaceTag newTag)
|
||||
{
|
||||
DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions);
|
||||
|
||||
bool found = false;
|
||||
uint16_t materialId = CreateOrUpdateDetailMaterial(material);
|
||||
for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces)
|
||||
DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions);
|
||||
if (materialRegion == nullptr)
|
||||
{
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
found = true;
|
||||
if (surface.m_detailMaterialId != materialId)
|
||||
{
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
surface.m_detailMaterialId = materialId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
AZ_Assert(false, "OnTerrainSurfaceMaterialMappingTagChanged() called for region that doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
|
||||
[[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, oldTag,
|
||||
[&](DetailMaterialSurface& surface)
|
||||
{
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, materialId });
|
||||
}
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
surface.m_surfaceTag = newTag;
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion->m_region);
|
||||
});
|
||||
AZ_Assert(found, "OnTerrainSurfaceMaterialMappingTagChanged() called for tag that doesn't exist.");
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion)
|
||||
@@ -667,23 +741,38 @@ namespace Terrain
|
||||
bool isFirstMaterial = true;
|
||||
float firstWeight = 0.0f;
|
||||
AZ::Vector2 position(surfacePoint.m_position.GetX(), surfacePoint.m_position.GetY());
|
||||
const DetailMaterialListRegion* region = FindRegionForPosition(position);
|
||||
|
||||
if (region == nullptr)
|
||||
{
|
||||
pixels.at(index).m_material1 = m_passthroughMaterialId;
|
||||
++index;
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& surfaceTagWeight : surfacePoint.m_surfaceTags)
|
||||
{
|
||||
if (surfaceTagWeight.m_weight > 0.0f)
|
||||
{
|
||||
AZ::Crc32 surfaceType = surfaceTagWeight.m_surfaceType;
|
||||
uint16_t materialId = GetDetailMaterialForSurfaceTypeAndPosition(surfaceType, position);
|
||||
if (materialId != m_detailMaterials.NoFreeSlot && materialId < 255)
|
||||
uint16_t materialId = GetDetailMaterialForSurfaceType(*region, surfaceType);
|
||||
if (materialId < 255)
|
||||
{
|
||||
if (isFirstMaterial)
|
||||
{
|
||||
// First material is valid. Save its weight to calculate blend later
|
||||
pixels.at(index).m_material1 = aznumeric_cast<uint8_t>(materialId);
|
||||
firstWeight = surfaceTagWeight.m_weight;
|
||||
// m_blend only needs to be calculated is material 2 is found, otherwise the initial value of 0 is correct.
|
||||
isFirstMaterial = false;
|
||||
static constexpr float MaxValueBeforeRounding = 254.5f / 255.0f;
|
||||
if (firstWeight >= MaxValueBeforeRounding)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second material is valid, weight is relative based on first material's weight.
|
||||
pixels.at(index).m_material2 = aznumeric_cast<uint8_t>(materialId);
|
||||
float totalWeight = firstWeight + surfaceTagWeight.m_weight;
|
||||
float blendWeight = 1.0f - (firstWeight / totalWeight);
|
||||
@@ -691,11 +780,37 @@ namespace Terrain
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue; // search for second material
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // since the list is ordered, no other materials are in the list with positive weights.
|
||||
// No more valid materials in list since surfaceTagWeight is ordered.
|
||||
|
||||
uint8_t defaultMaterial = region->m_defaultDetailMaterialId == InvalidDetailMaterailId ? m_passthroughMaterialId :
|
||||
aznumeric_cast<uint8_t>(m_detailMaterials.GetData(region->m_defaultDetailMaterialId).m_detailMaterialBufferIndex);
|
||||
|
||||
if (isFirstMaterial)
|
||||
{
|
||||
// Only one material and it's the default material.
|
||||
pixels.at(index).m_material1 = defaultMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second material is default, weight is exactly what the first material requested
|
||||
pixels.at(index).m_material2 = defaultMaterial;
|
||||
float blendWeight = 1.0f - AZStd::clamp<float>(firstWeight, 0.0f, 1.0f);
|
||||
pixels.at(index).m_blend = aznumeric_cast<uint8_t>(AZStd::round(blendWeight * 255.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (pixels.at(index).m_material1 == pixels.at(index).m_material2)
|
||||
{
|
||||
// If the materials are the same, then make the blend 100% on the first id so the shader
|
||||
// doesn't blend identical materials
|
||||
pixels.at(index).m_blend = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
};
|
||||
@@ -723,23 +838,37 @@ namespace Terrain
|
||||
|
||||
m_detailTextureImage->UpdateImageContents(imageUpdateRequest);
|
||||
}
|
||||
|
||||
uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position)
|
||||
|
||||
uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const
|
||||
{
|
||||
for (const auto& materialSurface : materialRegion.m_materialsForSurfaces)
|
||||
{
|
||||
if (materialSurface.m_surfaceTag == surfaceType)
|
||||
{
|
||||
return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex;
|
||||
}
|
||||
}
|
||||
return InvalidDetailMaterailId;
|
||||
}
|
||||
|
||||
auto TerrainDetailMaterialManager::FindRegionForPosition(const AZ::Vector2& position) const -> const DetailMaterialListRegion*
|
||||
{
|
||||
for (const auto& materialRegion : m_detailMaterialRegions.GetDataVector())
|
||||
{
|
||||
if (materialRegion.m_region.Contains(AZ::Vector3(position.GetX(), position.GetY(), 0.0f)))
|
||||
{
|
||||
for (const auto& materialSurface : materialRegion.m_materialsForSurfaces)
|
||||
{
|
||||
if (materialSurface.m_surfaceTag == surfaceType)
|
||||
{
|
||||
return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex;
|
||||
}
|
||||
}
|
||||
return &materialRegion;
|
||||
}
|
||||
}
|
||||
return m_detailMaterials.NoFreeSlot;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TerrainDetailMaterialManager::InitializePassthroughDetailMaterial()
|
||||
{
|
||||
m_passthroughMaterialId = aznumeric_cast<uint8_t>(m_detailMaterialShaderData.Reserve());
|
||||
DetailMaterialShaderData& materialShaderData = m_detailMaterialShaderData.GetElement(m_passthroughMaterialId);
|
||||
// Material defaults to white (1.0, 1.0, 1.0), set the blend mode to multiply so it passes through to the macro material.
|
||||
materialShaderData.m_flags = DetailTextureFlags::BlendModeMultiply;
|
||||
}
|
||||
|
||||
auto TerrainDetailMaterialManager::FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector<DetailMaterialListRegion>& container)
|
||||
@@ -784,5 +913,5 @@ namespace Terrain
|
||||
}
|
||||
AZ_Assert(false, "Entity Id not found in container.")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/std/function/function_template.h>
|
||||
|
||||
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
|
||||
|
||||
@@ -151,7 +152,11 @@ namespace Terrain
|
||||
AZ::EntityId m_entityId;
|
||||
AZ::Aabb m_region{AZ::Aabb::CreateNull()};
|
||||
AZStd::vector<DetailMaterialSurface> m_materialsForSurfaces;
|
||||
uint16_t m_defaultDetailMaterialId;
|
||||
};
|
||||
|
||||
using DetailMaterialContainer = AZ::Render::IndexedDataVector<DetailMaterialData>;
|
||||
static constexpr auto InvalidDetailMaterailId = DetailMaterialContainer::NoFreeSlot;
|
||||
|
||||
// System-level parameters
|
||||
static constexpr int32_t DetailTextureSize{ 1024 };
|
||||
@@ -162,9 +167,14 @@ namespace Terrain
|
||||
void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override;
|
||||
|
||||
// TerrainAreaMaterialNotificationBus overrides...
|
||||
void OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, AZ::Data::Instance<AZ::RPI::Material> material) override;
|
||||
void OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId) override;
|
||||
void OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, AZ::Data::Instance<AZ::RPI::Material> newMaterial) override;
|
||||
void OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override;
|
||||
void OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag) override;
|
||||
void OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override;
|
||||
void OnTerrainSurfaceMaterialMappingMaterialChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override;
|
||||
void OnTerrainSurfaceMaterialMappingTagChanged(
|
||||
AZ::EntityId entityId, SurfaceData::SurfaceTag oldSurfaceTag, SurfaceData::SurfaceTag newSurfaceTag) override;
|
||||
void OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) override;
|
||||
|
||||
//! Removes all images from all detail materials from the bindless image array
|
||||
@@ -186,22 +196,32 @@ namespace Terrain
|
||||
//! Updates the detail texture in a given area
|
||||
void UpdateDetailTexture(const AZ::Aabb& worldUpdateAabb, const Aabb2i& textureUpdateAabb);
|
||||
|
||||
//! Finds the detail material Id for a surface type and position
|
||||
uint16_t GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position);
|
||||
//! Finds the detail material Id for a region and surface type
|
||||
uint16_t GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const;
|
||||
|
||||
//! Finds a region for a position. Returns nullptr if none found.
|
||||
const DetailMaterialListRegion* FindRegionForPosition(const AZ::Vector2& position) const;
|
||||
|
||||
//! Initializes shader data for the default passthrough material which is used when no other detail material is found.
|
||||
void InitializePassthroughDetailMaterial();
|
||||
|
||||
using DefaultMaterialSurfaceCallback = AZStd::function<void(DetailMaterialSurface&)>;
|
||||
bool ForSurfaceTag(DetailMaterialListRegion& materialRegion,
|
||||
SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback);
|
||||
DetailMaterialListRegion* FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector<DetailMaterialListRegion>& container);
|
||||
DetailMaterialListRegion& FindOrCreateByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector<DetailMaterialListRegion>& container);
|
||||
void RemoveByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector<DetailMaterialListRegion>& container);
|
||||
|
||||
|
||||
AZStd::shared_ptr<AZ::Render::BindlessImageArrayHandler> m_bindlessImageHandler;
|
||||
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> m_detailTextureImage;
|
||||
|
||||
AZ::Render::IndexedDataVector<DetailMaterialData> m_detailMaterials;
|
||||
DetailMaterialContainer m_detailMaterials;
|
||||
AZ::Render::IndexedDataVector<DetailMaterialListRegion> m_detailMaterialRegions;
|
||||
AZ::Render::SparseVector<DetailMaterialShaderData> m_detailMaterialShaderData;
|
||||
AZ::Render::GpuBufferHandler m_detailMaterialDataBuffer;
|
||||
|
||||
uint8_t m_passthroughMaterialId = 0;
|
||||
|
||||
AZ::Aabb m_dirtyDetailRegion{ AZ::Aabb::CreateNull() };
|
||||
ClipmapBounds m_detailMaterialIdBounds;
|
||||
|
||||
@@ -212,6 +232,6 @@ namespace Terrain
|
||||
bool m_isInitialized{ false };
|
||||
bool m_detailMaterialBufferNeedsUpdate{ false };
|
||||
bool m_detailImageNeedsUpdate{ false };
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user