Merge pull request #5482 from aws-lumberyard-dev/Atom/antonmic/skinMeshSrgFix
Fixed issue where skin material wouldn't render if applied to a model with several submeshes and those submeshes had different material types applied to them.
This commit is contained in:
@@ -30,7 +30,7 @@ namespace AZ
|
||||
class TransformServiceFeatureProcessor;
|
||||
class RayTracingFeatureProcessor;
|
||||
|
||||
class MeshDataInstance
|
||||
class ModelDataInstance
|
||||
{
|
||||
friend class MeshFeatureProcessor;
|
||||
friend class MeshLoader;
|
||||
@@ -47,7 +47,7 @@ namespace AZ
|
||||
public:
|
||||
using ModelChangedEvent = MeshFeatureProcessorInterface::ModelChangedEvent;
|
||||
|
||||
MeshLoader(const Data::Asset<RPI::ModelAsset>& modelAsset, MeshDataInstance* parent);
|
||||
MeshLoader(const Data::Asset<RPI::ModelAsset>& modelAsset, ModelDataInstance* parent);
|
||||
~MeshLoader();
|
||||
|
||||
ModelChangedEvent& GetModelChangedEvent();
|
||||
@@ -68,7 +68,7 @@ namespace AZ
|
||||
} };
|
||||
MeshFeatureProcessorInterface::ModelChangedEvent m_modelChangedEvent;
|
||||
Data::Asset<RPI::ModelAsset> m_modelAsset;
|
||||
MeshDataInstance* m_parent = nullptr;
|
||||
ModelDataInstance* m_parent = nullptr;
|
||||
};
|
||||
|
||||
void DeInit();
|
||||
@@ -99,7 +99,8 @@ namespace AZ
|
||||
//! A reference to the original model asset in case it got cloned before creating the model instance.
|
||||
Data::Asset<RPI::ModelAsset> m_originalModelAsset;
|
||||
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_shaderResourceGroup;
|
||||
//! List of object SRGs used by meshes in this model
|
||||
AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>> m_objectSrgList;
|
||||
AZStd::unique_ptr<MeshLoader> m_meshLoader;
|
||||
RPI::Scene* m_scene = nullptr;
|
||||
RHI::DrawItemSortKey m_sortKey;
|
||||
@@ -152,7 +153,7 @@ namespace AZ
|
||||
|
||||
Data::Instance<RPI::Model> GetModel(const MeshHandle& meshHandle) const override;
|
||||
Data::Asset<RPI::ModelAsset> GetModelAsset(const MeshHandle& meshHandle) const override;
|
||||
Data::Instance<RPI::ShaderResourceGroup> GetObjectSrg(const MeshHandle& meshHandle) const override;
|
||||
const AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>>& GetObjectSrgs(const MeshHandle& meshHandle) const override;
|
||||
void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const override;
|
||||
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance<RPI::Material>& material) override;
|
||||
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override;
|
||||
@@ -195,7 +196,7 @@ namespace AZ
|
||||
void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override;
|
||||
|
||||
AZStd::concurrency_checker m_meshDataChecker;
|
||||
StableDynamicArray<MeshDataInstance> m_meshData;
|
||||
StableDynamicArray<ModelDataInstance> m_modelData;
|
||||
TransformServiceFeatureProcessor* m_transformService;
|
||||
RayTracingFeatureProcessor* m_rayTracingFeatureProcessor = nullptr;
|
||||
AZ::RPI::ShaderSystemInterface::GlobalShaderOptionUpdatedEvent::Handler m_handleGlobalShaderOptionUpdate;
|
||||
|
||||
+10
-7
@@ -20,7 +20,7 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
class MeshDataInstance;
|
||||
class ModelDataInstance;
|
||||
|
||||
//! Settings to apply to a mesh handle when acquiring it for the first time
|
||||
struct MeshHandleDescriptor
|
||||
@@ -40,7 +40,7 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::MeshFeatureProcessorInterface, "{975D7F0C-2E7E-4819-94D0-D3C4E2024721}", FeatureProcessor);
|
||||
|
||||
using MeshHandle = StableDynamicArrayHandle<MeshDataInstance>;
|
||||
using MeshHandle = StableDynamicArrayHandle<ModelDataInstance>;
|
||||
using ModelChangedEvent = Event<const Data::Instance<RPI::Model>>;
|
||||
|
||||
//! Acquires a model with an optional collection of material assignments.
|
||||
@@ -61,12 +61,15 @@ namespace AZ
|
||||
virtual Data::Instance<RPI::Model> GetModel(const MeshHandle& meshHandle) const = 0;
|
||||
//! Gets the underlying RPI::ModelAsset for a meshHandle.
|
||||
virtual Data::Asset<RPI::ModelAsset> GetModelAsset(const MeshHandle& meshHandle) const = 0;
|
||||
//! Gets the ObjectSrg for a meshHandle.
|
||||
//! Updating the ObjectSrg should be followed by a call to QueueObjectSrgForCompile,
|
||||
//! instead of compiling the srg directly. This way, if the srg has already been queued for compile,
|
||||
//! it will not be queued twice in the same frame. The ObjectSrg should not be updated during
|
||||
|
||||
//! Gets the ObjectSrgs for a meshHandle.
|
||||
//! Updating the ObjectSrgs should be followed by a call to QueueObjectSrgForCompile,
|
||||
//! instead of compiling the srgs directly. This way, if the srgs have already been queued for compile,
|
||||
//! they will not be queued twice in the same frame. The ObjectSrgs should not be updated during
|
||||
//! Simulate, or it will create a race between updating the data and the call to Compile
|
||||
virtual Data::Instance<RPI::ShaderResourceGroup> GetObjectSrg(const MeshHandle& meshHandle) const = 0;
|
||||
//! Cases where there may be multiple ObjectSrgs: if a model has multiple submeshes and those submeshes use different
|
||||
//! materials with different object SRGs.
|
||||
virtual const AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>>& GetObjectSrgs(const MeshHandle& meshHandle) const = 0;
|
||||
//! Queues the object srg for compile.
|
||||
virtual void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const = 0;
|
||||
//! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId.
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace UnitTest
|
||||
MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr<AZ::RPI::Model>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset<AZ::RPI::ModelAsset>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetObjectSrg, AZStd::intrusive_ptr<AZ::RPI::ShaderResourceGroup>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetObjectSrgs, const AZStd::vector<AZStd::intrusive_ptr<AZ::RPI::ShaderResourceGroup>>&(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(QueueObjectSrgForCompile, void(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&));
|
||||
MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&));
|
||||
|
||||
@@ -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
|
||||
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,74 +1154,74 @@ 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");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex exposureConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_exposure"));
|
||||
AZ_Error("ModelDataInstance", exposureConstantIndex.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->SetConstant(exposureConstantIndex, reflectionProbes[0]->GetRenderExposure());
|
||||
|
||||
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");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex exposureConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_exposure"));
|
||||
AZ_Error("MeshDataInstance", exposureConstantIndex.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->SetConstant(exposureConstantIndex, reflectionProbes[0]->GetRenderExposure());
|
||||
|
||||
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
|
||||
@@ -1241,7 +1247,7 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
void MeshDataInstance::SetVisible(bool isVisible)
|
||||
void ModelDataInstance::SetVisible(bool isVisible)
|
||||
{
|
||||
m_visible = isVisible;
|
||||
m_cullable.m_isHidden = !isVisible;
|
||||
|
||||
@@ -95,13 +95,13 @@ namespace AZ
|
||||
renderProxy.m_instance->m_model->WaitForUpload();
|
||||
}
|
||||
|
||||
//Note: we are creating pointers to the meshDataInstance cullpacket and lod packet here,
|
||||
//Note: we are creating pointers to the modelDataInstance cullpacket and lod packet here,
|
||||
//and holding them until the skinnedMeshDispatchItems are dispatched. There is an assumption that the underlying
|
||||
//data will not move during this phase.
|
||||
MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle;
|
||||
m_workgroup.m_cullPackets.push_back(&meshDataInstance.GetCullPacket());
|
||||
m_workgroup.m_drawListMask |= meshDataInstance.GetCullPacket().m_drawListMask;
|
||||
m_lodPackets.push_back(&meshDataInstance.GetLodPacket());
|
||||
ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle;
|
||||
m_workgroup.m_cullPackets.push_back(&modelDataInstance.GetCullPacket());
|
||||
m_workgroup.m_drawListMask |= modelDataInstance.GetCullPacket().m_drawListMask;
|
||||
m_lodPackets.push_back(&modelDataInstance.GetLodPacket());
|
||||
m_potentiallyVisibleProxies.push_back(&renderProxy);
|
||||
}
|
||||
}
|
||||
@@ -187,8 +187,8 @@ namespace AZ
|
||||
renderProxy.m_instance->m_model->WaitForUpload();
|
||||
}
|
||||
|
||||
MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle;
|
||||
const RPI::Cullable& cullable = meshDataInstance.GetCullable();
|
||||
ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle;
|
||||
const RPI::Cullable& cullable = modelDataInstance.GetCullable();
|
||||
|
||||
for (const RPI::ViewPtr& viewPtr : packet.m_views)
|
||||
{
|
||||
|
||||
@@ -880,12 +880,14 @@ namespace AZ
|
||||
{
|
||||
if (m_meshHandle)
|
||||
{
|
||||
Data::Instance<RPI::ShaderResourceGroup> wrinkleMaskObjectSrg = m_meshFeatureProcessor->GetObjectSrg(*m_meshHandle);
|
||||
if (wrinkleMaskObjectSrg)
|
||||
const AZStd::vector<Data::Instance<RPI::ShaderResourceGroup>>& wrinkleMaskObjectSrgs = m_meshFeatureProcessor->GetObjectSrgs(*m_meshHandle);
|
||||
|
||||
for (auto& wrinkleMaskObjectSrg : wrinkleMaskObjectSrgs)
|
||||
{
|
||||
RHI::ShaderInputImageIndex wrinkleMasksIndex = wrinkleMaskObjectSrg->FindShaderInputImageIndex(Name{ "m_wrinkle_masks" });
|
||||
RHI::ShaderInputConstantIndex wrinkleMaskWeightsIndex = wrinkleMaskObjectSrg->FindShaderInputConstantIndex(Name{ "m_wrinkle_mask_weights" });
|
||||
RHI::ShaderInputConstantIndex wrinkleMaskCountIndex = wrinkleMaskObjectSrg->FindShaderInputConstantIndex(Name{ "m_wrinkle_mask_count" });
|
||||
|
||||
if (wrinkleMasksIndex.IsValid() || wrinkleMaskWeightsIndex.IsValid() || wrinkleMaskCountIndex.IsValid())
|
||||
{
|
||||
AZ_Error("AtomActorInstance", wrinkleMasksIndex.IsValid(), "m_wrinkle_masks not found on the ObjectSrg, but m_wrinkle_mask_weights and/or m_wrinkle_mask_count are being used.");
|
||||
|
||||
Reference in New Issue
Block a user