diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli index b8c97ef421..4ccaabd067 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli @@ -156,15 +156,15 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene #define MESH_INDEX_BUFFER_OFFSET 0 #define MESH_POSITION_BUFFER_OFFSET 1 #define MESH_NORMAL_BUFFER_OFFSET 2 - #define MESH_TANGENT_BUFFER_OFFSET 3 - #define MESH_BITANGENT_BUFFER_OFFSET 4 // buffer flag bits indicating if optional buffers are present - #define MESH_BUFFER_FLAG_UV 1 + #define MESH_BUFFER_FLAG_TANGENT 1 + #define MESH_BUFFER_FLAG_BITANGENT 2 + #define MESH_BUFFER_FLAG_UV 3 // Unbounded array of mesh stream buffers: - // - Index, Position, Normal, Tangent, and Bitangent stream buffers are always present - // - Optional stream buffers such as UV are indicated in the MeshInfo.m_bufferFlags field + // - Index, Position, Normal stream buffers are always present + // - Optional stream buffers such as Tangent, Bitangent, and UV are indicated in the MeshInfo.m_bufferFlags field // - Buffers for a particular mesh start at MeshInfo.m_bufferStartIndex ByteAddressBuffer m_meshBuffers[]; } \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli index f858b9a11a..654879f39f 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli @@ -79,10 +79,14 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i]; } + // optional streams begin after MESH_NORMAL_BUFFER_OFFSET + uint optionalBufferOffset = MESH_NORMAL_BUFFER_OFFSET + 1; + // tangent + if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_TANGENT) { // array index of the tangent buffer for this mesh in the m_meshBuffers unbounded array - uint meshVertexTangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_TANGENT_BUFFER_OFFSET; + uint meshVertexTangentArrayIndex = meshInfo.m_bufferStartIndex + optionalBufferOffset++; // offset into the tangent buffer for this vertex uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 12); @@ -92,9 +96,10 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f } // bitangent + if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_BITANGENT) { // array index of the bitangent buffer for this mesh in the m_meshBuffers unbounded array - uint meshVertexBitangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_BITANGENT_BUFFER_OFFSET; + uint meshVertexBitangentArrayIndex = meshInfo.m_bufferStartIndex + optionalBufferOffset++; // offset into the bitangent buffer for this vertex uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12); @@ -103,9 +108,6 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i]; } - // optional streams begin after MESH_BITANGENT_BUFFER_OFFSET - uint optionalBufferOffset = MESH_BITANGENT_BUFFER_OFFSET + 1; - // UV if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_UV) { diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 359d0bd279..4e7dd5d3f0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -734,10 +734,12 @@ namespace AZ RPI::ShaderInputContract::StreamChannelInfo tangentStreamChannelInfo; tangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(TangentSemantic)); tangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(TangentStreamFormat); + tangentStreamChannelInfo.m_isOptional = true; RPI::ShaderInputContract::StreamChannelInfo bitangentStreamChannelInfo; bitangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(BitangentSemantic)); bitangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(BitangentStreamFormat); + bitangentStreamChannelInfo.m_isOptional = true; RPI::ShaderInputContract::StreamChannelInfo uvStreamChannelInfo; uvStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(UVSemantic)); @@ -776,7 +778,7 @@ namespace AZ // retrieve vertex/index buffers RPI::ModelLod::StreamBufferViewList streamBufferViews; - bool result = modelLod->GetStreamsForMesh( + [[maybe_unused]] bool result = modelLod->GetStreamsForMesh( inputStreamLayout, streamBufferViews, nullptr, @@ -784,12 +786,7 @@ namespace AZ meshIndex, materialAssignment.m_matModUvOverrides, material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap()); - - if (!result) - { - AZ_Warning("MeshFeatureProcessor", false, "Mesh is missing required vertex streams for RayTracing. Skipping."); - continue; - } + AZ_Assert(result, "Failed to retrieve mesh stream buffer views"); // note that the element count is the size of the entire buffer, even though this mesh may only // occupy a portion of the vertex buffer. This is necessary since we are accessing it using @@ -828,13 +825,21 @@ namespace AZ subMesh.m_normalVertexBufferView = streamBufferViews[1]; subMesh.m_normalShaderBufferView = const_cast(streamBufferViews[1].GetBuffer())->GetBufferView(normalBufferDescriptor); - subMesh.m_tangentFormat = TangentStreamFormat; - subMesh.m_tangentVertexBufferView = streamBufferViews[2]; - subMesh.m_tangentShaderBufferView = const_cast(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor); + if (tangentBufferByteCount > 0) + { + subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Tangent; + subMesh.m_tangentFormat = TangentStreamFormat; + subMesh.m_tangentVertexBufferView = streamBufferViews[2]; + subMesh.m_tangentShaderBufferView = const_cast(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor); + } - subMesh.m_bitangentFormat = BitangentStreamFormat; - subMesh.m_bitangentVertexBufferView = streamBufferViews[3]; - subMesh.m_bitangentShaderBufferView = const_cast(streamBufferViews[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor); + if (bitangentBufferByteCount > 0) + { + subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Bitangent; + subMesh.m_bitangentFormat = BitangentStreamFormat; + subMesh.m_bitangentVertexBufferView = streamBufferViews[3]; + subMesh.m_bitangentShaderBufferView = const_cast(streamBufferViews[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor); + } if (uvBufferByteCount > 0) { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 2db396e36d..059a9d92dd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -243,8 +243,16 @@ namespace AZ meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset(); meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset(); meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset(); - meshInfo.m_tangentOffset = subMesh.m_tangentVertexBufferView.GetByteOffset(); - meshInfo.m_bitangentOffset = subMesh.m_bitangentVertexBufferView.GetByteOffset(); + + if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::Tangent)) + { + meshInfo.m_tangentOffset = subMesh.m_tangentVertexBufferView.GetByteOffset(); + } + + if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::Bitangent)) + { + meshInfo.m_bitangentOffset = subMesh.m_bitangentVertexBufferView.GetByteOffset(); + } if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV)) { @@ -257,8 +265,8 @@ namespace AZ meshInfo.m_bufferStartIndex = bufferStartIndex; // add the count of buffers present in this subMesh to the start index for the next subMesh - // note that the Index, Position, Normal, Tangent, and Bitangent buffers are always counted since they are guaranteed - static const uint32_t RayTracingSubMeshFixedStreamCount = 5; + // note that the Index, Position, and Normal buffers are always counted since they are guaranteed + static const uint32_t RayTracingSubMeshFixedStreamCount = 3; bufferStartIndex += (RayTracingSubMeshFixedStreamCount + RHI::CountBitsSet(aznumeric_cast(meshInfo.m_bufferFlags))); meshInfos.emplace_back(meshInfo); @@ -423,8 +431,16 @@ namespace AZ meshBuffers.push_back(subMesh.m_indexShaderBufferView.get()); meshBuffers.push_back(subMesh.m_positionShaderBufferView.get()); meshBuffers.push_back(subMesh.m_normalShaderBufferView.get()); - meshBuffers.push_back(subMesh.m_tangentShaderBufferView.get()); - meshBuffers.push_back(subMesh.m_bitangentShaderBufferView.get()); + + if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::Tangent)) + { + meshBuffers.push_back(subMesh.m_tangentShaderBufferView.get()); + } + + if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::Bitangent)) + { + meshBuffers.push_back(subMesh.m_bitangentShaderBufferView.get()); + } if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV)) { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 90a9383ae6..11dcc5a11f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -32,7 +32,9 @@ namespace AZ { None = 0, - UV = AZ_BIT(0) + Tangent = AZ_BIT(0), + Bitangent = AZ_BIT(1), + UV = AZ_BIT(2) }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);