123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "RayTracingVertexFormatExampleComponent.h"
- #include <Atom/Bootstrap/BootstrapNotificationBus.h>
- #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
- #include <Atom/RPI.Public/Scene.h>
- #include <Automation/ScriptableImGui.h>
- #include <AzCore/Math/PackedVector3.h>
- #include <AzCore/Math/PackedVector4.h>
- #include <AzCore/Name/NameDictionary.h>
- namespace AtomSampleViewer::ImGuiHelper
- {
- template<typename T, AZStd::enable_if_t<AZStd::is_enum_v<T> && sizeof(T) == sizeof(int), bool> = true>
- bool RadioButton(const char* label, T* value, T buttonValue)
- {
- return ScriptableImGui::RadioButton(label, reinterpret_cast<int*>(value), AZStd::to_underlying(buttonValue));
- }
- } // namespace AtomSampleViewer::ImGuiHelper
- namespace
- {
- enum class FloatType
- {
- Float32,
- Float16,
- Float8,
- Unorm8,
- };
- enum class OctahedronType
- {
- Oct32,
- Oct16,
- Oct8,
- };
- constexpr int GetFloatTypeSize(FloatType floatType)
- {
- switch (floatType)
- {
- case FloatType::Float32:
- return 4;
- case FloatType::Float16:
- return 2;
- case FloatType::Float8:
- case FloatType::Unorm8:
- return 1;
- default:
- AZ_Assert(false, "Failed to get size of FloatType %d", floatType);
- return 1;
- }
- }
- constexpr int GetOctahedronTypeSize(OctahedronType octahedronType)
- {
- switch (octahedronType)
- {
- case OctahedronType::Oct32:
- return 4;
- case OctahedronType::Oct16:
- return 2;
- case OctahedronType::Oct8:
- return 1;
- default:
- AZ_Assert(false, "Failed to get size of OctahedronType %d", octahedronType);
- return 0;
- }
- }
- constexpr int GetOctahedronComponentBitCount(OctahedronType octahedronType)
- {
- switch (octahedronType)
- {
- case OctahedronType::Oct32:
- return 15;
- case OctahedronType::Oct16:
- return 7;
- case OctahedronType::Oct8:
- return 3;
- default:
- AZ_Assert(false, "Failed to get bit count of OctahedronType %d", octahedronType);
- return 0;
- }
- }
- template<FloatType floatType>
- void PackFloat(float sourceValue, void* targetAddress);
- template<>
- void PackFloat<FloatType::Float32>(float sourceValue, void* targetAddress)
- {
- std::memcpy(targetAddress, &sourceValue, 4);
- }
- template<>
- void PackFloat<FloatType::Float16>(float sourceValue, void* targetAddress)
- {
- uint32_t sourceValueInt{ *reinterpret_cast<uint32_t*>(&sourceValue) };
- // https://stackoverflow.com/a/5587983
- uint16_t targetValue = (sourceValueInt >> 31) << 5;
- uint16_t tmp = (sourceValueInt >> 23) & 0xff;
- tmp = (tmp - 0x70) & ((unsigned int)((int)(0x70 - tmp) >> 4) >> 27);
- targetValue = (targetValue | tmp) << 10;
- targetValue |= (sourceValueInt >> 13) & 0x3ff;
- std::memcpy(targetAddress, &targetValue, 2);
- }
- template<>
- void PackFloat<FloatType::Unorm8>(float sourceValue, void* targetAddress)
- {
- uint8_t targetValue{ aznumeric_cast<uint8_t>(AZStd::clamp(sourceValue, 0.f, 1.f) * 255.f) };
- std::memcpy(targetAddress, &targetValue, 1);
- }
- template<int ComponentCount, FloatType ComponentOutputFormat>
- void ConvertFloatBuffer(AZStd::span<const uint8_t> sourceBuffer, AZStd::span<uint8_t> targetBuffer, int sourceComponentCountOverride)
- {
- AZ_Assert(
- sourceComponentCountOverride == 0 || sourceComponentCountOverride < ComponentCount,
- "Component count override must be smaller than the format component count");
- size_t elementCount{ sourceBuffer.size() / (ComponentCount * sizeof(float)) };
- auto sourceIteratorBegin{ reinterpret_cast<const float*>(sourceBuffer.data()) };
- auto sourceIteratorEnd{ sourceIteratorBegin + elementCount * ComponentCount };
- uint8_t* targetBufferAddress{ targetBuffer.data() };
- int currentComponentIndex{ 0 };
- for (auto sourceIterator{ sourceIteratorBegin }; sourceIterator != sourceIteratorEnd; ++sourceIterator)
- {
- PackFloat<ComponentOutputFormat>(*sourceIterator, targetBufferAddress);
- targetBufferAddress += GetFloatTypeSize(ComponentOutputFormat);
- if (sourceComponentCountOverride != 0 && ++currentComponentIndex == sourceComponentCountOverride)
- {
- targetBufferAddress += GetFloatTypeSize(ComponentOutputFormat) * (ComponentCount - sourceComponentCountOverride);
- currentComponentIndex = 0;
- }
- }
- }
- AZ::Vector3 EncodeNormalSignedOctahedron(AZ::Vector3 normal)
- {
- // http://johnwhite3d.blogspot.com/2017/10/signed-octahedron-normal-encoding.html
- normal /= AZStd::abs(normal.GetX()) + AZStd::abs(normal.GetY()) + AZStd::abs(normal.GetZ());
- AZ::Vector3 encodedNormal;
- encodedNormal.SetY(normal.GetY() * 0.5f + 0.5f);
- encodedNormal.SetX(normal.GetX() * 0.5f + encodedNormal.GetY());
- encodedNormal.SetY(normal.GetX() * -0.5f + encodedNormal.GetY());
- encodedNormal.SetZ(AZStd::clamp(normal.GetZ() * AZStd::numeric_limits<float>::max(), 0.f, 1.f));
- return encodedNormal;
- }
- void EncodeTangentPackOctahedron(const AZ::PackedVector4f& sourceValue, OctahedronType octahedronType, void* targetAddress)
- {
- int xyBits{ GetOctahedronComponentBitCount(octahedronType) };
- AZ_Assert(xyBits * 2 + 2 <= 32, "Too many bits for octahedron encoding");
- AZ::Vector3 encodedNormal{ EncodeNormalSignedOctahedron(
- AZ::Vector3{ sourceValue.GetX(), sourceValue.GetY(), sourceValue.GetZ() }) };
- uint32_t mask{ (1u << xyBits) - 1 };
- uint32_t targetValue{ aznumeric_cast<uint32_t>(encodedNormal.GetX() * mask) |
- aznumeric_cast<uint32_t>(encodedNormal.GetY() * mask) << xyBits |
- aznumeric_cast<uint32_t>(encodedNormal.GetZ() > 0) << (xyBits * 2) |
- aznumeric_cast<uint32_t>(sourceValue.GetW() > 0) << (xyBits * 2 + 1) };
- std::memcpy(targetAddress, &targetValue, GetOctahedronTypeSize(octahedronType));
- }
- void EncodeNormalPackOctahedron(const AZ::PackedVector3f& sourceValue, OctahedronType octahedronType, void* targetAddress)
- {
- EncodeTangentPackOctahedron(
- AZ::PackedVector4f{ sourceValue.GetX(), sourceValue.GetY(), sourceValue.GetZ(), 0.f }, octahedronType, targetAddress);
- }
- template<OctahedronType ComponentOutputFormat>
- void ConvertNormalBuffer(AZStd::span<const uint8_t> sourceBuffer, AZStd::span<uint8_t> targetBuffer)
- {
- size_t elementCount{ sourceBuffer.size() / sizeof(AZ::PackedVector3f) };
- auto sourceIteratorBegin{ reinterpret_cast<const AZ::PackedVector3f*>(sourceBuffer.data()) };
- auto sourceIteratorEnd{ sourceIteratorBegin + elementCount };
- uint8_t* targetBufferAddress{ targetBuffer.data() };
- for (auto sourceIterator{ sourceIteratorBegin }; sourceIterator != sourceIteratorEnd; ++sourceIterator)
- {
- EncodeNormalPackOctahedron(*sourceIterator, ComponentOutputFormat, targetBufferAddress);
- targetBufferAddress += GetOctahedronTypeSize(ComponentOutputFormat);
- }
- }
- template<OctahedronType ComponentOutputFormat>
- void ConvertTangentBuffer(AZStd::span<const uint8_t> sourceBuffer, AZStd::span<uint8_t> targetBuffer)
- {
- size_t elementCount{ sourceBuffer.size() / sizeof(AZ::PackedVector4f) };
- auto sourceIteratorBegin{ reinterpret_cast<const AZ::PackedVector4f*>(sourceBuffer.data()) };
- auto sourceIteratorEnd{ sourceIteratorBegin + elementCount };
- uint8_t* targetBufferAddress{ targetBuffer.data() };
- for (auto sourceIterator{ sourceIteratorBegin }; sourceIterator != sourceIteratorEnd; ++sourceIterator)
- {
- EncodeTangentPackOctahedron(*sourceIterator, ComponentOutputFormat, targetBufferAddress);
- targetBufferAddress += GetOctahedronTypeSize(ComponentOutputFormat);
- }
- }
- void ConvertIndexBufferData(
- AZStd::span<const uint8_t> sourceBuffer, AZStd::span<uint8_t> targetBuffer, AZ::RHI::IndexFormat indexFormat)
- {
- size_t elementCount{ sourceBuffer.size() / sizeof(uint32_t) };
- auto sourceIteratorBegin{ reinterpret_cast<const uint32_t*>(sourceBuffer.data()) };
- auto sourceIteratorEnd{ sourceIteratorBegin + elementCount };
- uint8_t* targetBufferAddress{ targetBuffer.data() };
- for (auto sourceIterator{ sourceIteratorBegin }; sourceIterator != sourceIteratorEnd; ++sourceIterator)
- {
- uint32_t sourceValue{ *sourceIterator };
- std::memcpy(targetBufferAddress, &sourceValue, AZ::RHI::GetIndexFormatSize(indexFormat));
- targetBufferAddress += AZ::RHI::GetIndexFormatSize(indexFormat);
- }
- }
- } // namespace
- namespace AtomSampleViewer
- {
- using namespace AZ;
- void RayTracingVertexFormatExampleComponent::Reflect(ReflectContext* context)
- {
- if (auto* serializeContext{ azrtti_cast<SerializeContext*>(context) })
- {
- serializeContext->Class<RayTracingVertexFormatExampleComponent, Component>()->Version(0);
- }
- }
- void RayTracingVertexFormatExampleComponent::Activate()
- {
- m_modelBrowser.SetFilter(
- [](const Data::AssetInfo& assetInfo)
- {
- return assetInfo.m_assetType == azrtti_typeid<RPI::ModelAsset>();
- });
- m_modelBrowser.SetDefaultPinnedAssets(
- {
- "Objects/Shaderball_simple.fbx.azmodel",
- "Objects/bunny.fbx.azmodel",
- "Objects/suzanne.fbx.azmodel",
- "Objects/sponza.fbx.azmodel",
- },
- true);
- m_imguiSidebar.Activate();
- m_modelBrowser.Activate();
- auto& rayTracingDebugFeatureProcessor{ GetRayTracingDebugFeatureProcessor() };
- rayTracingDebugFeatureProcessor.OnRayTracingDebugComponentAdded();
- rayTracingDebugFeatureProcessor.GetSettingsInterface()->SetDebugViewMode(Render::RayTracingDebugViewMode::PrimitiveIndex);
- TickBus::Handler::BusConnect();
- EBUS_EVENT_ID(GetCameraEntityId(), Debug::CameraControllerRequestBus, Enable, azrtti_typeid<Debug::ArcBallControllerComponent>());
- EBUS_EVENT(Render::Bootstrap::NotificationBus, OnBootstrapSceneReady, m_scene);
- }
- void RayTracingVertexFormatExampleComponent::Deactivate()
- {
- m_modelBrowser.Deactivate();
- m_imguiSidebar.Deactivate();
- GetRayTracingDebugFeatureProcessor().OnRayTracingDebugComponentRemoved();
- // GetRayTracingFeatureProcessor().RemoveMesh(m_rayTracingUuid);
- EBUS_EVENT_ID(GetCameraEntityId(), Debug::CameraControllerRequestBus, Disable);
- TickBus::Handler::BusDisconnect();
- }
- void RayTracingVertexFormatExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
- {
- DrawSidebar();
- }
- void RayTracingVertexFormatExampleComponent::DrawSidebar()
- {
- if (m_imguiSidebar.Begin())
- {
- ImGuiAssetBrowser::WidgetSettings modelBrowserSettings;
- modelBrowserSettings.m_labels.m_root = "Models";
- bool modelChanged{ m_modelBrowser.Tick(modelBrowserSettings) };
- ImGui::Separator();
- ImGui::Spacing();
- ImGui::Text("RT Debug Type:");
- using DebugViewMode = Render::RayTracingDebugViewMode;
- bool debugViewModeUpdated{ false };
- debugViewModeUpdated |= ImGuiHelper::RadioButton("Instance Index", &m_debugViewMode, DebugViewMode::InstanceIndex);
- debugViewModeUpdated |= ImGuiHelper::RadioButton("Instance ID", &m_debugViewMode, DebugViewMode::InstanceID);
- debugViewModeUpdated |= ImGuiHelper::RadioButton("Primitive Index", &m_debugViewMode, DebugViewMode::PrimitiveIndex);
- debugViewModeUpdated |= ImGuiHelper::RadioButton("Barycentric Coordinates", &m_debugViewMode, DebugViewMode::Barycentrics);
- debugViewModeUpdated |= ImGuiHelper::RadioButton("Normals", &m_debugViewMode, DebugViewMode::Normals);
- debugViewModeUpdated |= ImGuiHelper::RadioButton("UV Coordinates", &m_debugViewMode, DebugViewMode::UVs);
- if (debugViewModeUpdated)
- {
- GetRayTracingDebugFeatureProcessor().GetSettingsInterface()->SetDebugViewMode(m_debugViewMode);
- }
- ImGui::Separator();
- ImGui::Spacing();
- ImGui::Text("Index Format:");
- bool indexFormatUpdated{ false };
- indexFormatUpdated |= ImGuiHelper::RadioButton("Uint32", &m_indexFormat, RHI::IndexFormat::Uint32);
- indexFormatUpdated |= ImGuiHelper::RadioButton("Uint16", &m_indexFormat, RHI::IndexFormat::Uint16);
- ImGui::Spacing();
- ImGui::PushID("Position");
- ImGui::Text("Position Format:");
- bool positionFormatUpdated{ false };
- positionFormatUpdated |= ImGuiHelper::RadioButton("R32G32B32_FLOAT", &m_positionFormat, RHI::VertexFormat::R32G32B32_FLOAT);
- positionFormatUpdated |=
- ImGuiHelper::RadioButton("R16G16B16A16_FLOAT", &m_positionFormat, RHI::VertexFormat::R16G16B16A16_FLOAT);
- ImGui::PopID();
- ImGui::Spacing();
- ImGui::PushID("Normal");
- ImGui::Text("Normal Format:");
- bool normalFormatUpdated{ false };
- normalFormatUpdated |= ImGuiHelper::RadioButton("R32G32B32_FLOAT", &m_normalFormat, RHI::VertexFormat::R32G32B32_FLOAT);
- normalFormatUpdated |= ImGuiHelper::RadioButton("R16G16B16_FLOAT", &m_normalFormat, RHI::VertexFormat::R16G16B16_FLOAT);
- normalFormatUpdated |= ImGuiHelper::RadioButton("N32_OCT", &m_normalFormat, RHI::VertexFormat::N32_OCT);
- normalFormatUpdated |= ImGuiHelper::RadioButton("N16_OCT", &m_normalFormat, RHI::VertexFormat::N16_OCT);
- normalFormatUpdated |= ImGuiHelper::RadioButton("N8_OCT", &m_normalFormat, RHI::VertexFormat::N8_OCT);
- ImGui::PopID();
- ImGui::Spacing();
- ImGui::PushID("UV");
- ImGui::Text("UV Format:");
- bool uvFormatUpdated{ false };
- uvFormatUpdated |= ImGuiHelper::RadioButton("R32G32_FLOAT", &m_uvFormat, RHI::VertexFormat::R32G32_FLOAT);
- uvFormatUpdated |= ImGuiHelper::RadioButton("R16G16_FLOAT", &m_uvFormat, RHI::VertexFormat::R16G16_FLOAT);
- uvFormatUpdated |= ImGuiHelper::RadioButton("R8G8_UNORM", &m_uvFormat, RHI::VertexFormat::R8G8_UNORM);
- ImGui::PopID();
- ImGui::Spacing();
- ImGui::PushID("Tangent");
- ImGui::Text("Tangent Format:");
- bool tangentFormatUpdated{ false };
- tangentFormatUpdated |= ImGuiHelper::RadioButton("R32G32B32A32_FLOAT", &m_tangentFormat, RHI::VertexFormat::R32G32B32A32_FLOAT);
- tangentFormatUpdated |= ImGuiHelper::RadioButton("R16G16B16A16_FLOAT", &m_tangentFormat, RHI::VertexFormat::R16G16B16A16_FLOAT);
- tangentFormatUpdated |= ImGuiHelper::RadioButton("T32_OCT", &m_tangentFormat, RHI::VertexFormat::T32_OCT);
- tangentFormatUpdated |= ImGuiHelper::RadioButton("T16_OCT", &m_tangentFormat, RHI::VertexFormat::T16_OCT);
- tangentFormatUpdated |= ImGuiHelper::RadioButton("T8_OCT", &m_tangentFormat, RHI::VertexFormat::T8_OCT);
- ImGui::PopID();
- ImGui::Spacing();
- ImGui::PushID("Bitangent");
- ImGui::Text("Bitangent Format:");
- bool bitangentFormatUpdated{ false };
- bitangentFormatUpdated |= ImGuiHelper::RadioButton("R32G32B32_FLOAT", &m_bitangentFormat, RHI::VertexFormat::R32G32B32_FLOAT);
- bitangentFormatUpdated |= ImGuiHelper::RadioButton("R16G16B16_FLOAT", &m_bitangentFormat, RHI::VertexFormat::R16G16B16_FLOAT);
- bitangentFormatUpdated |= ImGuiHelper::RadioButton("N32_OCT", &m_bitangentFormat, RHI::VertexFormat::N32_OCT);
- bitangentFormatUpdated |= ImGuiHelper::RadioButton("N16_OCT", &m_bitangentFormat, RHI::VertexFormat::N16_OCT);
- bitangentFormatUpdated |= ImGuiHelper::RadioButton("N8_OCT", &m_bitangentFormat, RHI::VertexFormat::N8_OCT);
- ImGui::PopID();
- if (modelChanged || indexFormatUpdated || positionFormatUpdated || uvFormatUpdated || normalFormatUpdated ||
- tangentFormatUpdated || bitangentFormatUpdated)
- {
- ModelChanged();
- }
- m_imguiSidebar.End();
- }
- }
- void RayTracingVertexFormatExampleComponent::ModelChanged()
- {
- if (!m_modelBrowser.GetSelectedAssetId().IsValid())
- {
- return;
- }
- m_currentModel.Create(m_modelBrowser.GetSelectedAssetId());
- m_currentModel.QueueLoad();
- m_currentModel.BlockUntilLoadComplete();
- Render::RayTracingFeatureProcessorInterface::Mesh rtMesh;
- rtMesh.m_assetId.m_guid = m_rayTracingUuid;
- rtMesh.m_instanceMask |= static_cast<uint32_t>(RHI::RayTracingAccelerationStructureInstanceInclusionMask::STATIC_MESH);
- AZStd::vector<Render::RayTracingFeatureProcessorInterface::SubMesh> rtSubMeshes;
- const auto& meshes{ m_currentModel->GetLodAssets()[0]->GetMeshes() };
- for (auto& mesh : meshes)
- {
- auto& rtSubMesh{ rtSubMeshes.emplace_back() };
- {
- const auto& indexView{ mesh.GetIndexBufferAssetView() };
- auto indexBuffer{ ConvertIndexBuffer(
- indexView.GetBufferAsset()->GetBuffer(), indexView.GetBufferViewDescriptor(), m_indexFormat) };
- uint32_t indexElementSize{ RHI::GetIndexFormatSize(m_indexFormat) };
- rtSubMesh.m_indexBufferView =
- RHI::IndexBufferView{ *indexBuffer->GetRHIBuffer(), 0, mesh.GetIndexCount() * indexElementSize, m_indexFormat };
- rtSubMesh.m_indexShaderBufferView = indexBuffer->GetRHIBuffer()->GetBufferView(indexBuffer->GetBufferViewDescriptor());
- }
- {
- const auto* positionView{ mesh.GetSemanticBufferAssetView(AZ_NAME_LITERAL("POSITION")) };
- uint32_t positionElementSize{ RHI::GetVertexFormatSize(m_positionFormat) };
- int sourceComponentOverride{ m_positionFormat == RHI::VertexFormat::R16G16B16A16_FLOAT ? 3 : 0 };
- auto positionBuffer{ ConvertVertexBuffer(
- positionView->GetBufferAsset()->GetBuffer(), positionView->GetBufferViewDescriptor(), m_positionFormat,
- sourceComponentOverride) };
- rtSubMesh.m_positionVertexBufferView =
- RHI::StreamBufferView{ *positionBuffer->GetRHIBuffer(), 0, mesh.GetVertexCount() * positionElementSize,
- positionElementSize };
- rtSubMesh.m_positionShaderBufferView =
- positionBuffer->GetRHIBuffer()->GetBufferView(positionBuffer->GetBufferViewDescriptor());
- rtSubMesh.m_positionFormat = m_positionFormat;
- }
- {
- const auto* normalView{ mesh.GetSemanticBufferAssetView(AZ_NAME_LITERAL("NORMAL")) };
- uint32_t normalElementSize{ RHI::GetVertexFormatSize(m_normalFormat) };
- auto normalBuffer{ ConvertVertexBuffer(
- normalView->GetBufferAsset()->GetBuffer(), normalView->GetBufferViewDescriptor(), m_normalFormat) };
- rtSubMesh.m_normalVertexBufferView =
- RHI::StreamBufferView{ *normalBuffer->GetRHIBuffer(), 0, mesh.GetVertexCount() * normalElementSize, normalElementSize };
- rtSubMesh.m_normalShaderBufferView = normalBuffer->GetRHIBuffer()->GetBufferView(normalBuffer->GetBufferViewDescriptor());
- rtSubMesh.m_normalFormat = m_normalFormat;
- }
- if (auto* uvView{ mesh.GetSemanticBufferAssetView(AZ_NAME_LITERAL("UV")) })
- {
- uint32_t uvElementSize{ RHI::GetVertexFormatSize(m_uvFormat) };
- auto uvBuffer{ ConvertVertexBuffer(uvView->GetBufferAsset()->GetBuffer(), uvView->GetBufferViewDescriptor(), m_uvFormat) };
- rtSubMesh.m_uvVertexBufferView =
- RHI::StreamBufferView{ *uvBuffer->GetRHIBuffer(), 0, mesh.GetVertexCount() * uvElementSize, uvElementSize };
- rtSubMesh.m_uvShaderBufferView = uvBuffer->GetRHIBuffer()->GetBufferView(uvBuffer->GetBufferViewDescriptor());
- rtSubMesh.m_uvFormat = m_uvFormat;
- rtSubMesh.m_bufferFlags |= Render::RayTracingSubMeshBufferFlags::UV;
- }
- if (auto* tangentView{ mesh.GetSemanticBufferAssetView(AZ_NAME_LITERAL("TANGENT")) })
- {
- uint32_t tangentElementSize{ RHI::GetVertexFormatSize(m_tangentFormat) };
- auto tangentBuffer{ ConvertVertexBuffer(
- tangentView->GetBufferAsset()->GetBuffer(), tangentView->GetBufferViewDescriptor(), m_tangentFormat) };
- rtSubMesh.m_tangentVertexBufferView =
- RHI::StreamBufferView{ *tangentBuffer->GetRHIBuffer(), 0, mesh.GetVertexCount() * tangentElementSize,
- tangentElementSize };
- rtSubMesh.m_tangentShaderBufferView =
- tangentBuffer->GetRHIBuffer()->GetBufferView(tangentBuffer->GetBufferViewDescriptor());
- rtSubMesh.m_tangentFormat = m_tangentFormat;
- rtSubMesh.m_bufferFlags |= Render::RayTracingSubMeshBufferFlags::Tangent;
- }
- if (auto* bitangentView{ mesh.GetSemanticBufferAssetView(AZ_NAME_LITERAL("BITANGENT")) })
- {
- uint32_t bitangentElementSize{ RHI::GetVertexFormatSize(m_bitangentFormat) };
- auto bitangentBuffer{ ConvertVertexBuffer(
- bitangentView->GetBufferAsset()->GetBuffer(), bitangentView->GetBufferViewDescriptor(), m_bitangentFormat) };
- rtSubMesh.m_bitangentVertexBufferView =
- RHI::StreamBufferView{ *bitangentBuffer->GetRHIBuffer(), 0, mesh.GetVertexCount() * bitangentElementSize,
- bitangentElementSize };
- rtSubMesh.m_bitangentShaderBufferView =
- bitangentBuffer->GetRHIBuffer()->GetBufferView(bitangentBuffer->GetBufferViewDescriptor());
- rtSubMesh.m_bitangentFormat = m_bitangentFormat;
- rtSubMesh.m_bufferFlags |= Render::RayTracingSubMeshBufferFlags::Bitangent;
- }
- }
- GetRayTracingFeatureProcessor().RemoveMesh(m_rayTracingUuid);
- GetRayTracingFeatureProcessor().AddMesh(m_rayTracingUuid, rtMesh, rtSubMeshes);
- }
- RPI::Ptr<RPI::Buffer> RayTracingVertexFormatExampleComponent::ConvertVertexBuffer(
- AZStd::span<const uint8_t> sourceBufferData,
- const RHI::BufferViewDescriptor& sourceBufferDescriptor,
- RHI::VertexFormat targetFormat,
- int sourceComponentCountOverride)
- {
- auto sourceBufferView{ sourceBufferData.subspan(
- sourceBufferDescriptor.m_elementOffset * sourceBufferDescriptor.m_elementSize,
- sourceBufferDescriptor.m_elementCount * sourceBufferDescriptor.m_elementSize) };
- uint32_t targetFormatSize{ RHI::GetVertexFormatSize(targetFormat) };
- // Use SizeAlignUp to ensure 4-byte-aligned reads in the shader are always valid when the buffer size is not a multiple of 4
- uint32_t targetBufferSize{ SizeAlignUp(sourceBufferDescriptor.m_elementCount * targetFormatSize, 4) };
- AZStd::vector<uint8_t> targetBufferData(targetBufferSize);
- switch (targetFormat)
- {
- case RHI::VertexFormat::R32G32B32A32_FLOAT:
- ConvertFloatBuffer<4, FloatType::Float32>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R16G16B16A16_FLOAT:
- ConvertFloatBuffer<4, FloatType::Float16>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R32G32B32_FLOAT:
- ConvertFloatBuffer<3, FloatType::Float32>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R16G16B16_FLOAT:
- ConvertFloatBuffer<3, FloatType::Float16>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R32G32_FLOAT:
- ConvertFloatBuffer<2, FloatType::Float32>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R16G16_FLOAT:
- ConvertFloatBuffer<2, FloatType::Float16>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::R8G8_UNORM:
- ConvertFloatBuffer<2, FloatType::Unorm8>(sourceBufferView, targetBufferData, sourceComponentCountOverride);
- break;
- case RHI::VertexFormat::N32_OCT:
- ConvertNormalBuffer<OctahedronType::Oct32>(sourceBufferView, targetBufferData);
- break;
- case RHI::VertexFormat::N16_OCT:
- ConvertNormalBuffer<OctahedronType::Oct16>(sourceBufferView, targetBufferData);
- break;
- case RHI::VertexFormat::N8_OCT:
- ConvertNormalBuffer<OctahedronType::Oct8>(sourceBufferView, targetBufferData);
- break;
- case RHI::VertexFormat::T32_OCT:
- ConvertTangentBuffer<OctahedronType::Oct32>(sourceBufferView, targetBufferData);
- break;
- case RHI::VertexFormat::T16_OCT:
- ConvertTangentBuffer<OctahedronType::Oct16>(sourceBufferView, targetBufferData);
- break;
- case RHI::VertexFormat::T8_OCT:
- ConvertTangentBuffer<OctahedronType::Oct8>(sourceBufferView, targetBufferData);
- break;
- default:
- AZ_Assert(false, "Target format %d not supported", targetFormat);
- }
- RPI::CommonBufferDescriptor desc;
- desc.m_poolType = RPI::CommonBufferPoolType::StaticInputAssembly;
- desc.m_bufferName = "VertexBuffer";
- desc.m_byteCount = targetBufferSize;
- desc.m_elementSize = targetFormatSize;
- desc.m_bufferData = targetBufferData.data();
- return RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
- }
- RPI::Ptr<RPI::Buffer> RayTracingVertexFormatExampleComponent::ConvertIndexBuffer(
- AZStd::span<const uint8_t> sourceBufferData, const RHI::BufferViewDescriptor& sourceBufferDescriptor, RHI::IndexFormat targetFormat)
- {
- auto sourceBufferView{ sourceBufferData.subspan(
- sourceBufferDescriptor.m_elementOffset * sourceBufferDescriptor.m_elementSize,
- sourceBufferDescriptor.m_elementCount * sourceBufferDescriptor.m_elementSize) };
- uint32_t targetFormatSize{ RHI::GetIndexFormatSize(targetFormat) };
- // Use SizeAlignUp to ensure 4-byte-aligned reads in the shader are always valid when the buffer size is not a multiple of 4
- uint32_t targetBufferSize{ SizeAlignUp(sourceBufferDescriptor.m_elementCount * targetFormatSize, 4) };
- AZStd::vector<uint8_t> targetBufferData(targetBufferSize);
- ConvertIndexBufferData(sourceBufferView, targetBufferData, targetFormat);
- RPI::CommonBufferDescriptor desc;
- desc.m_poolType = RPI::CommonBufferPoolType::StaticInputAssembly;
- desc.m_bufferName = "IndexBuffer";
- desc.m_byteCount = targetBufferSize;
- desc.m_elementSize = targetFormatSize;
- desc.m_bufferData = targetBufferData.data();
- return RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
- }
- Render::RayTracingFeatureProcessorInterface& RayTracingVertexFormatExampleComponent::GetRayTracingFeatureProcessor()
- {
- if (!m_rayTracingFeatureProcessor)
- {
- auto* scene{ RPI::Scene::GetSceneForEntityContextId(GetEntityContextId()) };
- auto featureProcessor{ scene->GetFeatureProcessor<Render::RayTracingFeatureProcessorInterface>() };
- AZ_Assert(featureProcessor != nullptr, "RayTracingFeatureProcessor not found");
- m_rayTracingFeatureProcessor = featureProcessor;
- }
- return *m_rayTracingFeatureProcessor;
- }
- Render::RayTracingDebugFeatureProcessorInterface& RayTracingVertexFormatExampleComponent::GetRayTracingDebugFeatureProcessor()
- {
- if (!m_rayTracingDebugFeatureProcessor)
- {
- auto* scene{ RPI::Scene::GetSceneForEntityContextId(GetEntityContextId()) };
- auto featureProcessor{ scene->GetFeatureProcessor<Render::RayTracingDebugFeatureProcessorInterface>() };
- AZ_Assert(featureProcessor != nullptr, "RayTracingDebugFeatureProcessor not found");
- m_rayTracingDebugFeatureProcessor = featureProcessor;
- }
- return *m_rayTracingDebugFeatureProcessor;
- }
- } // namespace AtomSampleViewer
|