|
|
|
@@ -67,7 +67,7 @@ namespace AZ
|
|
|
|
|
m_handleGlobalShaderOptionUpdate.Disconnect();
|
|
|
|
|
|
|
|
|
|
DisableSceneNotification();
|
|
|
|
|
AZ_Warning("MeshFeatureProcessor", m_meshData.size() == 0,
|
|
|
|
|
AZ_Warning("MeshFeatureProcessor", m_modelData.size() == 0,
|
|
|
|
|
"Deactivaing the MeshFeatureProcessor, but there are still outstanding mesh handles.\n"
|
|
|
|
|
);
|
|
|
|
|
m_transformService = nullptr;
|
|
|
|
@@ -81,7 +81,7 @@ namespace AZ
|
|
|
|
|
|
|
|
|
|
AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker);
|
|
|
|
|
|
|
|
|
|
const auto iteratorRanges = m_meshData.GetParallelRanges();
|
|
|
|
|
const auto iteratorRanges = m_modelData.GetParallelRanges();
|
|
|
|
|
AZ::JobCompletion jobCompletion;
|
|
|
|
|
for (const auto& iteratorRange : iteratorRanges)
|
|
|
|
|
{
|
|
|
|
@@ -125,11 +125,11 @@ namespace AZ
|
|
|
|
|
m_forceRebuildDrawPackets = false;
|
|
|
|
|
|
|
|
|
|
// CullingSystem::RegisterOrUpdateCullable() is not threadsafe, so need to do those updates in a single thread
|
|
|
|
|
for (MeshDataInstance& meshDataInstance : m_meshData)
|
|
|
|
|
for (ModelDataInstance& modelDataInstance : m_modelData)
|
|
|
|
|
{
|
|
|
|
|
if (meshDataInstance.m_model && meshDataInstance.m_cullBoundsNeedsUpdate)
|
|
|
|
|
if (modelDataInstance.m_model && modelDataInstance.m_cullBoundsNeedsUpdate)
|
|
|
|
|
{
|
|
|
|
|
meshDataInstance.UpdateCullBounds(m_transformService);
|
|
|
|
|
modelDataInstance.UpdateCullBounds(m_transformService);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -151,14 +151,14 @@ namespace AZ
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: AcquireMesh");
|
|
|
|
|
|
|
|
|
|
// don't need to check the concurrency during emplace() because the StableDynamicArray won't move the other elements during insertion
|
|
|
|
|
MeshHandle meshDataHandle = m_meshData.emplace();
|
|
|
|
|
MeshHandle meshDataHandle = m_modelData.emplace();
|
|
|
|
|
|
|
|
|
|
meshDataHandle->m_descriptor = descriptor;
|
|
|
|
|
meshDataHandle->m_scene = GetParentScene();
|
|
|
|
|
meshDataHandle->m_materialAssignments = materials;
|
|
|
|
|
meshDataHandle->m_objectId = m_transformService->ReserveObjectId();
|
|
|
|
|
meshDataHandle->m_originalModelAsset = descriptor.m_modelAsset;
|
|
|
|
|
meshDataHandle->m_meshLoader = AZStd::make_unique<MeshDataInstance::MeshLoader>(descriptor.m_modelAsset, &*meshDataHandle);
|
|
|
|
|
meshDataHandle->m_meshLoader = AZStd::make_unique<ModelDataInstance::MeshLoader>(descriptor.m_modelAsset, &*meshDataHandle);
|
|
|
|
|
|
|
|
|
|
return meshDataHandle;
|
|
|
|
|
}
|
|
|
|
@@ -183,7 +183,7 @@ namespace AZ
|
|
|
|
|
m_transformService->ReleaseObjectId(meshHandle->m_objectId);
|
|
|
|
|
|
|
|
|
|
AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker);
|
|
|
|
|
m_meshData.erase(meshHandle);
|
|
|
|
|
m_modelData.erase(meshHandle);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -215,9 +215,10 @@ namespace AZ
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Data::Instance<RPI::ShaderResourceGroup> MeshFeatureProcessor::GetObjectSrg(const MeshHandle& meshHandle) const
|
|
|
|
|
AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>>& MeshFeatureProcessor::GetObjectSrgs(const MeshHandle& meshHandle) const
|
|
|
|
|
{
|
|
|
|
|
return meshHandle.IsValid() ? meshHandle->m_shaderResourceGroup : nullptr;
|
|
|
|
|
static AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>> staticEmptyList;
|
|
|
|
|
return meshHandle.IsValid() ? meshHandle->m_objectSrgList : staticEmptyList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshFeatureProcessor::QueueObjectSrgForCompile(const MeshHandle& meshHandle) const
|
|
|
|
@@ -274,9 +275,9 @@ namespace AZ
|
|
|
|
|
{
|
|
|
|
|
if (meshHandle.IsValid())
|
|
|
|
|
{
|
|
|
|
|
MeshDataInstance& meshData = *meshHandle;
|
|
|
|
|
meshData.m_cullBoundsNeedsUpdate = true;
|
|
|
|
|
meshData.m_objectSrgNeedsUpdate = true;
|
|
|
|
|
ModelDataInstance& modelData = *meshHandle;
|
|
|
|
|
modelData.m_cullBoundsNeedsUpdate = true;
|
|
|
|
|
modelData.m_objectSrgNeedsUpdate = true;
|
|
|
|
|
|
|
|
|
|
m_transformService->SetTransformForId(meshHandle->m_objectId, transform, nonUniformScale);
|
|
|
|
|
|
|
|
|
@@ -292,10 +293,10 @@ namespace AZ
|
|
|
|
|
{
|
|
|
|
|
if (meshHandle.IsValid())
|
|
|
|
|
{
|
|
|
|
|
MeshDataInstance& meshData = *meshHandle;
|
|
|
|
|
meshData.m_aabb = localAabb;
|
|
|
|
|
meshData.m_cullBoundsNeedsUpdate = true;
|
|
|
|
|
meshData.m_objectSrgNeedsUpdate = true;
|
|
|
|
|
ModelDataInstance& modelData = *meshHandle;
|
|
|
|
|
modelData.m_aabb = localAabb;
|
|
|
|
|
modelData.m_cullBoundsNeedsUpdate = true;
|
|
|
|
|
modelData.m_objectSrgNeedsUpdate = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -465,7 +466,7 @@ namespace AZ
|
|
|
|
|
void MeshFeatureProcessor::UpdateMeshReflectionProbes()
|
|
|
|
|
{
|
|
|
|
|
// we need to rebuild the Srg for any meshes that are using the forward pass IBL specular option
|
|
|
|
|
for (auto& meshInstance : m_meshData)
|
|
|
|
|
for (auto& meshInstance : m_modelData)
|
|
|
|
|
{
|
|
|
|
|
if (meshInstance.m_descriptor.m_useForwardPassIblSpecular)
|
|
|
|
|
{
|
|
|
|
@@ -474,14 +475,14 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MeshDataInstance::MeshLoader...
|
|
|
|
|
MeshDataInstance::MeshLoader::MeshLoader(const Data::Asset<RPI::ModelAsset>& modelAsset, MeshDataInstance* parent)
|
|
|
|
|
// ModelDataInstance::MeshLoader...
|
|
|
|
|
ModelDataInstance::MeshLoader::MeshLoader(const Data::Asset<RPI::ModelAsset>& modelAsset, ModelDataInstance* parent)
|
|
|
|
|
: m_modelAsset(modelAsset)
|
|
|
|
|
, m_parent(parent)
|
|
|
|
|
{
|
|
|
|
|
if (!m_modelAsset.GetId().IsValid())
|
|
|
|
|
{
|
|
|
|
|
AZ_Error("MeshDataInstance::MeshLoader", false, "Invalid model asset Id.");
|
|
|
|
|
AZ_Error("ModelDataInstance::MeshLoader", false, "Invalid model asset Id.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -494,19 +495,19 @@ namespace AZ
|
|
|
|
|
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MeshDataInstance::MeshLoader::~MeshLoader()
|
|
|
|
|
ModelDataInstance::MeshLoader::~MeshLoader()
|
|
|
|
|
{
|
|
|
|
|
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
|
|
|
|
Data::AssetBus::Handler::BusDisconnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MeshFeatureProcessorInterface::ModelChangedEvent& MeshDataInstance::MeshLoader::GetModelChangedEvent()
|
|
|
|
|
MeshFeatureProcessorInterface::ModelChangedEvent& ModelDataInstance::MeshLoader::GetModelChangedEvent()
|
|
|
|
|
{
|
|
|
|
|
return m_modelChangedEvent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! AssetBus::Handler overrides...
|
|
|
|
|
void MeshDataInstance::MeshLoader::OnAssetReady(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
void ModelDataInstance::MeshLoader::OnAssetReady(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
{
|
|
|
|
|
Data::Asset<RPI::ModelAsset> modelAsset = asset;
|
|
|
|
|
|
|
|
|
@@ -527,7 +528,7 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AZ_Error("MeshDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr());
|
|
|
|
|
AZ_Error("ModelDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr());
|
|
|
|
|
model = RPI::Model::FindOrCreate(modelAsset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -547,29 +548,29 @@ namespace AZ
|
|
|
|
|
{
|
|
|
|
|
//when running with null renderer, the RPI::Model::FindOrCreate(...) is expected to return nullptr, so suppress this error.
|
|
|
|
|
AZ_Error(
|
|
|
|
|
"MeshDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'",
|
|
|
|
|
"ModelDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'",
|
|
|
|
|
asset.GetHint().c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::MeshLoader::OnModelReloaded(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
void ModelDataInstance::MeshLoader::OnModelReloaded(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
{
|
|
|
|
|
OnAssetReady(asset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::MeshLoader::OnAssetError(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
void ModelDataInstance::MeshLoader::OnAssetError(Data::Asset<Data::AssetData> asset)
|
|
|
|
|
{
|
|
|
|
|
// Note: m_modelAsset and asset represents same asset, but only m_modelAsset contains the file path in its hint from serialization
|
|
|
|
|
AZ_Error(
|
|
|
|
|
"MeshDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing",
|
|
|
|
|
"ModelDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing",
|
|
|
|
|
m_modelAsset.GetHint().c_str());
|
|
|
|
|
|
|
|
|
|
AzFramework::AssetSystemRequestBus::Broadcast(
|
|
|
|
|
&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, m_modelAsset.GetId().m_guid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
|
|
|
|
|
void ModelDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
|
|
|
|
|
{
|
|
|
|
|
if (assetId == m_modelAsset.GetId())
|
|
|
|
|
{
|
|
|
|
@@ -584,7 +585,7 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
|
|
|
|
|
void ModelDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
|
|
|
|
|
{
|
|
|
|
|
if (assetId == m_modelAsset.GetId())
|
|
|
|
|
{
|
|
|
|
@@ -599,9 +600,9 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MeshDataInstance...
|
|
|
|
|
// ModelDataInstance...
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::DeInit()
|
|
|
|
|
void ModelDataInstance::DeInit()
|
|
|
|
|
{
|
|
|
|
|
m_scene->GetCullingScene()->UnregisterCullable(m_cullable);
|
|
|
|
|
|
|
|
|
@@ -609,11 +610,11 @@ namespace AZ
|
|
|
|
|
|
|
|
|
|
m_drawPacketListsByLod.clear();
|
|
|
|
|
m_materialAssignments.clear();
|
|
|
|
|
m_shaderResourceGroup = {};
|
|
|
|
|
m_objectSrgList = {};
|
|
|
|
|
m_model = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::Init(Data::Instance<RPI::Model> model)
|
|
|
|
|
void ModelDataInstance::Init(Data::Instance<RPI::Model> model)
|
|
|
|
|
{
|
|
|
|
|
m_model = model;
|
|
|
|
|
const size_t modelLodCount = m_model->GetLodCount();
|
|
|
|
@@ -623,11 +624,11 @@ namespace AZ
|
|
|
|
|
BuildDrawPacketList(modelLodIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_shaderResourceGroup)
|
|
|
|
|
for(auto& objectSrg : m_objectSrgList)
|
|
|
|
|
{
|
|
|
|
|
// Set object Id once since it never changes
|
|
|
|
|
RHI::ShaderInputNameIndex objectIdIndex = "m_objectId";
|
|
|
|
|
m_shaderResourceGroup->SetConstant(objectIdIndex, m_objectId.GetIndex());
|
|
|
|
|
objectSrg->SetConstant(objectIdIndex, m_objectId.GetIndex());
|
|
|
|
|
objectIdIndex.AssertValid();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -643,12 +644,12 @@ namespace AZ
|
|
|
|
|
m_objectSrgNeedsUpdate = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::BuildDrawPacketList(size_t modelLodIndex)
|
|
|
|
|
void ModelDataInstance::BuildDrawPacketList(size_t modelLodIndex)
|
|
|
|
|
{
|
|
|
|
|
RPI::ModelLod& modelLod = *m_model->GetLods()[modelLodIndex];
|
|
|
|
|
const size_t meshCount = modelLod.GetMeshes().size();
|
|
|
|
|
|
|
|
|
|
MeshDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex];
|
|
|
|
|
ModelDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex];
|
|
|
|
|
drawPacketListOut.clear();
|
|
|
|
|
drawPacketListOut.reserve(meshCount);
|
|
|
|
|
|
|
|
|
@@ -682,27 +683,32 @@ namespace AZ
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_shaderResourceGroup && m_shaderResourceGroup->GetLayout()->GetHash() != objectSrgLayout->GetHash())
|
|
|
|
|
Data::Instance<RPI::ShaderResourceGroup> meshObjectSrg;
|
|
|
|
|
|
|
|
|
|
// See if the object SRG for this mesh is already in our list of object SRGs
|
|
|
|
|
for (auto& objectSrgIter : m_objectSrgList)
|
|
|
|
|
{
|
|
|
|
|
AZ_Warning("MeshFeatureProcessor", false, "All materials on a model must use the same per-object ShaderResourceGroup. Skipping.");
|
|
|
|
|
continue;
|
|
|
|
|
if (objectSrgIter->GetLayout()->GetHash() == objectSrgLayout->GetHash())
|
|
|
|
|
{
|
|
|
|
|
meshObjectSrg = objectSrgIter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The first time we find the per-surface SRG asset we create an instance and store it
|
|
|
|
|
// in shaderResourceGroupInOut. All of the Model's draw packets will use this same instance.
|
|
|
|
|
if (!m_shaderResourceGroup)
|
|
|
|
|
// If the object SRG for this mesh was not already in the list, create it and add it to the list
|
|
|
|
|
if (!meshObjectSrg)
|
|
|
|
|
{
|
|
|
|
|
auto& shaderAsset = material->GetAsset()->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg();
|
|
|
|
|
m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName());
|
|
|
|
|
if (!m_shaderResourceGroup)
|
|
|
|
|
meshObjectSrg = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName());
|
|
|
|
|
if (!meshObjectSrg)
|
|
|
|
|
{
|
|
|
|
|
AZ_Warning("MeshFeatureProcessor", false, "Failed to create a new shader resource group, skipping.");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
m_objectSrgList.push_back(meshObjectSrg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setup the mesh draw packet
|
|
|
|
|
RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, m_shaderResourceGroup, materialAssignment.m_matModUvOverrides);
|
|
|
|
|
RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, meshObjectSrg, materialAssignment.m_matModUvOverrides);
|
|
|
|
|
|
|
|
|
|
// set the shader option to select forward pass IBL specular if necessary
|
|
|
|
|
if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ m_descriptor.m_useForwardPassIblSpecular }))
|
|
|
|
@@ -726,7 +732,7 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::SetRayTracingData()
|
|
|
|
|
void ModelDataInstance::SetRayTracingData()
|
|
|
|
|
{
|
|
|
|
|
if (!m_model)
|
|
|
|
|
{
|
|
|
|
@@ -993,7 +999,7 @@ namespace AZ
|
|
|
|
|
rayTracingFeatureProcessor->SetMesh(m_objectId, m_model->GetModelAsset()->GetId(), subMeshes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::RemoveRayTracingData()
|
|
|
|
|
void ModelDataInstance::RemoveRayTracingData()
|
|
|
|
|
{
|
|
|
|
|
// remove from ray tracing
|
|
|
|
|
RayTracingFeatureProcessor* rayTracingFeatureProcessor = m_scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
|
|
|
|
@@ -1003,7 +1009,7 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey)
|
|
|
|
|
void ModelDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey)
|
|
|
|
|
{
|
|
|
|
|
m_sortKey = sortKey;
|
|
|
|
|
for (auto& drawPacketList : m_drawPacketListsByLod)
|
|
|
|
@@ -1015,24 +1021,24 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHI::DrawItemSortKey MeshDataInstance::GetSortKey() const
|
|
|
|
|
RHI::DrawItemSortKey ModelDataInstance::GetSortKey() const
|
|
|
|
|
{
|
|
|
|
|
return m_sortKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig)
|
|
|
|
|
void ModelDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig)
|
|
|
|
|
{
|
|
|
|
|
m_cullable.m_lodData.m_lodConfiguration = meshLodConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RPI::Cullable::LodConfiguration MeshDataInstance::GetMeshLodConfiguration() const
|
|
|
|
|
RPI::Cullable::LodConfiguration ModelDataInstance::GetMeshLodConfiguration() const
|
|
|
|
|
{
|
|
|
|
|
return m_cullable.m_lodData.m_lodConfiguration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
|
|
|
|
|
void ModelDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
|
|
|
|
|
{
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance:: UpdateDrawPackets");
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance:: UpdateDrawPackets");
|
|
|
|
|
for (auto& drawPacketList : m_drawPacketListsByLod)
|
|
|
|
|
{
|
|
|
|
|
for (auto& drawPacket : drawPacketList)
|
|
|
|
@@ -1045,9 +1051,9 @@ namespace AZ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::BuildCullable()
|
|
|
|
|
void ModelDataInstance::BuildCullable()
|
|
|
|
|
{
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: BuildCullable");
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: BuildCullable");
|
|
|
|
|
AZ_Assert(m_cullableNeedsRebuild, "This function only needs to be called if the cullable to be rebuilt");
|
|
|
|
|
AZ_Assert(m_model, "The model has not finished loading yet");
|
|
|
|
|
|
|
|
|
@@ -1122,9 +1128,9 @@ namespace AZ
|
|
|
|
|
m_cullBoundsNeedsUpdate = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService)
|
|
|
|
|
void ModelDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService)
|
|
|
|
|
{
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: UpdateCullBounds");
|
|
|
|
|
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: UpdateCullBounds");
|
|
|
|
|
AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt");
|
|
|
|
|
AZ_Assert(m_model, "The model has not finished loading yet");
|
|
|
|
|
|
|
|
|
@@ -1148,70 +1154,70 @@ namespace AZ
|
|
|
|
|
m_cullBoundsNeedsUpdate = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::UpdateObjectSrg()
|
|
|
|
|
void ModelDataInstance::UpdateObjectSrg()
|
|
|
|
|
{
|
|
|
|
|
if (!m_shaderResourceGroup)
|
|
|
|
|
for (auto& objectSrg : m_objectSrgList)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<ReflectionProbeFeatureProcessor>();
|
|
|
|
|
|
|
|
|
|
if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
|
|
|
|
|
{
|
|
|
|
|
// retrieve probe constant indices
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld"));
|
|
|
|
|
AZ_Error("ModelDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse"));
|
|
|
|
|
AZ_Error("ModelDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths"));
|
|
|
|
|
AZ_Error("ModelDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths"));
|
|
|
|
|
AZ_Error("ModelDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe"));
|
|
|
|
|
AZ_Error("ModelDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection"));
|
|
|
|
|
AZ_Error("ModelDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
// retrieve probe cubemap index
|
|
|
|
|
Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap");
|
|
|
|
|
RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = objectSrg->FindShaderInputImageIndex(reflectionCubeMapImageName);
|
|
|
|
|
AZ_Error("ModelDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr());
|
|
|
|
|
|
|
|
|
|
// retrieve the list of probes that contain the centerpoint of the mesh
|
|
|
|
|
TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor<TransformServiceFeatureProcessor>();
|
|
|
|
|
Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId);
|
|
|
|
|
|
|
|
|
|
ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes;
|
|
|
|
|
reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes);
|
|
|
|
|
|
|
|
|
|
if (!reflectionProbes.empty() && reflectionProbes[0])
|
|
|
|
|
{
|
|
|
|
|
objectSrg->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform());
|
|
|
|
|
objectSrg->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull());
|
|
|
|
|
objectSrg->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths());
|
|
|
|
|
objectSrg->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths());
|
|
|
|
|
objectSrg->SetConstant(useReflectionProbeConstantIndex, true);
|
|
|
|
|
objectSrg->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection());
|
|
|
|
|
|
|
|
|
|
objectSrg->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
objectSrg->SetConstant(useReflectionProbeConstantIndex, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
objectSrg->Compile();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<ReflectionProbeFeatureProcessor>();
|
|
|
|
|
|
|
|
|
|
if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
|
|
|
|
|
{
|
|
|
|
|
// retrieve probe constant indices
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld"));
|
|
|
|
|
AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse"));
|
|
|
|
|
AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths"));
|
|
|
|
|
AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths"));
|
|
|
|
|
AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe"));
|
|
|
|
|
AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection"));
|
|
|
|
|
AZ_Error("MeshDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
|
|
|
|
|
|
|
|
|
// retrieve probe cubemap index
|
|
|
|
|
Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap");
|
|
|
|
|
RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = m_shaderResourceGroup->FindShaderInputImageIndex(reflectionCubeMapImageName);
|
|
|
|
|
AZ_Error("MeshDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr());
|
|
|
|
|
|
|
|
|
|
// retrieve the list of probes that contain the centerpoint of the mesh
|
|
|
|
|
TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor<TransformServiceFeatureProcessor>();
|
|
|
|
|
Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId);
|
|
|
|
|
|
|
|
|
|
ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes;
|
|
|
|
|
reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes);
|
|
|
|
|
|
|
|
|
|
if (!reflectionProbes.empty() && reflectionProbes[0])
|
|
|
|
|
{
|
|
|
|
|
m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform());
|
|
|
|
|
m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull());
|
|
|
|
|
m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths());
|
|
|
|
|
m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths());
|
|
|
|
|
m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true);
|
|
|
|
|
m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection());
|
|
|
|
|
|
|
|
|
|
m_shaderResourceGroup->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_shaderResourceGroup->Compile();
|
|
|
|
|
m_objectSrgNeedsUpdate = false;
|
|
|
|
|
// Set m_objectSrgNeedsUpdate to false if there are object SRGs in the list
|
|
|
|
|
m_objectSrgNeedsUpdate = m_objectSrgNeedsUpdate && (m_objectSrgList.size() == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MeshDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance<RPI::Material> material) const
|
|
|
|
|
bool ModelDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance<RPI::Material> material) const
|
|
|
|
|
{
|
|
|
|
|
// look for a shader that has the o_materialUseForwardPassIBLSpecular option set
|
|
|
|
|
// Note: this should be changed to have the material automatically set the forwardPassIBLSpecular
|
|
|
|
@@ -1237,7 +1243,7 @@ namespace AZ
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshDataInstance::SetVisible(bool isVisible)
|
|
|
|
|
void ModelDataInstance::SetVisible(bool isVisible)
|
|
|
|
|
{
|
|
|
|
|
m_visible = isVisible;
|
|
|
|
|
m_cullable.m_isHidden = !isVisible;
|
|
|
|
|