Added RayTracingMaterialSrg.
Added UV buffer to the RayTracingSceneSrg mesh buffers. Added RayTracingSceneUtils and RayTracingMaterialUtils shader includes.
This commit is contained in:
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
|
||||
{
|
||||
Sampler LinearSampler
|
||||
{
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Linear;
|
||||
MaxAnisotropy = 16;
|
||||
};
|
||||
|
||||
// material info structured buffer
|
||||
struct MaterialInfo
|
||||
{
|
||||
float4 m_baseColor;
|
||||
float m_metallicFactor;
|
||||
float m_roughnessFactor;
|
||||
uint m_textureFlags;
|
||||
uint m_textureStartIndex;
|
||||
};
|
||||
|
||||
// hit shaders can retrieve the MaterialInfo for a mesh hit using: RayTracingMaterialSrg::m_materialInfo[InstanceIndex()]
|
||||
StructuredBuffer<MaterialInfo> m_materialInfo;
|
||||
|
||||
// texture flag bits indicating if optional textures are present
|
||||
#define TEXTURE_FLAG_BASECOLOR 1
|
||||
#define TEXTURE_FLAG_NORMAL 2
|
||||
#define TEXTURE_FLAG_METALLIC 4
|
||||
#define TEXTURE_FLAG_ROUGHNESS 8
|
||||
|
||||
// unbounded array of Material textures
|
||||
Texture2D m_materialTextures[];
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
struct TextureData
|
||||
{
|
||||
float4 m_baseColor;
|
||||
float3 m_normal;
|
||||
float m_metallic;
|
||||
float m_roughness;
|
||||
};
|
||||
|
||||
TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo, float2 uv)
|
||||
{
|
||||
TextureData textureData = (TextureData)0;
|
||||
|
||||
uint textureIndex = materialInfo.m_textureStartIndex;
|
||||
|
||||
// base color
|
||||
if (materialInfo.m_textureFlags & TEXTURE_FLAG_BASECOLOR)
|
||||
{
|
||||
textureData.m_baseColor = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textureData.m_baseColor = materialInfo.m_baseColor;
|
||||
}
|
||||
|
||||
// normal
|
||||
if (materialInfo.m_textureFlags & TEXTURE_FLAG_NORMAL)
|
||||
{
|
||||
textureData.m_normal = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textureData.m_normal = float3(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
// metallic
|
||||
if (materialInfo.m_textureFlags & TEXTURE_FLAG_METALLIC)
|
||||
{
|
||||
textureData.m_metallic = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textureData.m_metallic = materialInfo.m_metallicFactor;
|
||||
}
|
||||
|
||||
// roughness
|
||||
if (materialInfo.m_textureFlags & TEXTURE_FLAG_ROUGHNESS)
|
||||
{
|
||||
textureData.m_roughness = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textureData.m_roughness = materialInfo.m_roughnessFactor;
|
||||
}
|
||||
|
||||
return textureData;
|
||||
}
|
||||
|
||||
+25
-8
@@ -136,18 +136,35 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
|
||||
uint m_indexOffset;
|
||||
uint m_positionOffset;
|
||||
uint m_normalOffset;
|
||||
uint m_tangentOffset;
|
||||
uint m_bitangentOffset;
|
||||
uint m_uvOffset;
|
||||
float m_padding0[2];
|
||||
|
||||
float4 m_irradianceColor;
|
||||
float3x3 m_worldInvTranspose;
|
||||
float m_padding1[1];
|
||||
|
||||
uint m_bufferFlags;
|
||||
uint m_bufferStartIndex;
|
||||
};
|
||||
|
||||
|
||||
// hit shaders can retrieve the MeshInfo for a mesh hit using: RayTracingSceneSrg::m_meshInfo[InstanceIndex()]
|
||||
StructuredBuffer<MeshInfo> m_meshInfo;
|
||||
|
||||
// unbounded array of Index, VertexPosition, and VertexNormal buffers
|
||||
// each mesh has three entries in this array starting at its InstanceIndex() * BUFFER_COUNT_PER_MESH
|
||||
#define BUFFER_COUNT_PER_MESH 3
|
||||
#define MESH_INDEX_BUFFER_OFFSET 0
|
||||
#define MESH_POSITION_BUFFER_OFFSET 1
|
||||
#define MESH_NORMAL_BUFFER_OFFSET 2
|
||||
|
||||
// buffer array index offsets for buffers that are always present for each mesh
|
||||
#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
|
||||
|
||||
// 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
|
||||
// - Buffers for a particular mesh start at MeshInfo.m_bufferStartIndex
|
||||
ByteAddressBuffer m_meshBuffers[];
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
// returns the normalized camera view ray into the scene for this raytracing dispatch thread
|
||||
float3 GetViewRayDirection(float4x4 viewProjectionInverseMatrix)
|
||||
{
|
||||
float2 pixel = ((float2)DispatchRaysIndex().xy + float2(0.5f, 0.5f)) / (float2)DispatchRaysDimensions();
|
||||
float2 ndc = pixel * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f);
|
||||
return normalize(mul(viewProjectionInverseMatrix, float4(ndc, 0.0f, 1.0f)).xyz);
|
||||
}
|
||||
|
||||
// returns the vertex indices for the primitive hit by the ray
|
||||
// Note: usable only in a raytracing Hit shader
|
||||
uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
|
||||
{
|
||||
// compute the array index of the index buffer for this mesh in the m_meshBuffers unbounded array
|
||||
uint meshIndexBufferArrayIndex = meshInfo.m_bufferStartIndex + MESH_INDEX_BUFFER_OFFSET;
|
||||
|
||||
// compute the offset into the index buffer for this primitve of the mesh
|
||||
uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
|
||||
|
||||
// load the indices for this primitive from the index buffer
|
||||
return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
|
||||
}
|
||||
|
||||
// returns the interpolated vertex data for the primitive hit by the ray
|
||||
// Note: usable only in a raytracing hit shader
|
||||
struct VertexData
|
||||
{
|
||||
float3 m_position;
|
||||
float3 m_normal;
|
||||
float3 m_tangent;
|
||||
float3 m_bitangent;
|
||||
float2 m_uv;
|
||||
};
|
||||
|
||||
VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, float2 builtInBarycentrics)
|
||||
{
|
||||
// retrieve the poly indices
|
||||
uint3 indices = GetHitIndices(meshInfo);
|
||||
|
||||
// compute barycentrics
|
||||
float3 barycentrics = float3((1.0f - builtInBarycentrics.x - builtInBarycentrics.y), builtInBarycentrics.x, builtInBarycentrics.y);
|
||||
|
||||
// compute the vertex data using barycentric interpolation
|
||||
VertexData vertexData = (VertexData)0;
|
||||
for (uint i = 0; i < 3; ++i)
|
||||
{
|
||||
// position
|
||||
{
|
||||
// array index of the position buffer for this mesh in the m_meshBuffers unbounded array
|
||||
uint meshVertexPositionArrayIndex = meshInfo.m_bufferStartIndex + MESH_POSITION_BUFFER_OFFSET;
|
||||
|
||||
// offset into the position buffer for this vertex
|
||||
uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
|
||||
|
||||
// load the position data
|
||||
vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
|
||||
}
|
||||
|
||||
// normal
|
||||
{
|
||||
// array index of the normal buffer for this mesh in the m_meshBuffers unbounded array
|
||||
uint meshVertexNormalArrayIndex = meshInfo.m_bufferStartIndex + MESH_NORMAL_BUFFER_OFFSET;
|
||||
|
||||
// offset into the normal buffer for this vertex
|
||||
uint normalOffset = meshInfo.m_normalOffset + (indices[i] * 12);
|
||||
|
||||
// load the normal data
|
||||
vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// offset into the tangent buffer for this vertex
|
||||
uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 12);
|
||||
|
||||
// load the tangent data
|
||||
vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load3(tangentOffset)) * barycentrics[i];
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// offset into the bitangent buffer for this vertex
|
||||
uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
|
||||
|
||||
// load the bitangent data
|
||||
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)
|
||||
{
|
||||
// array index of the UV buffer for this mesh in the m_meshBuffers unbounded array
|
||||
uint meshVertexUVArrayIndex = meshInfo.m_bufferStartIndex + optionalBufferOffset++;
|
||||
|
||||
// offset into the UV buffer for this vertex
|
||||
uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);
|
||||
|
||||
// load the UV data
|
||||
vertexData.m_uv += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex].Load2(uvOffset)) * barycentrics[i];
|
||||
}
|
||||
}
|
||||
|
||||
vertexData.m_normal = normalize(vertexData.m_normal);
|
||||
|
||||
return vertexData;
|
||||
}
|
||||
@@ -64,3 +64,8 @@ ShaderResourceGroupSemantic SRG_RayTracingScene
|
||||
{
|
||||
FrequencyId = 1;
|
||||
};
|
||||
|
||||
ShaderResourceGroupSemantic SRG_RayTracingMaterial
|
||||
{
|
||||
FrequencyId = 2;
|
||||
};
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+21
-3
@@ -44,8 +44,14 @@
|
||||
"field": "element",
|
||||
"typeName": "ShaderResourceGroupLayout",
|
||||
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
|
||||
"version": 6,
|
||||
"version": 7,
|
||||
"Objects": [
|
||||
{
|
||||
"field": "m_name",
|
||||
"typeName": "Name",
|
||||
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"field": "m_staticSamplers",
|
||||
"typeName": "AZStd::vector",
|
||||
@@ -3338,8 +3344,14 @@
|
||||
"field": "element",
|
||||
"typeName": "ShaderResourceGroupLayout",
|
||||
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
|
||||
"version": 6,
|
||||
"version": 7,
|
||||
"Objects": [
|
||||
{
|
||||
"field": "m_name",
|
||||
"typeName": "Name",
|
||||
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"field": "m_staticSamplers",
|
||||
"typeName": "AZStd::vector",
|
||||
@@ -6632,8 +6644,14 @@
|
||||
"field": "element",
|
||||
"typeName": "ShaderResourceGroupLayout",
|
||||
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
|
||||
"version": 6,
|
||||
"version": 7,
|
||||
"Objects": [
|
||||
{
|
||||
"field": "m_name",
|
||||
"typeName": "Name",
|
||||
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"field": "m_staticSamplers",
|
||||
"typeName": "AZStd::vector",
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -710,27 +710,53 @@ namespace AZ
|
||||
uint32_t rayTracingLod = aznumeric_cast<uint32_t>(modelLods.size() - 1);
|
||||
const Data::Instance<RPI::ModelLod>& modelLod = modelLods[rayTracingLod];
|
||||
|
||||
// setup a stream layout and shader input contract for the position and normal streams
|
||||
// setup a stream layout and shader input contract for the vertex streams
|
||||
static const char* PositionSemantic = "POSITION";
|
||||
static const char* NormalSemantic = "NORMAL";
|
||||
static const RHI::Format StreamFormat = RHI::Format::R32G32B32_FLOAT;
|
||||
static const char* TangentSemantic = "TANGENT";
|
||||
static const char* BitangentSemantic = "BITANGENT";
|
||||
static const char* UVSemantic = "UV";
|
||||
static const RHI::Format PositionStreamFormat = RHI::Format::R32G32B32_FLOAT;
|
||||
static const RHI::Format NormalStreamFormat = RHI::Format::R32G32B32_FLOAT;
|
||||
static const RHI::Format TangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
|
||||
static const RHI::Format BitangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
|
||||
static const RHI::Format UVStreamFormat = RHI::Format::R32G32_FLOAT;
|
||||
|
||||
RHI::InputStreamLayoutBuilder layoutBuilder;
|
||||
layoutBuilder.AddBuffer()->Channel(PositionSemantic, StreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(NormalSemantic, StreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(PositionSemantic, PositionStreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(NormalSemantic, NormalStreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(UVSemantic, UVStreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(TangentSemantic, TangentStreamFormat);
|
||||
layoutBuilder.AddBuffer()->Channel(BitangentSemantic, BitangentStreamFormat);
|
||||
RHI::InputStreamLayout inputStreamLayout = layoutBuilder.End();
|
||||
|
||||
RPI::ShaderInputContract::StreamChannelInfo positionStreamChannelInfo;
|
||||
positionStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(PositionSemantic));
|
||||
positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
|
||||
positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(PositionStreamFormat);
|
||||
|
||||
RPI::ShaderInputContract::StreamChannelInfo normalStreamChannelInfo;
|
||||
normalStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(NormalSemantic));
|
||||
normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
|
||||
normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(NormalStreamFormat);
|
||||
|
||||
RPI::ShaderInputContract::StreamChannelInfo tangentStreamChannelInfo;
|
||||
tangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(TangentSemantic));
|
||||
tangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(TangentStreamFormat);
|
||||
|
||||
RPI::ShaderInputContract::StreamChannelInfo bitangentStreamChannelInfo;
|
||||
bitangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(BitangentSemantic));
|
||||
bitangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(BitangentStreamFormat);
|
||||
|
||||
RPI::ShaderInputContract::StreamChannelInfo uvStreamChannelInfo;
|
||||
uvStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(UVSemantic));
|
||||
uvStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(UVStreamFormat);
|
||||
uvStreamChannelInfo.m_isOptional = true;
|
||||
|
||||
RPI::ShaderInputContract shaderInputContract;
|
||||
shaderInputContract.m_streamChannels.emplace_back(positionStreamChannelInfo);
|
||||
shaderInputContract.m_streamChannels.emplace_back(normalStreamChannelInfo);
|
||||
shaderInputContract.m_streamChannels.emplace_back(tangentStreamChannelInfo);
|
||||
shaderInputContract.m_streamChannels.emplace_back(bitangentStreamChannelInfo);
|
||||
shaderInputContract.m_streamChannels.emplace_back(uvStreamChannelInfo);
|
||||
|
||||
// setup the raytracing data for each sub-mesh
|
||||
const size_t meshCount = modelLod->GetMeshes().size();
|
||||
@@ -739,26 +765,6 @@ namespace AZ
|
||||
{
|
||||
const RPI::ModelLod::Mesh& mesh = modelLod->GetMeshes()[meshIndex];
|
||||
|
||||
// retrieve vertex/index buffers
|
||||
RPI::ModelLod::StreamBufferViewList streamBufferViews;
|
||||
[[maybe_unused]] bool result = modelLod->GetStreamsForMesh(inputStreamLayout, streamBufferViews, shaderInputContract, meshIndex);
|
||||
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
|
||||
// a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer.
|
||||
uint32_t vertexBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor vertexBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, vertexBufferByteCount);
|
||||
|
||||
const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView;
|
||||
uint32_t indexElementSize = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? 2 : 4;
|
||||
uint32_t indexElementCount = (uint32_t)indexBufferView.GetBuffer()->GetDescriptor().m_byteCount / indexElementSize;
|
||||
RHI::BufferViewDescriptor indexBufferDescriptor;
|
||||
indexBufferDescriptor.m_elementOffset = 0;
|
||||
indexBufferDescriptor.m_elementCount = indexElementCount;
|
||||
indexBufferDescriptor.m_elementSize = indexElementSize;
|
||||
indexBufferDescriptor.m_elementFormat = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? RHI::Format::R16_UINT : RHI::Format::R32_UINT;
|
||||
|
||||
// retrieve the material
|
||||
Data::Instance<RPI::Material> material = mesh.m_material;
|
||||
|
||||
@@ -769,31 +775,162 @@ namespace AZ
|
||||
material = materialAssignment.m_materialInstance;
|
||||
}
|
||||
|
||||
AZ::Color irradianceColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
// retrieve vertex/index buffers
|
||||
RPI::ModelLod::StreamBufferViewList streamBufferViews;
|
||||
[[maybe_unused]] bool result = modelLod->GetStreamsForMesh(
|
||||
inputStreamLayout,
|
||||
streamBufferViews,
|
||||
shaderInputContract,
|
||||
meshIndex,
|
||||
materialAssignment.m_matModUvOverrides,
|
||||
material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap());
|
||||
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
|
||||
// a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer.
|
||||
uint32_t positionBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor positionBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, positionBufferByteCount);
|
||||
|
||||
uint32_t normalBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor normalBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, normalBufferByteCount);
|
||||
|
||||
uint32_t tangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor tangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tangentBufferByteCount);
|
||||
|
||||
uint32_t bitangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor bitangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, bitangentBufferByteCount);
|
||||
|
||||
uint32_t uvBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[4].GetBuffer())->GetDescriptor().m_byteCount;
|
||||
RHI::BufferViewDescriptor uvBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, uvBufferByteCount);
|
||||
|
||||
const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView;
|
||||
uint32_t indexElementSize = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? 2 : 4;
|
||||
uint32_t indexElementCount = (uint32_t)indexBufferView.GetBuffer()->GetDescriptor().m_byteCount / indexElementSize;
|
||||
RHI::BufferViewDescriptor indexBufferDescriptor;
|
||||
indexBufferDescriptor.m_elementOffset = 0;
|
||||
indexBufferDescriptor.m_elementCount = indexElementCount;
|
||||
indexBufferDescriptor.m_elementSize = indexElementSize;
|
||||
indexBufferDescriptor.m_elementFormat = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? RHI::Format::R16_UINT : RHI::Format::R32_UINT;
|
||||
|
||||
// set the SubMesh data to pass to the RayTracingFeatureProcessor, starting with vertex/index data
|
||||
RayTracingFeatureProcessor::SubMesh subMesh;
|
||||
subMesh.m_positionFormat = PositionStreamFormat;
|
||||
subMesh.m_positionVertexBufferView = streamBufferViews[0];
|
||||
subMesh.m_positionShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
|
||||
|
||||
subMesh.m_normalFormat = NormalStreamFormat;
|
||||
subMesh.m_normalVertexBufferView = streamBufferViews[1];
|
||||
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
|
||||
|
||||
subMesh.m_tangentFormat = TangentStreamFormat;
|
||||
subMesh.m_tangentVertexBufferView = streamBufferViews[2];
|
||||
subMesh.m_tangentShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
|
||||
|
||||
subMesh.m_bitangentFormat = BitangentStreamFormat;
|
||||
subMesh.m_bitangentVertexBufferView = streamBufferViews[3];
|
||||
subMesh.m_bitangentShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor);
|
||||
|
||||
if (uvBufferByteCount > 0)
|
||||
{
|
||||
subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::UV;
|
||||
subMesh.m_uvFormat = UVStreamFormat;
|
||||
subMesh.m_uvVertexBufferView = streamBufferViews[4];
|
||||
subMesh.m_uvShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
|
||||
}
|
||||
|
||||
subMesh.m_indexBufferView = mesh.m_indexBufferView;
|
||||
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
|
||||
|
||||
// add material data
|
||||
if (material)
|
||||
{
|
||||
// irradiance color
|
||||
RPI::MaterialPropertyIndex propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.color"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
irradianceColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
|
||||
subMesh.m_irradianceColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
|
||||
}
|
||||
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.factor"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
|
||||
subMesh.m_irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
|
||||
}
|
||||
|
||||
// base color
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.color"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
subMesh.m_baseColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
|
||||
}
|
||||
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.factor"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
subMesh.m_baseColor *= material->GetPropertyValue<float>(propertyIndex);
|
||||
}
|
||||
|
||||
// metallic
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.factor"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
subMesh.m_metallicFactor = material->GetPropertyValue<float>(propertyIndex);
|
||||
}
|
||||
|
||||
// roughness
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.factor"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
subMesh.m_roughnessFactor = material->GetPropertyValue<float>(propertyIndex);
|
||||
}
|
||||
|
||||
// textures
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.textureMap"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
|
||||
if (image.get())
|
||||
{
|
||||
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::BaseColor;
|
||||
subMesh.m_baseColorImageView = image->GetImageView();
|
||||
}
|
||||
}
|
||||
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("normal.textureMap"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
|
||||
if (image.get())
|
||||
{
|
||||
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Normal;
|
||||
subMesh.m_normalImageView = image->GetImageView();
|
||||
}
|
||||
}
|
||||
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.textureMap"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
|
||||
if (image.get())
|
||||
{
|
||||
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Metallic;
|
||||
subMesh.m_metallicImageView = image->GetImageView();
|
||||
}
|
||||
}
|
||||
|
||||
propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.textureMap"));
|
||||
if (propertyIndex.IsValid())
|
||||
{
|
||||
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
|
||||
if (image.get())
|
||||
{
|
||||
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Roughness;
|
||||
subMesh.m_roughnessImageView = image->GetImageView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RayTracingFeatureProcessor::SubMesh subMesh;
|
||||
subMesh.m_vertexFormat = StreamFormat;
|
||||
subMesh.m_positionVertexBufferView = streamBufferViews[0];
|
||||
subMesh.m_positionShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(vertexBufferDescriptor);
|
||||
subMesh.m_normalVertexBufferView = streamBufferViews[1];
|
||||
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(vertexBufferDescriptor);
|
||||
subMesh.m_indexBufferView = mesh.m_indexBufferView;
|
||||
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
|
||||
subMesh.m_irradianceColor = irradianceColor;
|
||||
subMeshes.push_back(subMesh);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -115,11 +115,11 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
// update and compile the RayTracingSceneSrg
|
||||
// update and compile the RayTracingSceneSrg and RayTracingMaterialSrg
|
||||
// Note: the timing of this update is very important, it needs to be updated after the TLAS is allocated so it can
|
||||
// be set on the RayTracingSceneSrg for this frame, and the ray tracing mesh data in the RayTracingSceneSrg must
|
||||
// exactly match the TLAS. Any mismatch in this data may result in a TDR.
|
||||
rayTracingFeatureProcessor->UpdateRayTracingSceneSrg();
|
||||
rayTracingFeatureProcessor->UpdateRayTracingSrgs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,13 @@ namespace AZ
|
||||
AZ_Assert(rayTracingSceneSrgAsset.IsReady(), "Failed to load RayTracingSceneSrg asset");
|
||||
|
||||
m_rayTracingSceneSrg = RPI::ShaderResourceGroup::Create(rayTracingSceneSrgAsset);
|
||||
|
||||
// load the RayTracingMaterialSrg asset
|
||||
Data::Asset<RPI::ShaderResourceGroupAsset> rayTracingMaterialSrgAsset =
|
||||
RPI::AssetUtils::LoadAssetByProductPath<RPI::ShaderResourceGroupAsset>("shaderlib/atom/features/raytracing/raytracingmaterialsrg_raytracingmaterialsrg.azsrg", RPI::AssetUtils::TraceLevel::Error);
|
||||
AZ_Assert(rayTracingMaterialSrgAsset.IsReady(), "Failed to load RayTracingMaterialSrg asset");
|
||||
|
||||
m_rayTracingMaterialSrg = RPI::ShaderResourceGroup::Create(rayTracingMaterialSrgAsset);
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::SetMesh(const ObjectId objectId, const SubMeshVector& subMeshes)
|
||||
@@ -104,7 +111,7 @@ namespace AZ
|
||||
RHI::RayTracingBlasDescriptor blasDescriptor;
|
||||
blasDescriptor.Build()
|
||||
->Geometry()
|
||||
->VertexFormat(subMesh.m_vertexFormat)
|
||||
->VertexFormat(subMesh.m_positionFormat)
|
||||
->VertexBuffer(subMesh.m_positionVertexBufferView)
|
||||
->IndexBuffer(subMesh.m_indexBufferView)
|
||||
;
|
||||
@@ -124,6 +131,7 @@ namespace AZ
|
||||
m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size());
|
||||
|
||||
m_meshInfoBufferNeedsUpdate = true;
|
||||
m_materialInfoBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::RemoveMesh(const ObjectId objectId)
|
||||
@@ -142,6 +150,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
m_meshInfoBufferNeedsUpdate = true;
|
||||
m_materialInfoBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, const AZ::Vector3 nonUniformScale)
|
||||
@@ -162,14 +171,14 @@ namespace AZ
|
||||
m_meshInfoBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
|
||||
void RayTracingFeatureProcessor::UpdateRayTracingSrgs()
|
||||
{
|
||||
if (!m_tlas->GetTlasBuffer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_rayTracingSceneSrg->IsQueuedForCompile())
|
||||
if (m_rayTracingSceneSrg->IsQueuedForCompile() || m_rayTracingMaterialSrg->IsQueuedForCompile())
|
||||
{
|
||||
//[GFX TODO][ATOM-14792] AtomSampleViewer: Reset scene and feature processors before switching to sample
|
||||
return;
|
||||
@@ -178,7 +187,144 @@ namespace AZ
|
||||
// update the mesh info buffer with the latest ray tracing enabled meshes
|
||||
UpdateMeshInfoBuffer();
|
||||
|
||||
// update the material info buffer with the latest ray tracing enabled meshes
|
||||
UpdateMaterialInfoBuffer();
|
||||
|
||||
// update the RayTracingSceneSrg
|
||||
UpdateRayTracingSceneSrg();
|
||||
|
||||
// update the RayTracingMaterialSrg
|
||||
UpdateRayTracingMaterialSrg();
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
|
||||
{
|
||||
if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
|
||||
{
|
||||
TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor<TransformServiceFeatureProcessor>();
|
||||
|
||||
AZStd::vector<MeshInfo> meshInfos;
|
||||
meshInfos.reserve(m_subMeshCount);
|
||||
|
||||
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
|
||||
|
||||
if (m_meshInfoBuffer == nullptr)
|
||||
{
|
||||
// allocate the MeshInfo structured buffer
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = "RayTracingMeshInfo";
|
||||
desc.m_byteCount = newMeshByteCount;
|
||||
desc.m_elementSize = sizeof(MeshInfo);
|
||||
m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
}
|
||||
else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
|
||||
{
|
||||
// resize for the new sub-mesh count
|
||||
m_meshInfoBuffer->Resize(newMeshByteCount);
|
||||
}
|
||||
|
||||
// keep track of the start index of the buffers for each mesh, this is put into the MeshInfo
|
||||
// entry for each mesh so it knows where to find the start of its buffers in the unbounded array
|
||||
uint32_t bufferStartIndex = 0;
|
||||
|
||||
for (const auto& mesh : m_meshes)
|
||||
{
|
||||
AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
|
||||
AZ::Transform noScaleTransform = meshTransform;
|
||||
noScaleTransform.ExtractScale();
|
||||
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
|
||||
rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
|
||||
|
||||
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
|
||||
for (const auto& subMesh : subMeshes)
|
||||
{
|
||||
MeshInfo meshInfo;
|
||||
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::UV))
|
||||
{
|
||||
meshInfo.m_uvOffset = subMesh.m_uvVertexBufferView.GetByteOffset();
|
||||
}
|
||||
|
||||
subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
|
||||
rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
|
||||
meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
|
||||
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;
|
||||
bufferStartIndex += (RayTracingSubMeshFixedStreamCount + RHI::CountBitsSet(aznumeric_cast<uint32_t>(meshInfo.m_bufferFlags)));
|
||||
|
||||
meshInfos.emplace_back(meshInfo);
|
||||
}
|
||||
}
|
||||
|
||||
m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
|
||||
m_meshInfoBufferNeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::UpdateMaterialInfoBuffer()
|
||||
{
|
||||
if (m_materialInfoBufferNeedsUpdate && (m_subMeshCount > 0))
|
||||
{
|
||||
AZStd::vector<MaterialInfo> materialInfos;
|
||||
materialInfos.reserve(m_subMeshCount);
|
||||
|
||||
uint32_t newMaterialByteCount = m_subMeshCount * sizeof(MaterialInfo);
|
||||
|
||||
if (m_materialInfoBuffer == nullptr)
|
||||
{
|
||||
// allocate the MaterialInfo structured buffer
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = "RayTracingMaterialInfo";
|
||||
desc.m_byteCount = newMaterialByteCount;
|
||||
desc.m_elementSize = sizeof(MaterialInfo);
|
||||
m_materialInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
}
|
||||
else if (m_materialInfoBuffer->GetBufferSize() < newMaterialByteCount)
|
||||
{
|
||||
// resize for the new sub-mesh count
|
||||
m_materialInfoBuffer->Resize(newMaterialByteCount);
|
||||
}
|
||||
|
||||
// keep track of the start index of the textures for each mesh, this is put into the MaterialInfo
|
||||
// entry for each mesh so it knows where to find the start of its textures in the unbounded array
|
||||
uint32_t textureStartIndex = 0;
|
||||
|
||||
for (const auto& mesh : m_meshes)
|
||||
{
|
||||
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
|
||||
for (const auto& subMesh : subMeshes)
|
||||
{
|
||||
MaterialInfo materialInfo;
|
||||
subMesh.m_baseColor.StoreToFloat4(materialInfo.m_baseColor.data());
|
||||
materialInfo.m_metallicFactor = subMesh.m_metallicFactor;
|
||||
materialInfo.m_roughnessFactor = subMesh.m_roughnessFactor;
|
||||
materialInfo.m_textureFlags = subMesh.m_textureFlags;
|
||||
materialInfo.m_textureStartIndex = textureStartIndex;
|
||||
|
||||
// add the count of textures present in this subMesh to the start index for the next subMesh
|
||||
textureStartIndex += RHI::CountBitsSet(aznumeric_cast<uint32_t>(materialInfo.m_textureFlags));
|
||||
|
||||
materialInfos.emplace_back(materialInfo);
|
||||
}
|
||||
}
|
||||
|
||||
m_materialInfoBuffer->UpdateData(materialInfos.data(), newMaterialByteCount);
|
||||
m_materialInfoBufferNeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
|
||||
{
|
||||
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingSceneSrg->GetLayout();
|
||||
RHI::ShaderInputImageIndex imageIndex;
|
||||
RHI::ShaderInputBufferIndex bufferIndex;
|
||||
@@ -272,11 +418,18 @@ namespace AZ
|
||||
const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
|
||||
for (const auto& subMesh : subMeshes)
|
||||
{
|
||||
// add the index, position, and normal buffers for this sub-mesh to the mesh buffer list, this will
|
||||
// go into the shader as an unbounded array in the Srg
|
||||
// add the stream buffers for this sub-mesh to the mesh buffer list,
|
||||
// this is sent to the shader as an unbounded array in the Srg
|
||||
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::UV))
|
||||
{
|
||||
meshBuffers.push_back(subMesh.m_uvShaderBufferView.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,58 +440,53 @@ namespace AZ
|
||||
m_rayTracingSceneSrg->Compile();
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
|
||||
void RayTracingFeatureProcessor::UpdateRayTracingMaterialSrg()
|
||||
{
|
||||
if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
|
||||
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingMaterialSrg->GetLayout();
|
||||
RHI::ShaderInputImageIndex imageIndex;
|
||||
RHI::ShaderInputBufferIndex bufferIndex;
|
||||
RHI::ShaderInputConstantIndex constantIndex;
|
||||
|
||||
bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialInfo"));
|
||||
m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialInfoBuffer->GetBufferView());
|
||||
|
||||
if (m_subMeshCount)
|
||||
{
|
||||
TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor<TransformServiceFeatureProcessor>();
|
||||
|
||||
AZStd::vector<MeshInfo> meshInfos;
|
||||
meshInfos.reserve(m_subMeshCount);
|
||||
|
||||
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
|
||||
|
||||
if (m_meshInfoBuffer == nullptr)
|
||||
{
|
||||
// allocate the MeshInfo structured buffer
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = "RayTracingMeshInfo";
|
||||
desc.m_byteCount = newMeshByteCount;
|
||||
desc.m_elementSize = sizeof(MeshInfo);
|
||||
m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
}
|
||||
else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
|
||||
{
|
||||
// resize for the new sub-mesh count
|
||||
m_meshInfoBuffer->Resize(newMeshByteCount);
|
||||
}
|
||||
|
||||
AZStd::vector<const RHI::ImageView*> materialTextures;
|
||||
for (const auto& mesh : m_meshes)
|
||||
{
|
||||
AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
|
||||
AZ::Transform noScaleTransform = meshTransform;
|
||||
noScaleTransform.ExtractScale();
|
||||
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
|
||||
rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
|
||||
|
||||
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
|
||||
const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
|
||||
for (const auto& subMesh : subMeshes)
|
||||
{
|
||||
MeshInfo meshInfo;
|
||||
meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset();
|
||||
meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
|
||||
meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
|
||||
subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
|
||||
rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
|
||||
// add the baseColor, normal, metallic, and roughness images for this sub-mesh to the material texture list,
|
||||
// this is sent to the shader as an unbounded array in the Srg
|
||||
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::BaseColor))
|
||||
{
|
||||
materialTextures.push_back(subMesh.m_baseColorImageView.get());
|
||||
}
|
||||
|
||||
meshInfos.emplace_back(meshInfo);
|
||||
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Normal))
|
||||
{
|
||||
materialTextures.push_back(subMesh.m_normalImageView.get());
|
||||
}
|
||||
|
||||
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Metallic))
|
||||
{
|
||||
materialTextures.push_back(subMesh.m_metallicImageView.get());
|
||||
}
|
||||
|
||||
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Roughness))
|
||||
{
|
||||
materialTextures.push_back(subMesh.m_roughnessImageView.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
|
||||
m_meshInfoBufferNeedsUpdate = false;
|
||||
RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
|
||||
m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, materialTextures);
|
||||
}
|
||||
|
||||
m_rayTracingMaterialSrg->Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <Atom/RHI/RayTracingAccelerationStructure.h>
|
||||
#include <Atom/RHI/RayTracingBufferPools.h>
|
||||
#include <Atom/RHI/BufferView.h>
|
||||
#include <Atom/RHI/ImageView.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
|
||||
@@ -23,6 +24,28 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
static const uint32_t RayTracingGlobalSrgBindingSlot = 0;
|
||||
static const uint32_t RayTracingSceneSrgBindingSlot = 1;
|
||||
static const uint32_t RayTracingMaterialSrgBindingSlot = 2;
|
||||
|
||||
enum class RayTracingSubMeshBufferFlags : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
|
||||
UV = AZ_BIT(0)
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);
|
||||
|
||||
enum class RayTracingSubMeshTextureFlags : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
BaseColor = AZ_BIT(0),
|
||||
Normal = AZ_BIT(1),
|
||||
Metallic = AZ_BIT(2),
|
||||
Roughness = AZ_BIT(3)
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshTextureFlags);
|
||||
|
||||
//! This feature processor manages ray tracing data for a Scene
|
||||
class RayTracingFeatureProcessor
|
||||
: public RPI::FeatureProcessor
|
||||
@@ -42,20 +65,53 @@ namespace AZ
|
||||
//! Contains data for a single sub-mesh
|
||||
struct SubMesh
|
||||
{
|
||||
// vertex/index buffer data
|
||||
RHI::Format m_vertexFormat = RHI::Format::Unknown;
|
||||
// vertex streams
|
||||
RHI::Format m_positionFormat = RHI::Format::Unknown;
|
||||
RHI::StreamBufferView m_positionVertexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_positionShaderBufferView;
|
||||
|
||||
RHI::Format m_normalFormat = RHI::Format::Unknown;
|
||||
RHI::StreamBufferView m_normalVertexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_normalShaderBufferView;
|
||||
|
||||
RHI::Format m_tangentFormat = RHI::Format::Unknown;
|
||||
RHI::StreamBufferView m_tangentVertexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_tangentShaderBufferView;
|
||||
|
||||
RHI::Format m_bitangentFormat = RHI::Format::Unknown;
|
||||
RHI::StreamBufferView m_bitangentVertexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_bitangentShaderBufferView;
|
||||
|
||||
RHI::Format m_uvFormat = RHI::Format::Unknown;
|
||||
RHI::StreamBufferView m_uvVertexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_uvShaderBufferView;
|
||||
|
||||
// index buffer
|
||||
RHI::IndexBufferView m_indexBufferView;
|
||||
RHI::Ptr<RHI::BufferView> m_indexShaderBufferView;
|
||||
|
||||
// vertex buffer usage flags
|
||||
RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
|
||||
|
||||
// color of the bounced light from this sub-mesh
|
||||
AZ::Color m_irradianceColor;
|
||||
AZ::Color m_irradianceColor = AZ::Color(1.0f);
|
||||
|
||||
// ray tracing Blas
|
||||
RHI::Ptr<RHI::RayTracingBlas> m_blas;
|
||||
|
||||
// material data
|
||||
AZ::Color m_baseColor = AZ::Color(0.0f);
|
||||
float m_metallicFactor = 0.0f;
|
||||
float m_roughnessFactor = 0.0f;
|
||||
|
||||
// material texture usage flags
|
||||
RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
|
||||
|
||||
// material textures
|
||||
RHI::Ptr<const RHI::ImageView> m_baseColorImageView;
|
||||
RHI::Ptr<const RHI::ImageView> m_normalImageView;
|
||||
RHI::Ptr<const RHI::ImageView> m_metallicImageView;
|
||||
RHI::Ptr<const RHI::ImageView> m_roughnessImageView;
|
||||
};
|
||||
using SubMeshVector = AZStd::vector<SubMesh>;
|
||||
|
||||
@@ -98,6 +154,9 @@ namespace AZ
|
||||
//! Retrieves the RayTracingSceneSrg
|
||||
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingSceneSrg() const { return m_rayTracingSceneSrg; }
|
||||
|
||||
//! Retrieves the RayTracingMaterialSrg
|
||||
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingMaterialSrg() const { return m_rayTracingMaterialSrg; }
|
||||
|
||||
//! Retrieves the RayTracingTlas
|
||||
const RHI::Ptr<RHI::RayTracingTlas>& GetTlas() const { return m_tlas; }
|
||||
RHI::Ptr<RHI::RayTracingTlas>& GetTlas() { return m_tlas; }
|
||||
@@ -118,14 +177,20 @@ namespace AZ
|
||||
//! Retrieves the GPU buffer containing information for all ray tracing meshes.
|
||||
const Data::Instance<RPI::Buffer> GetMeshInfoBuffer() const { return m_meshInfoBuffer; }
|
||||
|
||||
//! Updates the RayTracingSceneSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
|
||||
void UpdateRayTracingSceneSrg();
|
||||
//! Retrieves the GPU buffer containing information for all ray tracing materials.
|
||||
const Data::Instance<RPI::Buffer> GetMaterialInfoBuffer() const { return m_materialInfoBuffer; }
|
||||
|
||||
//! Updates the RayTracingSceneSrg and RayTracingMaterialSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
|
||||
void UpdateRayTracingSrgs();
|
||||
|
||||
private:
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(RayTracingFeatureProcessor);
|
||||
|
||||
void UpdateMeshInfoBuffer();
|
||||
void UpdateMaterialInfoBuffer();
|
||||
void UpdateRayTracingSceneSrg();
|
||||
void UpdateRayTracingMaterialSrg();
|
||||
|
||||
// flag indicating if RayTracing is enabled, currently based on device support
|
||||
bool m_rayTracingEnabled = false;
|
||||
@@ -143,6 +208,9 @@ namespace AZ
|
||||
// ray tracing scene Srg
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_rayTracingSceneSrg;
|
||||
|
||||
// ray tracing material Srg
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_rayTracingMaterialSrg;
|
||||
|
||||
// current revision number of ray tracing data
|
||||
uint32_t m_revision = 0;
|
||||
|
||||
@@ -158,18 +226,43 @@ namespace AZ
|
||||
// structure for data in the m_meshInfoBuffer, shaders that use the buffer must match this type
|
||||
struct MeshInfo
|
||||
{
|
||||
uint32_t m_indexOffset;
|
||||
uint32_t m_positionOffset;
|
||||
uint32_t m_normalOffset;
|
||||
uint32_t m_indexOffset;
|
||||
uint32_t m_positionOffset;
|
||||
uint32_t m_normalOffset;
|
||||
uint32_t m_tangentOffset;
|
||||
uint32_t m_bitangentOffset;
|
||||
uint32_t m_uvOffset;
|
||||
float m_padding0[2];
|
||||
|
||||
AZStd::array<float, 4> m_irradianceColor; // float4
|
||||
AZStd::array<float, 9> m_worldInvTranspose; // float3x3
|
||||
float m_padding1[1];
|
||||
|
||||
RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
|
||||
uint32_t m_bufferStartIndex = 0;
|
||||
};
|
||||
|
||||
// buffer containing a MeshInfo for each sub-mesh
|
||||
Data::Instance<RPI::Buffer> m_meshInfoBuffer;
|
||||
|
||||
// flag indicating we need to update the mesh info GPU buffer
|
||||
// structure for data in the m_materialInfoBuffer, shaders that use the buffer must match this type
|
||||
struct MaterialInfo
|
||||
{
|
||||
AZStd::array<float, 4> m_baseColor; // float4
|
||||
float m_metallicFactor = 0.0f;
|
||||
float m_roughnessFactor = 0.0f;
|
||||
RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
|
||||
uint32_t m_textureStartIndex = 0;
|
||||
};
|
||||
|
||||
// buffer containing a MaterialInfo for each sub-mesh
|
||||
Data::Instance<RPI::Buffer> m_materialInfoBuffer;
|
||||
|
||||
// flag indicating we need to update the meshInfo buffer
|
||||
bool m_meshInfoBufferNeedsUpdate = false;
|
||||
|
||||
// flag indicating we need to update the materialInfo buffer
|
||||
bool m_materialInfoBufferNeedsUpdate = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,6 @@ namespace AZ
|
||||
AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state");
|
||||
|
||||
// create global srg
|
||||
static const uint32_t RayTracingGlobalSrgBindingSlot = 0;
|
||||
Data::Asset<RPI::ShaderResourceGroupAsset> globalSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingGlobalSrgBindingSlot);
|
||||
AZ_Error("PassSystem", globalSrgAsset.GetId().IsValid(), "RayTracingPass [%s] Failed to find RayTracingGlobalSrg asset", GetPathName().GetCStr());
|
||||
AZ_Error("PassSystem", globalSrgAsset.IsReady(), "RayTracingPass [%s] asset is not loaded for shader", GetPathName().GetCStr());
|
||||
@@ -120,10 +119,13 @@ namespace AZ
|
||||
AZ_Assert(m_shaderResourceGroup, "RayTracingPass [%s]: Failed to create RayTracingGlobalSrg", GetPathName().GetCStr());
|
||||
RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get());
|
||||
|
||||
// check to see if the shader requires a ViewSrg
|
||||
// check to see if the shader requires the View and RayTracingMaterial Srgs
|
||||
Data::Asset<RPI::ShaderResourceGroupAsset> viewSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RPI::SrgBindingSlot::View);
|
||||
m_requiresViewSrg = viewSrgAsset.GetId().IsValid();
|
||||
|
||||
Data::Asset<RPI::ShaderResourceGroupAsset> rayTracingMaterialSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingMaterialSrgBindingSlot);
|
||||
m_requiresRayTracingMaterialSrg = rayTracingMaterialSrgAsset.GetId().IsValid();
|
||||
|
||||
// build the ray tracing pipeline state descriptor
|
||||
RHI::RayTracingPipelineStateDescriptor descriptor;
|
||||
descriptor.Build()
|
||||
@@ -298,6 +300,11 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
if (m_requiresRayTracingMaterialSrg)
|
||||
{
|
||||
shaderResourceGroups.push_back(rayTracingFeatureProcessor->GetRayTracingMaterialSrg()->GetRHIShaderResourceGroup());
|
||||
}
|
||||
|
||||
dispatchRaysItem.m_shaderResourceGroupCount = aznumeric_cast<uint32_t>(shaderResourceGroups.size());
|
||||
dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups.data();
|
||||
dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get();
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace AZ
|
||||
RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
|
||||
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
|
||||
bool m_requiresViewSrg = false;
|
||||
bool m_requiresRayTracingMaterialSrg = false;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
Reference in New Issue
Block a user