b9824ed172
* Updated all array_view uses with the C++20 span. The updates were done in the following order 1. `AZStd::array_view<([^>].+)\* ?>` -> `AZStd::span<\1 const>` 2. `AZStd::array_view<(?:const )(.+)>` -> `AZStd::span<const \1>` 3. `AZStd::array_view` -> `AZStd::span` Removed the implementation of array_view. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added missing whitespace between `const` and the typename for spans. Updated the ShaderTest comparison of the ShaderResourceGroupLayout span to compare the sizes as well Updated comments on some of the methods that stated that they return "an array" to mention they return "a span". Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
155 lines
6.7 KiB
C++
155 lines
6.7 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <SkinnedMesh/SkinnedMeshRenderProxy.h>
|
|
#include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
|
|
#include <SkinnedMesh/SkinnedMeshComputePass.h>
|
|
#include <MorphTargets/MorphTargetComputePass.h>
|
|
|
|
#include <Atom/Feature/Mesh/MeshFeatureProcessor.h>
|
|
|
|
#include <Atom/RPI.Public/Model/Model.h>
|
|
#include <Atom/RPI.Public/Scene.h>
|
|
#include <Atom/RPI.Public/Shader/Shader.h>
|
|
|
|
#include <Atom/Utils/Utils.h>
|
|
namespace AZ
|
|
{
|
|
namespace Render
|
|
{
|
|
SkinnedMeshRenderProxy::SkinnedMeshRenderProxy(const SkinnedMeshFeatureProcessorInterface::SkinnedMeshRenderProxyDesc& desc)
|
|
: m_inputBuffers(desc.m_inputBuffers)
|
|
, m_instance(desc.m_instance)
|
|
, m_meshHandle(desc.m_meshHandle)
|
|
, m_boneTransforms(desc.m_boneTransforms)
|
|
, m_shaderOptions(desc.m_shaderOptions)
|
|
{
|
|
}
|
|
|
|
bool SkinnedMeshRenderProxy::Init(const RPI::Scene& scene, SkinnedMeshFeatureProcessor* featureProcessor)
|
|
{
|
|
AZ_PROFILE_FUNCTION(AzRender);
|
|
if(!m_instance->m_model)
|
|
{
|
|
return false;
|
|
}
|
|
const size_t modelLodCount = m_instance->m_model->GetLodCount();
|
|
m_featureProcessor = featureProcessor;
|
|
|
|
for (size_t modelLodIndex = 0; modelLodIndex < modelLodCount; ++modelLodIndex)
|
|
{
|
|
if (!BuildDispatchItem(scene, modelLodIndex, m_shaderOptions))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SkinnedMeshRenderProxy::BuildDispatchItem([[maybe_unused]] const RPI::Scene& scene, size_t modelLodIndex, [[maybe_unused]] const SkinnedMeshShaderOptions& shaderOptions)
|
|
{
|
|
Data::Instance<RPI::Shader> skinningShader = m_featureProcessor->GetSkinningShader();
|
|
if (!skinningShader)
|
|
{
|
|
AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get skinning shader from skinning pass");
|
|
return false;
|
|
}
|
|
|
|
// Get the value needed for encoding/decoding floats as integers when passing them
|
|
// from the morph target pass to the skinning pass.
|
|
// Integer encoding is used so that AZSL's InterlockedAdd can be used, wich only supports int/uint
|
|
const AZStd::vector<MorphTargetMetaData>& morphTargetMetaDatas = m_inputBuffers->GetMorphTargetMetaData(modelLodIndex);
|
|
float morphDeltaIntegerEncoding = 0.0f;
|
|
if (morphTargetMetaDatas.size() > 0)
|
|
{
|
|
morphDeltaIntegerEncoding = ComputeMorphTargetIntegerEncoding(morphTargetMetaDatas);
|
|
}
|
|
|
|
m_dispatchItemsByLod.emplace_back(
|
|
aznew SkinnedMeshDispatchItem{
|
|
m_inputBuffers,
|
|
m_instance->m_outputStreamOffsetsInBytes[modelLodIndex],
|
|
modelLodIndex, m_boneTransforms,
|
|
m_shaderOptions,
|
|
m_featureProcessor,
|
|
m_instance->m_morphTargetInstanceMetaData[modelLodIndex],
|
|
morphDeltaIntegerEncoding });
|
|
|
|
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");
|
|
if (!m_dispatchItemsByLod[modelLodIndex]->Init())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get the data needed to create a morph target dispatch item
|
|
Data::Instance<RPI::Shader> morphTargetShader = m_featureProcessor->GetMorphTargetShader();
|
|
const AZStd::vector<AZStd::intrusive_ptr<MorphTargetInputBuffers>>& morphTargetInputBuffersVector = m_inputBuffers->GetMorphTargetInputBuffers(modelLodIndex);
|
|
AZ_Assert(morphTargetMetaDatas.size() == morphTargetInputBuffersVector.size(), "Skinned Mesh Feature Processor - Mismatch in morph target metadata count and morph target input buffer count");
|
|
|
|
if (!morphTargetShader && morphTargetMetaDatas.size() > 0)
|
|
{
|
|
AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get morph target shader from morph target pass");
|
|
return false;
|
|
}
|
|
|
|
// Create one dispatch item per morph target
|
|
m_morphTargetDispatchItemsByLod.emplace_back(AZStd::vector<AZStd::unique_ptr<MorphTargetDispatchItem>>());
|
|
for (size_t morphTargetIndex = 0; morphTargetIndex < morphTargetMetaDatas.size(); ++morphTargetIndex)
|
|
{
|
|
m_morphTargetDispatchItemsByLod[modelLodIndex].emplace_back(
|
|
aznew MorphTargetDispatchItem{
|
|
morphTargetInputBuffersVector[morphTargetIndex],
|
|
morphTargetMetaDatas[morphTargetIndex],
|
|
m_featureProcessor,
|
|
m_instance->m_morphTargetInstanceMetaData[modelLodIndex],
|
|
morphDeltaIntegerEncoding });
|
|
|
|
// Initialize the MorphTargetDispatchItem we just created
|
|
if (!m_morphTargetDispatchItemsByLod[modelLodIndex].back()->Init())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SkinnedMeshRenderProxy::SetTransform(const AZ::Transform& transform)
|
|
{
|
|
// Set the position to be used for determining lod
|
|
m_position = transform.GetTranslation();
|
|
}
|
|
|
|
void SkinnedMeshRenderProxy::SetSkinningMatrices(const AZStd::vector<float>& data)
|
|
{
|
|
if (m_boneTransforms)
|
|
{
|
|
WriteToBuffer(m_boneTransforms->GetRHIBuffer(), data);
|
|
}
|
|
}
|
|
|
|
void SkinnedMeshRenderProxy::SetMorphTargetWeights(uint32_t lodIndex, const AZStd::vector<float>& weights)
|
|
{
|
|
auto& morphTargetDispatchItems = m_morphTargetDispatchItemsByLod[lodIndex];
|
|
|
|
AZ_Assert(morphTargetDispatchItems.size() == weights.size(), "Skinned Mesh Feature Processor - Morph target weights passed into SetMorphTargetWeight don't align with morph target dispatch items.");
|
|
for (size_t morphIndex = 0; morphIndex < weights.size(); ++morphIndex)
|
|
{
|
|
morphTargetDispatchItems[morphIndex]->SetWeight(weights[morphIndex]);
|
|
}
|
|
}
|
|
|
|
AZStd::span<const AZStd::unique_ptr<SkinnedMeshDispatchItem>> SkinnedMeshRenderProxy::GetDispatchItems() const
|
|
{
|
|
return m_dispatchItemsByLod;
|
|
}
|
|
|
|
} // namespace Render
|
|
} // namespace AZ
|