Integrating github/staging through commit ab87ed9

This commit is contained in:
alexpete
2021-04-09 11:27:37 -07:00
parent ae62a97894
commit 1044dc3da1
1582 changed files with 29374 additions and 519051 deletions
@@ -40,6 +40,7 @@
#include <SceneAPI/SceneCore/DataTypes/Rules/ICoordinateSystemRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ILodRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ISkinRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IClothRule.h>
#include <SceneAPI/SceneCore/Events/ExportEventContext.h>
#include <SceneAPI/SceneCore/Utilities/SceneGraphSelector.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
@@ -93,6 +94,11 @@ namespace
const AZ::RHI::Format MorphTargetPositionDeltaFormat = AZ::RHI::Format::R16_UINT; // 16-bit integer per compressed position delta component
const char* ShaderSemanticName_MorphTargetNormalDeltas = "MORPHTARGET_NORMALDELTAS";
const AZ::RHI::Format MorphTargetNormalDeltaFormat = AZ::RHI::Format::R8_UINT; // 8-bit integer per compressed normal delta component
// Cloth data
const char* const ShaderSemanticName_ClothData = "CLOTH_DATA";
const uint32_t ClothDataFloatsPerVert = 4;
const AZ::RHI::Format ClothDataFormat = AZ::RHI::Format::R32G32B32A32_FLOAT;
}
namespace AZ
@@ -113,6 +119,7 @@ namespace AZ
}
ModelAssetBuilderComponent::ModelAssetBuilderComponent()
: m_numSkinJointInfluencesPerVertex(DefaultSkinInfluencesPerVert)
{
BindToCall(&ModelAssetBuilderComponent::BuildModel);
}
@@ -331,6 +338,12 @@ namespace AZ
sourceMesh.m_isMorphed = GetIsMorphed(sceneGraph, node);
// Get the cloth data (only for full mesh LOD 0).
sourceMesh.m_meshClothData = (lodIndex == 0)
? SceneAPI::DataTypes::IClothRule::FindClothData(
sceneGraph, node, sourceMesh.m_meshData->GetVertexCount(), context.m_group.GetRuleContainerConst())
: AZStd::vector<AZ::Color>{};
// We've traversed this node and all its children that hold
// relevant data We can move it into the list of content for this lod
sourceMeshContentList.emplace_back(AZStd::move(sourceMesh));
@@ -371,17 +384,19 @@ namespace AZ
// If the merge meshes option is disabled in the advanced mesh rule, don't merge meshes
canMergeMeshes = false;
}
for (const SourceMeshContent& sourceMesh : sourceMeshContentList)
else
{
if (sourceMesh.m_isMorphed)
for (const SourceMeshContent& sourceMesh : sourceMeshContentList)
{
// Merging meshes shuffles around the order of the vertices, but morph targets rely on having an index that tell them which vertices to morph
// We do not merge morphed meshes so that this index is preserved and correct.
// If we keep track of the ordering changes in MergeMeshesByMaterialUid and then re-mapped the MORPHTARGET_VERTEXINDICES buffer
// we could potentially enable merging meshes that are morphed. But for now, disable merging.
canMergeMeshes = false;
break;
if (sourceMesh.m_isMorphed)
{
// Merging meshes shuffles around the order of the vertices, but morph targets rely on having an index that tell them which vertices to morph
// We do not merge morphed meshes so that this index is preserved and correct.
// If we keep track of the ordering changes in MergeMeshesByMaterialUid and then re-mapped the MORPHTARGET_VERTEXINDICES buffer
// we could potentially enable merging meshes that are morphed. But for now, disable merging.
canMergeMeshes = false;
break;
}
}
}
@@ -396,12 +411,12 @@ namespace AZ
ProductMeshViewList lodMeshViews;
ProductMeshContent mergedMesh;
MergeMeshesToCommonBuffers(context, lodMeshes, mergedMesh, lodMeshViews);
MergeMeshesToCommonBuffers(lodMeshes, mergedMesh, lodMeshViews);
BufferAssetView indexBuffer;
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo> streamBuffers;
if (!CreateModelLodBuffers(context, mergedMesh, indexBuffer, streamBuffers, lodAssetCreator))
if (!CreateModelLodBuffers(mergedMesh, indexBuffer, streamBuffers, lodAssetCreator))
{
return AZ::SceneAPI::Events::ProcessingResult::Failure;
}
@@ -417,7 +432,7 @@ namespace AZ
uint32_t meshIndex = 0;
for (const ProductMeshContent& mesh : lodMeshes)
{
const ProductMeshView meshView = CreateViewToEntireMesh(context, mesh);
const ProductMeshView meshView = CreateViewToEntireMesh(mesh);
BufferAssetView indexBuffer;
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo> streamBuffers;
@@ -425,7 +440,7 @@ namespace AZ
// Mesh name in ProductMeshContent could be duplicated so generate unique mesh name using index
m_meshName = AZStd::string::format("mesh%d", meshIndex++);
if (!CreateModelLodBuffers(context, mesh, indexBuffer, streamBuffers, lodAssetCreator))
if (!CreateModelLodBuffers(mesh, indexBuffer, streamBuffers, lodAssetCreator))
{
return AZ::SceneAPI::Events::ProcessingResult::Failure;
}
@@ -614,7 +629,11 @@ namespace AZ
productMeshList.reserve(productMeshCount);
// Get the skin rule
AZStd::shared_ptr<const SceneAPI::DataTypes::ISkinRule> skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>();
if (const auto* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get())
{
m_numSkinJointInfluencesPerVertex = skinRule->GetMaxWeightsPerVertex();
m_skinWeightThreshold = skinRule->GetWeightThreshold();
}
uint32_t totalVertexCount = 0;
for (size_t i = 0; i < productList.size(); ++i)
@@ -632,6 +651,7 @@ namespace AZ
const auto& colorContentCollection = sourceMesh.m_meshColorData;
const size_t colorSetCount = colorContentCollection.size();
bool processedMorphTargets = false;
bool warnedExcessOfSkinInfluences = false;
for (const auto& it : productsByMaterialUid)
{
@@ -677,6 +697,7 @@ namespace AZ
AZStd::vector<AZ::Name>& uvNames = productMesh.m_uvCustomNames;
AZStd::vector<AZStd::vector<float>>& colorSets = productMesh.m_colorSets;
AZStd::vector<AZ::Name>& colorNames = productMesh.m_colorCustomNames;
AZStd::vector<float>& clothData = productMesh.m_clothData;
const size_t vertexCount = oldToNewIndices.size();
positions.reserve(vertexCount * PositionFloatsPerVert);
@@ -716,7 +737,16 @@ namespace AZ
colorSet.reserve(vertexCount * ColorFloatsPerVert);
}
if (!sourceMesh.m_skinData.empty())
const bool hasClothData = !sourceMesh.m_meshClothData.empty();
if (hasClothData)
{
AZ_Assert(sourceMesh.m_meshClothData.size() == vertexCount,
"Vertex Count %d does not match mesh cloth data size %d", vertexCount, sourceMesh.m_meshClothData.size());
clothData.reserve(vertexCount * ClothDataFloatsPerVert);
}
const bool hasSkinData = !sourceMesh.m_skinData.empty();
if (hasSkinData)
{
// Skinned meshes require that positions, normals, tangents, bitangents, all exist and have the same number
// of total elements. Pad buffers with missing data to make them align with positions and normals
@@ -817,8 +847,23 @@ namespace AZ
colors.push_back(color.alpha);
}
// Gather Cloth Data
if (hasClothData)
{
const AZ::Color& vertexClothData = sourceMesh.m_meshClothData[oldIndex];
clothData.push_back(vertexClothData.GetR());
clothData.push_back(vertexClothData.GetG());
clothData.push_back(vertexClothData.GetB());
clothData.push_back(vertexClothData.GetA());
}
// Gather skinning influences
GatherSkinningInfluences(context, sourceMesh, productMesh, jointNameToIndexMap, oldIndex);
if (hasSkinData)
{
// Warn about excess of skin influences once per-source mesh.
GatherVertexSkinningInfluences(sourceMesh, productMesh, jointNameToIndexMap, oldIndex, warnedExcessOfSkinInfluences);
}
}
if(!processedMorphTargets)
@@ -836,19 +881,16 @@ namespace AZ
return productMeshList;
}
void ModelAssetBuilderComponent::GatherSkinningInfluences(
const ModelAssetBuilderContext& context,
void ModelAssetBuilderComponent::GatherVertexSkinningInfluences(
const SourceMeshContent& sourceMesh,
ProductMeshContent& productMesh,
AZStd::unordered_map<AZStd::string, uint16_t>& jointNameToIndexMap,
size_t vertexIndex) const
size_t vertexIndex,
bool& warnedExcessOfSkinInfluences) const
{
AZStd::vector<uint16_t>& skinJointIndices = productMesh.m_skinJointIndices;
AZStd::vector<float>& skinWeights = productMesh.m_skinWeights;
const auto& sourceMeshData = sourceMesh.m_meshData;
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const size_t maxNumInfluences = ExtractMaxNumInfluencesPerVertex(skinRule);
const float weightThreshold = skinRule ? skinRule->GetWeightThreshold() : 0.0f;
size_t numInfluencesAdded = 0;
for (const auto& skinData : sourceMesh.m_skinData)
@@ -857,8 +899,9 @@ namespace AZ
const AZ::u32 controlPointIndex = sourceMeshData->GetControlPointIndex(vertexIndex);
const size_t numSkinInfluences = skinData->GetLinkCount(controlPointIndex);
const size_t numInfluencesToAdd = AZStd::min<size_t>(numSkinInfluences, maxNumInfluences - numInfluencesAdded);
for (size_t influenceIndex = 0; influenceIndex < numInfluencesToAdd; ++influenceIndex)
size_t numInfluencesExcess = 0;
for (size_t influenceIndex = 0; influenceIndex < numSkinInfluences; ++influenceIndex)
{
const AZ::SceneAPI::DataTypes::ISkinWeightData::Link& link = skinData->GetLink(controlPointIndex, influenceIndex);
@@ -874,30 +917,37 @@ namespace AZ
const AZ::u16 jointIndex = jointNameToIndexMap[boneName];
// Add skin influence
if (weight > weightThreshold)
if (weight > m_skinWeightThreshold)
{
skinJointIndices.push_back(jointIndex);
skinWeights.push_back(weight);
numInfluencesAdded++;
if (numInfluencesAdded < m_numSkinJointInfluencesPerVertex)
{
skinJointIndices.push_back(jointIndex);
skinWeights.push_back(weight);
numInfluencesAdded++;
}
else
{
numInfluencesExcess++;
}
}
}
if (numInfluencesAdded > maxNumInfluences)
if (numInfluencesExcess > 0)
{
AZ_WarningOnce(s_builderName, false, "More skin influences (%d) on data than supported (%d). Skinning influences won't be normalized.",
numSkinInfluences, maxNumInfluences);
AZ_Warning(s_builderName, warnedExcessOfSkinInfluences,
"Mesh %s has more skin influences (%d) than the maximum (%d). Skinning influences won't be normalized. Maximum number of skin influences can be increased with a Skin Modifier in FBX Settings.",
sourceMesh.m_name.GetCStr(),
m_numSkinJointInfluencesPerVertex + numInfluencesExcess,
m_numSkinJointInfluencesPerVertex);
warnedExcessOfSkinInfluences = true;
break;
}
}
if (!sourceMesh.m_skinData.empty() &&
numInfluencesAdded < maxNumInfluences)
for (size_t influenceIndex = numInfluencesAdded; influenceIndex < m_numSkinJointInfluencesPerVertex; ++influenceIndex)
{
for (size_t influenceIndex = numInfluencesAdded; influenceIndex < maxNumInfluences; ++influenceIndex)
{
skinJointIndices.push_back(0);
skinWeights.push_back(0.0f);
}
skinJointIndices.push_back(0);
skinWeights.push_back(0.0f);
}
}
@@ -914,7 +964,6 @@ namespace AZ
for (const ProductMeshContent& mesh : productMeshList)
{
// Disable mesh merging whenever a mesh is morphed.
if (mesh.CanBeMerged())
{
meshCountByMatUid[mesh.m_materialUid]++;
@@ -970,9 +1019,11 @@ namespace AZ
}
template<typename T>
void ModelAssetBuilderComponent::ValidateStreamSize([[maybe_unused]] size_t expectedVertexCount, const AZStd::vector<T>& bufferData, AZ::RHI::Format format, [[maybe_unused]] const char* streamName) const
void ModelAssetBuilderComponent::ValidateStreamSize([[maybe_unused]] size_t expectedVertexCount, [[maybe_unused]] const AZStd::vector<T>& bufferData, [[maybe_unused]] AZ::RHI::Format format, [[maybe_unused]] const char* streamName) const
{
#if defined(AZ_ENABLE_TRACING)
size_t actualVertexCount = (bufferData.size() * sizeof(T)) / RHI::GetFormatSize(format);
#endif
AZ_Error(s_builderName, expectedVertexCount == actualVertexCount, "VertexStream '%s' does not match the expected vertex count. This typically means multiple sub-meshes have mis-matched vertex stream layouts (such as one having more uv sets than the other) but are assigned the same material in the dcc tool so they were merged.", streamName);
}
@@ -999,9 +1050,21 @@ namespace AZ
{
ValidateStreamSize(expectedVertexCount, mesh.m_colorSets[i], ColorFormat, mesh.m_colorCustomNames[i].GetCStr());
}
if (!mesh.m_clothData.empty())
{
ValidateStreamSize(expectedVertexCount, mesh.m_clothData, ClothDataFormat, ShaderSemanticName_ClothData);
}
if (!mesh.m_skinJointIndices.empty())
{
ValidateStreamSize(expectedVertexCount * m_numSkinJointInfluencesPerVertex, mesh.m_skinJointIndices, AZ::RHI::Format::R16_UINT, ShaderSemanticName_SkinJointIndices);
}
if (!mesh.m_skinWeights.empty())
{
ValidateStreamSize(expectedVertexCount * m_numSkinJointInfluencesPerVertex, mesh.m_skinWeights, SkinWeightFormat, ShaderSemanticName_SkinWeights);
}
}
ModelAssetBuilderComponent::ProductMeshView ModelAssetBuilderComponent::CreateViewToEntireMesh(const ModelAssetBuilderContext& context, const ProductMeshContent& mesh)
ModelAssetBuilderComponent::ProductMeshView ModelAssetBuilderComponent::CreateViewToEntireMesh(const ProductMeshContent& mesh)
{
ProductMeshView meshView;
meshView.m_name = mesh.m_name.GetStringView();
@@ -1059,16 +1122,13 @@ namespace AZ
if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(),
"Number of skin influence joint indices (%d) should match the number of weights (%d).",
mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size());
AZ_Assert(mesh.m_skinWeights.size() % maxNumSkinInfluencesPerVertex == 0,
AZ_Assert(mesh.m_skinWeights.size() % m_numSkinJointInfluencesPerVertex == 0,
"The number of skin influences per vertex (%d) is not a multiple of the total number of skinning weights (%d). This means that not every vertex has exactly (%d) skinning weights and invalidates the data.",
mesh.m_skinWeights.size(), maxNumSkinInfluencesPerVertex, maxNumSkinInfluencesPerVertex);
mesh.m_skinWeights.size(), m_numSkinJointInfluencesPerVertex, m_numSkinJointInfluencesPerVertex);
const size_t numSkinInfluences = mesh.m_skinWeights.size();
uint32_t jointIndicesSizeInBytes = numSkinInfluences * sizeof(uint16_t);
@@ -1082,13 +1142,25 @@ namespace AZ
meshView.m_morphTargetVertexDataView = RHI::BufferViewDescriptor::CreateStructured(0, numTotalVertices, sizeof(PackedCompressedMorphTargetDelta));
}
if (!mesh.m_clothData.empty())
{
auto meshClothDataFloatCount = static_cast<uint32_t>(mesh.m_clothData.size());
AZ_Assert((meshClothDataFloatCount % ClothDataFloatsPerVert) == 0,
"Unexpected number of cloth data elements (%d), it should contain a multiple of %d elements.", meshClothDataFloatCount, ClothDataFloatsPerVert);
auto meshClothDataCount = meshClothDataFloatCount / ClothDataFloatsPerVert;
AZ_Assert(meshClothDataCount == meshPositionCount,
"Number of cloth data elements (%d) does not match the number of positions (%d) in the mesh", meshClothDataCount, meshPositionCount);
meshView.m_clothDataView = RHI::BufferViewDescriptor::CreateTyped(0, meshClothDataCount, ClothDataFormat);
}
meshView.m_materialUid = mesh.m_materialUid;
return meshView;
}
void ModelAssetBuilderComponent::MergeMeshesToCommonBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContentList& lodMeshList,
ProductMeshContent& lodMeshContent,
ProductMeshViewList& meshViews)
@@ -1120,6 +1192,7 @@ namespace AZ
auto meshNormalsFloatCount = static_cast<uint32_t>(mesh.m_normals.size());
auto meshTangentsFloatCount = static_cast<uint32_t>(mesh.m_tangents.size());
auto meshBitangentsFloatCount = static_cast<uint32_t>(mesh.m_bitangents.size());
auto meshClothDataFloatCount = static_cast<uint32_t>(mesh.m_clothData.size());
// For each element we need to:
// record the offset for the view
@@ -1199,20 +1272,24 @@ namespace AZ
}
}
if (!mesh.m_clothData.empty())
{
const uint32_t elementOffset = static_cast<uint32_t>(lodBufferInfo.m_clothDataFloatCount) / ClothDataFloatsPerVert;
meshView.m_clothDataView = RHI::BufferViewDescriptor::CreateTyped(elementOffset, meshVertexCount, ClothDataFormat);
lodBufferInfo.m_clothDataFloatCount += meshClothDataFloatCount;
}
meshView.m_materialUid = mesh.m_materialUid;
if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(),
"Number of skin influence joint indices (%d) should match the number of weights (%d).",
mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size());
AZ_Assert(mesh.m_skinWeights.size() % maxNumSkinInfluencesPerVertex == 0,
AZ_Assert(mesh.m_skinWeights.size() % m_numSkinJointInfluencesPerVertex == 0,
"The number of skin influences per vertex (%d) is not a multiple of the total number of skinning weights (%d). This means that not every vertex has exactly (%d) skinning weights and invalidates the data.",
mesh.m_skinWeights.size(), maxNumSkinInfluencesPerVertex, maxNumSkinInfluencesPerVertex);
mesh.m_skinWeights.size(), m_numSkinJointInfluencesPerVertex, m_numSkinJointInfluencesPerVertex);
const size_t numPrevSkinInfluences = lodBufferInfo.m_skinInfluencesCount;
const size_t numNewSkinInfluences = mesh.m_skinWeights.size();
@@ -1253,6 +1330,7 @@ namespace AZ
size_t normalCount = 0;
size_t tangentCount = 0;
size_t bitangentCount = 0;
size_t clothDataCount = 0;
AZStd::vector<size_t> uvSetCounts;
AZStd::vector<size_t> colorSetCounts;
@@ -1263,6 +1341,7 @@ namespace AZ
normalCount += mesh.m_normals.size();
tangentCount += mesh.m_tangents.size();
bitangentCount += mesh.m_bitangents.size();
clothDataCount += mesh.m_clothData.size();
if (mesh.m_uvSets.size() > uvSetCounts.size())
{
@@ -1290,6 +1369,7 @@ namespace AZ
mergedMesh.m_normals.reserve(normalCount);
mergedMesh.m_tangents.reserve(tangentCount);
mergedMesh.m_bitangents.reserve(bitangentCount);
mergedMesh.m_clothData.reserve(clothDataCount);
mergedMesh.m_uvCustomNames.resize(uvSetCounts.size());
for (auto& mesh : productMeshList)
@@ -1424,6 +1504,12 @@ namespace AZ
auto& mergedMorphTargetData = mergedMesh.m_morphTargetVertexData;
mergedMorphTargetData.insert(mergedMorphTargetData.end(), sourceMorphTargetData.begin(), sourceMorphTargetData.end());
}
if (!mesh.m_clothData.empty())
{
mergedMesh.m_clothData.insert(
mergedMesh.m_clothData.end(), mesh.m_clothData.begin(), mesh.m_clothData.end());
}
}
return mergedMesh;
@@ -1522,7 +1608,6 @@ namespace AZ
};
bool ModelAssetBuilderComponent::CreateModelLodBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContent& lodBufferContent,
BufferAssetView& outIndexBuffer,
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& outStreamBuffers,
@@ -1537,6 +1622,7 @@ namespace AZ
const AZStd::vector<AZ::Name>& uvCustomNames = lodBufferContent.m_uvCustomNames;
const AZStd::vector<AZStd::vector<float>>& colorSets = lodBufferContent.m_colorSets;
const AZStd::vector<AZ::Name>& colorCustomNames = lodBufferContent.m_colorCustomNames;
const AZStd::vector<float>& clothData = lodBufferContent.m_clothData;
// Build Index Buffer ...
{
@@ -1598,10 +1684,8 @@ namespace AZ
const AZStd::vector<float>& skinWeights = lodBufferContent.m_skinWeights;
if (!skinJointIndices.empty() && !skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
const size_t vertexCount = positions.size() / PositionFloatsPerVert;
const size_t numSkinInfluences = vertexCount * maxNumSkinInfluencesPerVertex;
const size_t numSkinInfluences = vertexCount * m_numSkinJointInfluencesPerVertex;
if (!BuildRawStreamBuffer<uint16_t>(outStreamBuffers, skinJointIndices, RHI::ShaderSemantic{ShaderSemanticName_SkinJointIndices}))
{
@@ -1625,6 +1709,14 @@ namespace AZ
}
}
if (!clothData.empty())
{
if (!BuildTypedStreamBuffer<float>(outStreamBuffers, clothData, ClothDataFormat, RHI::ShaderSemantic{ ShaderSemanticName_ClothData }))
{
return false;
}
}
lodAssetCreator.SetLodIndexBuffer(outIndexBuffer.GetBufferAsset());
for (const auto& streamBufferInfo : outStreamBuffers)
@@ -1758,6 +1850,15 @@ namespace AZ
}
}
// Set cloth data buffer
if (meshView.m_clothDataView.m_elementCount > 0)
{
if (!SetMeshStreamBufferById(RHI::ShaderSemantic{ ShaderSemanticName_ClothData }, AZ::Name(), meshView.m_clothDataView, lodStreamBuffers, lodAssetCreator))
{
return false;
}
}
lodAssetCreator.EndMesh();
return true;
@@ -2014,15 +2115,5 @@ namespace AZ
return transform;
}
AZ::u32 ModelAssetBuilderComponent::ExtractMaxNumInfluencesPerVertex(const SceneAPI::DataTypes::ISkinRule* skinRule) const
{
if (skinRule)
{
return skinRule->GetMaxWeightsPerVertex();
}
return DefaultSkinInfluencesPerVert;
}
} // namespace RPI
} // namespace AZ
@@ -90,6 +90,7 @@ namespace AZ
AZStd::vector<AZStd::shared_ptr<const UVData>> m_meshUVData;
AZStd::vector<AZStd::shared_ptr<const ColorData>> m_meshColorData;
AZStd::vector<AZStd::shared_ptr<const SkinData>> m_skinData;
AZStd::vector<AZ::Color> m_meshClothData;
AZStd::vector<MaterialUid> m_materials;
bool m_isMorphed = false;
@@ -110,6 +111,7 @@ namespace AZ
AZStd::vector<AZ::Name> m_uvCustomNames;
AZStd::vector<AZStd::vector<float>> m_colorSets;
AZStd::vector<AZ::Name> m_colorCustomNames;
AZStd::vector<float> m_clothData;
//! Joint index per vertex in range [0, numJoints].
//! Note: The joint indices have to match the used skeleton when applying skinning.
@@ -121,7 +123,7 @@ namespace AZ
AZStd::vector<RPI::PackedCompressedMorphTargetDelta> m_morphTargetVertexData;
MaterialUid m_materialUid;
bool CanBeMerged() const { return true; }
bool CanBeMerged() const { return m_clothData.empty(); }
};
using ProductMeshContentList = AZStd::vector<ProductMeshContent>;
@@ -143,6 +145,7 @@ namespace AZ
size_t m_normalsFloatCount = 0;
size_t m_tangentsFloatCount = 0;
size_t m_bitangentsFloatCount = 0;
size_t m_clothDataFloatCount = 0;
AZStd::vector<size_t> m_uvSetFloatCounts;
AZStd::vector<size_t> m_colorSetFloatCounts;
size_t m_skinInfluencesCount = 0;
@@ -173,6 +176,8 @@ namespace AZ
RHI::BufferViewDescriptor m_morphTargetVertexDataView;
RHI::BufferViewDescriptor m_clothDataView;
MaterialUid m_materialUid;
};
using ProductMeshViewList = AZStd::vector<ProductMeshView>;
@@ -197,13 +202,12 @@ namespace AZ
const ProductMeshContentList& productMeshList);
//! Simple helper to create a MeshView that views an entire given ProductMeshContent object as one mesh.
ProductMeshView CreateViewToEntireMesh(const ModelAssetBuilderContext& context, const ProductMeshContent& mesh);
ProductMeshView CreateViewToEntireMesh(const ProductMeshContent& mesh);
//! Takes a ProductMeshContentList and merges all elements into a single ProductMeshContent object.
//! This also produces a ProductMeshViewList that contains views to all
//! the original meshes described in the lodMeshList collection.
void MergeMeshesToCommonBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContentList& lodMeshList,
ProductMeshContent& lodMeshContent,
ProductMeshViewList& meshViewsPerLodBuffer);
@@ -274,7 +278,6 @@ namespace AZ
//!
//! Returns false if an error occurs
bool CreateModelLodBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContent& lodBufferContent,
BufferAssetView& outIndexBuffer,
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& outStreamBuffers,
@@ -356,6 +359,9 @@ namespace AZ
AZStd::string m_lodName;
AZStd::string m_meshName;
size_t m_numSkinJointInfluencesPerVertex = 0;
float m_skinWeightThreshold = 0.0f;
AZStd::set<uint32_t> m_createdSubId;
// NOTE: This is explicitly fetched from a filename. In the future, this should be fetched from the RPI system
@@ -366,15 +372,13 @@ namespace AZ
SceneAPI::DataTypes::MatrixType GetWorldTransform(const SceneAPI::Containers::SceneGraph& sceneGraph, SceneAPI::Containers::SceneGraph::NodeIndex node);
private:
//! Collects skinning influences from the SceneAPI source mesh and fills them in the resulting mesh
void GatherSkinningInfluences(
const ModelAssetBuilderContext& context,
//! Collects skinning influences of a vertex from the SceneAPI source mesh and fills them in the resulting mesh
void GatherVertexSkinningInfluences(
const SourceMeshContent& sourceMesh,
ProductMeshContent& productMesh,
AZStd::unordered_map<AZStd::string, uint16_t>& jointNameToIndexMap,
size_t vertexIndex) const;
AZ::u32 ExtractMaxNumInfluencesPerVertex(const SceneAPI::DataTypes::ISkinRule* skinRule) const;
size_t vertexIndex,
bool& warnedExcessOfSkinInfluences) const;
};
} // namespace RPI
} // namespace AZ
@@ -104,8 +104,10 @@ namespace AZ::RPI
AZ_Assert(blendShapeData, "Node is expected to be a blend shape.");
if (blendShapeData)
{
#if defined(AZ_ENABLE_TRACING)
const Containers::SceneGraph::NodeIndex morphMeshParentIndex = sceneGraph.GetNodeParent(sceneNodeIndex);
const char* meshNodeName = sceneGraph.GetNodeName(morphMeshParentIndex).GetName();
#endif
AZ_Assert(AZ::StringFunc::Equal(sourceMesh.m_name.GetCStr(), meshNodeName, /*bCaseSensitive=*/true),
"Scene graph mesh node (%s) has a different name than the product mesh (%s).",
@@ -50,7 +50,6 @@ namespace AZ
return false;
}
MaterialPropertyDataType dataType = propertyDescriptor->GetDataType();
AZ::TypeId typeId = propertyDescriptor->GetStorageDataTypeId();
auto iter = m_possibleValues.find(typeId);
if (iter != m_possibleValues.end())
@@ -60,7 +59,7 @@ namespace AZ
if (!m_resolvedValue.IsValid())
{
AZ_Error("MaterialPropertyValueSourceData", false, "Value for material property '%s' is invalid. %s is required.", materialPropertyName.GetCStr(), ToString(dataType));
AZ_Error("MaterialPropertyValueSourceData", false, "Value for material property '%s' is invalid. %s is required.", materialPropertyName.GetCStr(), ToString(propertyDescriptor->GetDataType()));
return false;
}
@@ -79,7 +79,7 @@ namespace AZ
}
// Tell the FrameGraph which RHI QueryPool, and which RHI Queries need to be used.
RHI::ResultCode resultCode = frameGraph.UseQueryPool(m_queryPool->m_rhiQueryPool, rhiQueryIndices.value(), m_attachmentType, m_attachmentAccess);
[[maybe_unused]] RHI::ResultCode resultCode = frameGraph.UseQueryPool(m_queryPool->m_rhiQueryPool, rhiQueryIndices.value(), m_attachmentType, m_attachmentAccess);
AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to add the queries to the scope builder");
// Invalidate the ScopeId.
@@ -108,7 +108,7 @@ namespace AZ
return QueryResultCode::Fail;
}
RHI::ResultCode resultCode = m_queryPool->BeginQueryInternal(rhiQueryIndices.value(), *context.GetCommandList());
[[maybe_unused]] RHI::ResultCode resultCode = m_queryPool->BeginQueryInternal(rhiQueryIndices.value(), *context.GetCommandList());
AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to begin recording the query");
m_cachedScopeId = context.GetScopeId();
@@ -144,7 +144,7 @@ namespace AZ
return QueryResultCode::Fail;
}
RHI::ResultCode resultCode = m_queryPool->EndQueryInternal(rhiQueryIndices.value(), *context.GetCommandList());
[[maybe_unused]] RHI::ResultCode resultCode = m_queryPool->EndQueryInternal(rhiQueryIndices.value(), *context.GetCommandList());
AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to end recording the query");
return QueryResultCode::Success;
@@ -57,7 +57,7 @@ namespace AZ
queryPoolDesc.m_pipelineStatisticsMask = m_statisticsFlags;
m_rhiQueryPool = RHI::Factory::Get().CreateQueryPool();
auto result = m_rhiQueryPool->Init(*device, queryPoolDesc);
[[maybe_unused]] auto result = m_rhiQueryPool->Init(*device, queryPoolDesc);
AZ_Assert(result == RHI::ResultCode::Success, "Failed to create the query pool");
}
@@ -504,7 +504,7 @@ namespace AZ
// Re-initialize the image.
Shutdown();
RHI::ResultCode resultCode = Init(*imageAsset);
[[maybe_unused]] RHI::ResultCode resultCode = Init(*imageAsset);
AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to re-initialize streaming image");
}
@@ -137,7 +137,7 @@ namespace AZ
return m_modelAsset;
}
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance) const
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
float firstHit;
@@ -150,7 +150,7 @@ namespace AZ
AZ::Debug::Timer timer;
timer.Stamp();
#endif
const bool hit = modelAssetPtr->LocalRayIntersectionAgainstModel(rayStart, dir, distance);
const bool hit = modelAssetPtr->LocalRayIntersectionAgainstModel(rayStart, dir, distance, normal);
#if defined(AZ_RPI_PROFILE_RAYCASTING_AGAINST_MODELS)
if (hit)
{
@@ -164,7 +164,7 @@ namespace AZ
return false;
}
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
const AZ::Transform inverseTM = modelTransform.GetInverse();
@@ -175,7 +175,7 @@ namespace AZ
const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest);
const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal;
return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor);
return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor, normal);
}
const AZStd::unordered_set<AZ::Name>& Model::GetUvNames() const
@@ -92,7 +92,7 @@ namespace AZ
AZ_Assert(pass->m_parent == this, "Trying to remove a pass of which we are not the parent.");
// Find child and move it to the end of the list
auto it = AZStd::remove(m_children.begin(), m_children.end(), pass);
[[maybe_unused]] auto it = AZStd::remove(m_children.begin(), m_children.end(), pass);
AZ_Assert((it + 1) == m_children.end(), "Pass::RemoveChild found more than one Ptr<Pass> in m_children, which is not allowed.");
// Delete the child that is now at the end of the list
@@ -220,7 +220,7 @@ namespace AZ
TemplateEntry* entry = GetEntry(pass->m_template->m_name);
if (entry)
{
auto iter = AZStd::remove(entry->m_passes.begin(), entry->m_passes.end(), pass);
[[maybe_unused]] auto iter = AZStd::remove(entry->m_passes.begin(), entry->m_passes.end(), pass);
AZ_Assert((iter + 1) == entry->m_passes.end(),
"Pass [%s] is being deleted but was not registered with it's PassTemlate [%s] in the PassLibrary.",
@@ -372,7 +372,6 @@ namespace AZ
{
RHI::Format format = imageAttachment.m_imageDescriptor.m_format;
AZStd::string formatLocation = AZStd::string::format("PassAttachmentDesc [%s] on PassTemplate [%s]", imageAttachment.m_name.GetCStr(), passTemplate->m_name.GetCStr());
RHI::FormatCapabilities capabilities = RHI::FormatCapabilities::Sample;
imageAttachment.m_imageDescriptor.m_format = RHI::ValidateFormat(format, formatLocation.c_str(), imageAttachment.m_formatFallbacks);
}
@@ -82,7 +82,7 @@ namespace AZ
}
RHI::RenderAttachmentLayout layout;
RHI::ResultCode result = builder.End(layout);
[[maybe_unused]] RHI::ResultCode result = builder.End(layout);
AZ_Assert(result == RHI::ResultCode::Success, "RenderPass [%s] failed to create render attachment layout", GetPathName().GetCStr());
return RHI::RenderAttachmentConfiguration{ layout, 0 };
}
@@ -151,7 +151,6 @@ namespace AZ
{
if (passAttachment == binding.m_attachment)
{
RHI::AttachmentType type = binding.m_attachment->GetAttachmentType();
RHI::AttachmentId attachmentId = binding.m_attachment->GetAttachmentId();
// Append slot index and pass name so the read back's name won't be same as the attachment used in other passes.
@@ -496,6 +496,11 @@ namespace AZ
m_renderMode = RenderMode::NoRender;
m_rootPass->SetEnabled(false);
}
RenderPipeline::RenderMode RenderPipeline::GetRenderMode() const
{
return m_renderMode;
}
bool RenderPipeline::NeedsRender() const
{
@@ -288,6 +288,11 @@ namespace AZ
return false;
}
bool ShaderResourceGroup::SetImageViewUnboundedArray(RHI::ShaderInputImageUnboundedArrayIndex inputIndex, AZStd::array_view<const RHI::ImageView*> imageViews)
{
return m_data.SetImageViewUnboundedArray(inputIndex, imageViews);
}
bool ShaderResourceGroup::SetBufferView(RHI::ShaderInputNameIndex& inputIndex, const RHI::BufferView* bufferView, uint32_t arrayIndex)
{
if (inputIndex.ValidateOrFindBufferIndex(GetLayout()))
@@ -334,6 +339,11 @@ namespace AZ
return false;
}
bool ShaderResourceGroup::SetBufferViewUnboundedArray(RHI::ShaderInputBufferUnboundedArrayIndex inputIndex, AZStd::array_view<const RHI::BufferView*> bufferViews)
{
return m_data.SetBufferViewUnboundedArray(inputIndex, bufferViews);
}
bool ShaderResourceGroup::SetSampler(RHI::ShaderInputNameIndex& inputIndex, const RHI::SamplerState& sampler, uint32_t arrayIndex)
{
if (inputIndex.ValidateOrFindSamplerIndex(GetLayout()))
@@ -101,8 +101,11 @@ namespace AZ
void ViewportContext::RenderTick()
{
if (m_currentPipeline)
// add the current pipeline to next render tick if it's not already added.
if (m_currentPipeline && m_currentPipeline->GetRenderMode() != RenderPipeline::RenderMode::RenderOnce)
{
ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick);
ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick);
m_currentPipeline->AddToRenderTickOnce();
}
}
@@ -23,6 +23,7 @@ namespace AZ
ViewportContextManager::ViewportContextManager()
{
AZ::Interface<ViewportContextRequestsInterface>::Register(this);
m_defaultViewportContextName = AZ::Name(s_defaultViewportContextName);
}
ViewportContextManager::~ViewportContextManager()
@@ -185,7 +186,12 @@ namespace AZ
AZ::Name ViewportContextManager::GetDefaultViewportContextName() const
{
return AZ::Name(s_defaultViewportContextName);
return m_defaultViewportContextName;
}
ViewportContextPtr ViewportContextManager::GetDefaultViewportContext() const
{
return GetViewportContextByName(m_defaultViewportContextName);
}
void ViewportContextManager::PushView(const Name& context, ViewPtr view)
@@ -63,8 +63,7 @@ namespace AZ
}
else
{
const Name& shaderOptionName = layout->GetShaderOption(optionIndex).GetName();
AZ_Error("MaterialFunctor", false, "Shader option '%s' is not owned by this material.", shaderOptionName.GetCStr());
AZ_Error("MaterialFunctor", false, "Shader option '%s' is not owned by this material.", layout->GetShaderOption(optionIndex).GetName().GetCStr());
}
return false;
@@ -395,11 +394,13 @@ namespace AZ
template const Color& MaterialFunctor::EditorContext::GetMaterialPropertyValue<Color> (const MaterialPropertyIndex& index) const;
template const Data::Instance<Image>& MaterialFunctor::EditorContext::GetMaterialPropertyValue<Data::Instance<Image>> (const MaterialPropertyIndex& index) const;
void CheckPropertyAccess(const MaterialPropertyIndex& index, const MaterialPropertyFlags& materialPropertyDependencies, const MaterialPropertiesLayout& materialPropertiesLayout)
void CheckPropertyAccess(const MaterialPropertyIndex& index, const MaterialPropertyFlags& materialPropertyDependencies, [[maybe_unused]] const MaterialPropertiesLayout& materialPropertiesLayout)
{
if (!materialPropertyDependencies.test(index.GetIndex()))
{
#if defined(AZ_ENABLE_TRACING)
const MaterialPropertyDescriptor* propertyDescriptor = materialPropertiesLayout.GetPropertyDescriptor(index);
#endif
AZ_Error("MaterialFunctor", false, "Material functor accessing an unregistered material property '%s'.",
propertyDescriptor ? propertyDescriptor->GetName().GetCStr() : "<unknown>");
}
@@ -75,7 +75,7 @@ namespace AZ
m_status = Data::AssetData::AssetStatus::Ready;
}
bool ModelAsset::LocalRayIntersectionAgainstModel(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance) const
bool ModelAsset::LocalRayIntersectionAgainstModel(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
@@ -97,11 +97,11 @@ namespace AZ
}
else
{
return m_kdTree->RayIntersection(rayStart, dir, distance);
return m_kdTree->RayIntersection(rayStart, dir, distance, normal);
}
}
return BruteForceRayIntersect(rayStart, dir, distance);
return BruteForceRayIntersect(rayStart, dir, distance, normal);
}
void ModelAsset::BuildKdTree() const
@@ -136,7 +136,7 @@ namespace AZ
}
}
bool ModelAsset::BruteForceRayIntersect(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance) const
bool ModelAsset::BruteForceRayIntersect(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
{
// brute force - check every triangle
if (GetLodAssets().empty() == false)
@@ -147,12 +147,18 @@ namespace AZ
float shortestDistance = std::numeric_limits<float>::max();
bool anyHit = false;
AZ::Vector3 intersectionNormal;
for (const ModelLodAsset::Mesh& mesh : loadAssetPtr->GetMeshes())
{
if (LocalRayIntersectionAgainstMesh(mesh, rayStart, dir, distance))
if (LocalRayIntersectionAgainstMesh(mesh, rayStart, dir, distance, intersectionNormal))
{
anyHit = true;
shortestDistance = AZ::GetMin(distance, shortestDistance);
if (distance < shortestDistance)
{
normal = intersectionNormal;
shortestDistance = distance;
}
}
}
@@ -168,7 +174,7 @@ namespace AZ
return false;
}
bool ModelAsset::LocalRayIntersectionAgainstMesh(const ModelLodAsset::Mesh& mesh, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance) const
bool ModelAsset::LocalRayIntersectionAgainstMesh(const ModelLodAsset::Mesh& mesh, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
{
const BufferAssetView& indexBufferView = mesh.GetIndexBufferAssetView();
const AZStd::array_view<ModelLodAsset::Mesh::StreamBufferInfo>& streamBufferList = mesh.GetStreamBufferInfoList();
@@ -216,7 +222,7 @@ namespace AZ
const AZ::Vector3 rayEnd = rayStart + dir * distance;
AZ::Vector3 a, b, c;
AZ::Vector3 normal;
AZ::Vector3 intersectionNormal;
float normalizedDistance = 1.f;
const AZ::u32* indexPtr = reinterpret_cast<const AZ::u32*>(indexRawBuffer.data());
@@ -241,9 +247,13 @@ namespace AZ
p = reinterpret_cast<const float*>(&positionRawBuffer[index2 * positionElementSize]);
c.Set(const_cast<float*>(p));
if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, normal, normalizedDistance))
if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, intersectionNormal, normalizedDistance))
{
closestNormalizedDistance = AZ::GetMin(closestNormalizedDistance, normalizedDistance);
if (normalizedDistance < closestNormalizedDistance)
{
normal = intersectionNormal;
closestNormalizedDistance = normalizedDistance;
}
anyHit = true;
}
}
@@ -221,12 +221,12 @@ namespace AZ
}
}
bool ModelKdTree::RayIntersection(const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance) const
bool ModelKdTree::RayIntersection(const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const
{
return RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, distance);
return RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, distance, normal);
}
bool ModelKdTree::RayIntersectionRecursively(ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance) const
bool ModelKdTree::RayIntersectionRecursively(ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const
{
if (!pNode)
{
@@ -252,7 +252,7 @@ namespace AZ
return false;
}
AZ::Vector3 ignoreNormal;
AZ::Vector3 intersectionNormal;
float hitDistanceNormalized;
const float maxDist(FLT_MAX);
float nearestDist = maxDist;
@@ -278,9 +278,15 @@ namespace AZ
const AZ::Vector3 rayEnd = raySrc + rayDir * distance;
if (AZ::Intersect::IntersectSegmentTriangleCCW(raySrc, rayEnd, trianglePoints[0], trianglePoints[1], trianglePoints[2],
ignoreNormal, hitDistanceNormalized) != Intersect::ISECT_RAY_AABB_NONE)
intersectionNormal, hitDistanceNormalized) != Intersect::ISECT_RAY_AABB_NONE)
{
float hitDistance = hitDistanceNormalized * distance;
if (nearestDist > hitDistance)
{
normal = intersectionNormal;
}
nearestDist = AZStd::GetMin(nearestDist, hitDistance);
}
}
@@ -295,8 +301,8 @@ namespace AZ
}
// running both sides to find the closest intersection
const bool bFoundChild0 = RayIntersectionRecursively(pNode->GetChild(0), raySrc, rayDir, distance);
const bool bFoundChild1 = RayIntersectionRecursively(pNode->GetChild(1), raySrc, rayDir, distance);
const bool bFoundChild0 = RayIntersectionRecursively(pNode->GetChild(0), raySrc, rayDir, distance, normal);
const bool bFoundChild1 = RayIntersectionRecursively(pNode->GetChild(1), raySrc, rayDir, distance, normal);
return bFoundChild0 || bFoundChild1;
}
@@ -138,19 +138,6 @@ namespace AZ
return nullptr;
}
AZStd::array_view<uint8_t> ModelLodAsset::Mesh::GetSemanticBuffer(const AZ::Name& semantic) const
{
if (const BufferAssetView* bufferAssetView = GetSemanticBufferAssetView(semantic))
{
if (const BufferAsset* bufferAsset = bufferAssetView->GetBufferAsset().Get())
{
return bufferAsset->GetBuffer();
}
}
return {};
}
void ModelLodAsset::SetReady()
{
m_status = Data::AssetData::AssetStatus::Ready;
@@ -39,6 +39,7 @@ namespace AZ
serializeContext->Class<PrecompiledShaderAssetSourceData>()
->Version(0)
->Field("ShaderAssetFileName", &PrecompiledShaderAssetSourceData::m_shaderAssetFileName)
->Field("PlatformIdentifiers", &PrecompiledShaderAssetSourceData::m_platformIdentifiers)
->Field("ShaderResourceGroupAssets", &PrecompiledShaderAssetSourceData::m_srgAssetFileNames)
->Field("RootShaderVariantAssets", &PrecompiledShaderAssetSourceData::m_rootShaderVariantAssets)
;
@@ -264,7 +264,7 @@ namespace AZ
if (!foundVariantAsset)
{
ReportError("Failed to find variant asset for API [%d]", perAPIShaderData.m_APIType);
ReportWarning("Failed to find variant asset for API [%d]", perAPIShaderData.m_APIType);
}
m_asset->m_perAPIShaderData.push_back(perAPIShaderData);
@@ -80,6 +80,22 @@ namespace AZ
}
}
void ShaderResourceGroupAssetCreator::AddShaderInput(const RHI::ShaderInputBufferUnboundedArrayDescriptor& shaderInputBufferUnboundedArray)
{
if (ValidateIsReady())
{
m_shaderResourceGroupLayout->AddShaderInput(shaderInputBufferUnboundedArray);
}
}
void ShaderResourceGroupAssetCreator::AddShaderInput(const RHI::ShaderInputImageUnboundedArrayDescriptor& shaderInputImageUnboundedArray)
{
if (ValidateIsReady())
{
m_shaderResourceGroupLayout->AddShaderInput(shaderInputImageUnboundedArray);
}
}
void ShaderResourceGroupAssetCreator::AddShaderInput(const RHI::ShaderInputSamplerDescriptor& shaderInputSampler)
{
if (ValidateIsReady())
@@ -150,4 +166,4 @@ namespace AZ
return true;
}
} // namespace RPI
} // namespace AZ
} // namespace AZ