3
0

SkinnedMeshRenderProxy.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <SkinnedMesh/SkinnedMeshRenderProxy.h>
  9. #include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
  10. #include <SkinnedMesh/SkinnedMeshComputePass.h>
  11. #include <MorphTargets/MorphTargetComputePass.h>
  12. #include <Atom/Feature/Mesh/MeshFeatureProcessor.h>
  13. #include <Atom/RPI.Public/Model/Model.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <Atom/RPI.Public/Shader/Shader.h>
  16. #include <Atom/Utils/Utils.h>
  17. namespace AZ
  18. {
  19. namespace Render
  20. {
  21. SkinnedMeshRenderProxy::SkinnedMeshRenderProxy(const SkinnedMeshFeatureProcessorInterface::SkinnedMeshHandleDescriptor& desc)
  22. : m_inputBuffers(desc.m_inputBuffers)
  23. , m_instance(desc.m_instance)
  24. , m_meshHandle(desc.m_meshHandle)
  25. , m_boneTransforms(desc.m_boneTransforms)
  26. , m_shaderOptions(desc.m_shaderOptions)
  27. {
  28. }
  29. bool SkinnedMeshRenderProxy::Init(const RPI::Scene& scene, SkinnedMeshFeatureProcessor* featureProcessor)
  30. {
  31. AZ_PROFILE_FUNCTION(AzRender);
  32. if(!m_instance->m_model)
  33. {
  34. return false;
  35. }
  36. const size_t modelLodCount = m_instance->m_model->GetLodCount();
  37. m_featureProcessor = featureProcessor;
  38. for (uint32_t modelLodIndex = 0; modelLodIndex < modelLodCount; ++modelLodIndex)
  39. {
  40. if (!BuildDispatchItem(scene, modelLodIndex, m_shaderOptions))
  41. {
  42. return false;
  43. }
  44. }
  45. return true;
  46. }
  47. bool SkinnedMeshRenderProxy::BuildDispatchItem([[maybe_unused]] const RPI::Scene& scene, uint32_t modelLodIndex, [[maybe_unused]] const SkinnedMeshShaderOptions& shaderOptions)
  48. {
  49. Data::Instance<RPI::Shader> skinningShader = m_featureProcessor->GetSkinningShader();
  50. if (!skinningShader)
  51. {
  52. AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get skinning shader from skinning pass");
  53. return false;
  54. }
  55. // Get the data needed to create a morph target dispatch item
  56. Data::Instance<RPI::Shader> morphTargetShader = m_featureProcessor->GetMorphTargetShader();
  57. if (!morphTargetShader)
  58. {
  59. AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get morph target shader from morph target pass");
  60. return false;
  61. }
  62. // Create a vector of dispatch items for each lod
  63. m_dispatchItemsByLod.emplace_back(AZStd::vector<AZStd::unique_ptr<SkinnedMeshDispatchItem>>());
  64. m_morphTargetDispatchItemsByLod.emplace_back(AZStd::vector<AZStd::unique_ptr<MorphTargetDispatchItem>>());
  65. size_t meshCount = m_inputBuffers->GetMeshCount(modelLodIndex);
  66. m_dispatchItemsByLod[modelLodIndex].reserve(meshCount);
  67. // Populate the vector with a dispatch item for each mesh
  68. for (uint32_t meshIndex = 0; meshIndex < meshCount; ++meshIndex)
  69. {
  70. // Create the skinning dispatch Item
  71. m_dispatchItemsByLod[modelLodIndex].emplace_back(
  72. aznew SkinnedMeshDispatchItem{
  73. m_inputBuffers,
  74. m_instance->m_outputStreamOffsetsInBytes[modelLodIndex][meshIndex],
  75. m_instance->m_positionHistoryBufferOffsetsInBytes[modelLodIndex][meshIndex],
  76. modelLodIndex, meshIndex, m_boneTransforms,
  77. m_shaderOptions,
  78. m_featureProcessor,
  79. m_instance->m_morphTargetInstanceMetaData[modelLodIndex][meshIndex],
  80. m_inputBuffers->GetMorphTargetIntegerEncoding(modelLodIndex, meshIndex)});
  81. }
  82. AZ_Assert(m_dispatchItemsByLod.size() == modelLodIndex + 1, "Skinned Mesh Feature Processor - Mismatch in size between the fixed vector of dispatch items and the lod being initialized");
  83. for (size_t dispatchIndex = 0; dispatchIndex < m_dispatchItemsByLod[modelLodIndex].size(); ++dispatchIndex)
  84. {
  85. if (!m_dispatchItemsByLod[modelLodIndex][dispatchIndex]->Init())
  86. {
  87. return false;
  88. }
  89. }
  90. size_t morphTargetCount = m_inputBuffers->GetMorphTargetInputBuffers(modelLodIndex).size();
  91. AZ_Assert(
  92. m_inputBuffers->GetMorphTargetComputeMetaDatas(modelLodIndex).size() == morphTargetCount,
  93. "SkinnedMeshRenderProxy: Invalid SkinnedMeshInputBuffers have mis-matched morph target input buffers and compute metadata");
  94. m_morphTargetDispatchItemsByLod[modelLodIndex].reserve(morphTargetCount);
  95. // Create one dispatch item per morph target, in the order that they were originally added
  96. // to the skinned mesh to stay in sync with the animation system
  97. for (size_t morphTargetIndex = 0; morphTargetIndex < morphTargetCount; ++morphTargetIndex)
  98. {
  99. const MorphTargetComputeMetaData& metaData =
  100. m_inputBuffers->GetMorphTargetComputeMetaDatas(modelLodIndex)[morphTargetIndex];
  101. m_morphTargetDispatchItemsByLod[modelLodIndex].emplace_back(
  102. aznew MorphTargetDispatchItem
  103. {
  104. m_inputBuffers->GetMorphTargetInputBuffers(modelLodIndex)[morphTargetIndex],
  105. metaData,
  106. m_featureProcessor,
  107. m_instance->m_morphTargetInstanceMetaData[modelLodIndex][metaData.m_meshIndex],
  108. m_inputBuffers->GetMorphTargetIntegerEncoding(modelLodIndex, metaData.m_meshIndex)
  109. });
  110. // Initialize the MorphTargetDispatchItem we just created
  111. if (!m_morphTargetDispatchItemsByLod[modelLodIndex].back()->Init())
  112. {
  113. return false;
  114. }
  115. }
  116. return true;
  117. }
  118. void SkinnedMeshRenderProxy::SetSkinningMatrices(const AZStd::vector<float>& data)
  119. {
  120. if (m_boneTransforms)
  121. {
  122. m_boneTransforms->UpdateData(data.data(), data.size() * sizeof(float));
  123. }
  124. }
  125. void SkinnedMeshRenderProxy::SetMorphTargetWeights(uint32_t lodIndex, const AZStd::vector<float>& weights)
  126. {
  127. auto& morphTargetDispatchItems = m_morphTargetDispatchItemsByLod[lodIndex];
  128. AZ_Assert(morphTargetDispatchItems.size() == weights.size(), "Skinned Mesh Feature Processor - Morph target weights passed into SetMorphTargetWeight don't align with morph target dispatch items.");
  129. for (size_t morphIndex = 0; morphIndex < weights.size(); ++morphIndex)
  130. {
  131. morphTargetDispatchItems[morphIndex]->SetWeight(weights[morphIndex]);
  132. }
  133. }
  134. void SkinnedMeshRenderProxy::EnableSkinning(uint32_t lodIndex, uint32_t meshIndex)
  135. {
  136. m_dispatchItemsByLod[lodIndex][meshIndex]->Enable();
  137. }
  138. void SkinnedMeshRenderProxy::DisableSkinning(uint32_t lodIndex, uint32_t meshIndex)
  139. {
  140. m_dispatchItemsByLod[lodIndex][meshIndex]->Disable();
  141. }
  142. uint32_t SkinnedMeshRenderProxy::GetLodCount() const
  143. {
  144. return aznumeric_caster(m_dispatchItemsByLod.size());
  145. }
  146. AZStd::span<const AZStd::unique_ptr<SkinnedMeshDispatchItem>> SkinnedMeshRenderProxy::GetDispatchItems(uint32_t lodIndex) const
  147. {
  148. return m_dispatchItemsByLod[lodIndex];
  149. }
  150. } // namespace Render
  151. } // namespace AZ