123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /*
- * 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 <BloomExampleComponent.h>
- #include <AzCore/Component/Entity.h>
- #include <AzCore/IO/Path/Path.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <AzFramework/Entity/EntityContextBus.h>
- #include <SampleComponentManager.h>
- #include <SampleComponentConfig.h>
- #include <EntityUtilityFunctions.h>
- #include <Atom/Feature/Utils/FrameCaptureBus.h>
- #include <Atom/RHI/DrawPacketBuilder.h>
- #include <Atom/RPI.Public/RPISystemInterface.h>
- #include <Atom/RPI.Public/Shader/Shader.h>
- #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
- #include <RHI/BasicRHIComponent.h>
- namespace AtomSampleViewer
- {
- using namespace AZ;
- void BloomExampleComponent::Reflect(AZ::ReflectContext* context)
- {
- if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<BloomExampleComponent, AZ::Component>()
- ->Version(0)
- ;
- }
- }
- BloomExampleComponent::BloomExampleComponent()
- : m_imageBrowser("@user@/BloomExampleComponent/image_browser.xml")
- {
- }
- void BloomExampleComponent::Activate()
- {
- m_dynamicDraw = RPI::GetDynamicDraw();
- m_postProcessFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessorInterface>();
- CreateBloomEntity();
- m_imguiSidebar.Activate();
- AZ::TickBus::Handler::BusConnect();
- PrepareRenderData();
- m_imageBrowser.SetFilter([this](const AZ::Data::AssetInfo& assetInfo)
- {
- if (!AzFramework::StringFunc::Path::IsExtension(assetInfo.m_relativePath.c_str(), "streamingimage"))
- {
- return false;
- }
- AZStd::string assetPath(assetInfo.m_relativePath);
- if (!AzFramework::StringFunc::Path::Normalize(assetPath))
- {
- return false;
- }
- if (!Utils::IsFileUnderFolder(assetPath, InputImageFolder))
- {
- return false;
- }
- return true;
- });
- m_imageBrowser.Activate();
- // Load a default image
- QueueAssetPathForLoad("textures/tonemapping/hdr_test_pattern.exr.streamingimage");
- Data::Asset<RPI::AnyAsset> displayMapperAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::AnyAsset>("passes/DisplayMapperConfiguration.azasset", RPI::AssetUtils::TraceLevel::Error);
- const Render::DisplayMapperConfigurationDescriptor* displayMapperConfigurationDescriptor = RPI::GetDataFromAnyAsset<Render::DisplayMapperConfigurationDescriptor>(displayMapperAsset);
- if (displayMapperConfigurationDescriptor == nullptr)
- {
- AZ_Error("DisplayMapperPass", false, "Failed to load display mapper configuration file.");
- return;
- }
- m_displayMapperConfiguration = *displayMapperConfigurationDescriptor;
- }
- void BloomExampleComponent::Deactivate()
- {
- AZ::TickBus::Handler::BusDisconnect();
- AZ::EntityBus::MultiHandler::BusDisconnect();
- if (m_bloomEntity)
- {
- DestroyEntity(m_bloomEntity, GetEntityContextId());
- m_postProcessFeatureProcessor = nullptr;
- }
- m_imguiSidebar.Deactivate();
- m_imageBrowser.Deactivate();
- }
- void BloomExampleComponent::OnEntityDestruction(const AZ::EntityId& entityId)
- {
- AZ::EntityBus::MultiHandler::BusDisconnect(entityId);
- if (m_bloomEntity && m_bloomEntity->GetId() == entityId)
- {
- m_postProcessFeatureProcessor->RemoveSettingsInterface(m_bloomEntity->GetId());
- m_bloomEntity = nullptr;
- }
- else
- {
- AZ_Assert(false, "unexpected entity destruction is signaled.");
- }
- }
- void BloomExampleComponent::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint)
- {
- if (m_drawImage.m_image && !m_drawImage.m_wasStreamed)
- {
- m_drawImage.m_wasStreamed = m_drawImage.m_image->GetResidentMipLevel() == 0;
- m_drawImage.m_srg->Compile();
- }
- DrawSidebar();
- DrawImage(&m_drawImage);
- }
- void BloomExampleComponent::DrawSidebar()
- {
- using namespace AZ::Render;
- const char* items[] = { "White", "Red", "Green", "Blue" };
- static int item_current0 = 0;
- static int item_current1 = 0;
- static int item_current2 = 0;
- static int item_current3 = 0;
- static int item_current4 = 0;
- auto ColorPicker = [](int index)->Vector3 {
- switch (index)
- {
- case 0: return Vector3(1.0, 1.0, 1.0); break;
- case 1: return Vector3(1.0, 0.5, 0.5); break;
- case 2: return Vector3(0.5, 1.0, 0.5); break;
- case 3: return Vector3(0.5, 0.5, 1.0); break;
- default: return Vector3(1.0, 1.0, 1.0);
- }
- };
- if (!m_imguiSidebar.Begin())
- {
- return;
- }
- ImGui::Spacing();
- bool enabled = m_bloomSettings->GetEnabled();
- if (ImGui::Checkbox("Enable", &enabled) || m_isInitParameters)
- {
- m_bloomSettings->SetEnabled(enabled);
- m_bloomSettings->OnConfigChanged();
- }
- ImGui::Spacing();
- float threshold = m_bloomSettings->GetThreshold();
- if (ImGui::SliderFloat("Threshold", &threshold, 0.0f, 20.0f, "%0.1f") || !m_isInitParameters)
- {
- m_bloomSettings->SetThreshold(threshold);
- m_bloomSettings->OnConfigChanged();
- }
- float knee = m_bloomSettings->GetKnee();
- if (ImGui::SliderFloat("Knee", &knee, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKnee(knee);
- m_bloomSettings->OnConfigChanged();
- }
- ImGui::Spacing();
- float sizeScale = m_bloomSettings->GetKernelSizeScale();
- if (ImGui::SliderFloat("KernelSizeScale", &sizeScale, 0.0f, 2.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeScale(sizeScale);
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::CollapsingHeader("KernelSize", ImGuiTreeNodeFlags_DefaultOpen))
- {
- ImGui::Indent();
- float kernelSize0 = m_bloomSettings->GetKernelSizeStage0();
- if (ImGui::SliderFloat("Size0", &kernelSize0, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeStage0(kernelSize0);
- m_bloomSettings->OnConfigChanged();
- }
- float kernelSize1 = m_bloomSettings->GetKernelSizeStage1();
- if (ImGui::SliderFloat("Size1", &kernelSize1, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeStage1(kernelSize1);
- m_bloomSettings->OnConfigChanged();
- }
- float kernelSize2 = m_bloomSettings->GetKernelSizeStage2();
- if (ImGui::SliderFloat("Size2", &kernelSize2, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeStage2(kernelSize2);
- m_bloomSettings->OnConfigChanged();
- }
- float kernelSize3 = m_bloomSettings->GetKernelSizeStage3();
- if (ImGui::SliderFloat("Size3", &kernelSize3, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeStage3(kernelSize3);
- m_bloomSettings->OnConfigChanged();
- }
- float kernelSize4 = m_bloomSettings->GetKernelSizeStage4();
- if (ImGui::SliderFloat("Size4", &kernelSize4, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetKernelSizeStage4(kernelSize4);
- m_bloomSettings->OnConfigChanged();
- }
- ImGui::Unindent();
- }
- ImGui::Spacing();
- float intensity = m_bloomSettings->GetIntensity();
- if (ImGui::SliderFloat("Intensity", &intensity, 0.0f, 1.0f) || m_isInitParameters)
- {
- m_bloomSettings->SetIntensity(intensity);
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::CollapsingHeader("Tint", ImGuiTreeNodeFlags_DefaultOpen))
- {
- ImGui::Indent();
- if (ImGui::ListBox("Tint0", &item_current0, items, IM_ARRAYSIZE(items), 4) || m_isInitParameters)
- {
- m_bloomSettings->SetTintStage0(ColorPicker(item_current0));
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::ListBox("Tint1", &item_current1, items, IM_ARRAYSIZE(items), 4) || m_isInitParameters)
- {
- m_bloomSettings->SetTintStage1(ColorPicker(item_current1));
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::ListBox("Tint2", &item_current2, items, IM_ARRAYSIZE(items), 4) || m_isInitParameters)
- {
- m_bloomSettings->SetTintStage2(ColorPicker(item_current2));
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::ListBox("Tint3", &item_current3, items, IM_ARRAYSIZE(items), 4) || m_isInitParameters)
- {
- m_bloomSettings->SetTintStage3(ColorPicker(item_current3));
- m_bloomSettings->OnConfigChanged();
- }
- if (ImGui::ListBox("Tint4", &item_current4, items, IM_ARRAYSIZE(items), 4) || m_isInitParameters)
- {
- m_bloomSettings->SetTintStage4(ColorPicker(item_current4));
- m_bloomSettings->OnConfigChanged();
- }
- ImGui::Unindent();
- }
- ImGui::Spacing();
- bool bicubicEnabled = m_bloomSettings->GetBicubicEnabled();
- if (ImGui::Checkbox("Bicubic upsampling", &bicubicEnabled) || m_isInitParameters)
- {
- m_bloomSettings->SetBicubicEnabled(bicubicEnabled);
- m_bloomSettings->OnConfigChanged();
- }
- m_imguiSidebar.End();
- }
- void BloomExampleComponent::PrepareRenderData()
- {
- const auto CreatePipeline = [](const char* shaderFilepath,
- const char* srgName,
- Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset,
- RHI::Ptr<AZ::RHI::ShaderResourceGroupLayout>& srgLayout,
- RHI::ConstPtr<RHI::PipelineState>& pipelineState,
- RHI::DrawListTag& drawListTag,
- RPI::Scene* scene)
- {
- // Since the shader is using SV_VertexID and SV_InstanceID as VS input, we won't need to have vertex buffer.
- // Also, the index buffer is not needed with DrawLinear.
- RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor;
- shaderAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::ShaderAsset>(shaderFilepath, RPI::AssetUtils::TraceLevel::Error);
- Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset);
- if (!shader)
- {
- AZ_Error("Render", false, "Failed to find or create shader instance from shader asset with path %s", shaderFilepath);
- return;
- }
- const RPI::ShaderVariant& shaderVariant = shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
- shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
- drawListTag = shader->GetDrawListTag();
- scene->ConfigurePipelineState(shader->GetDrawListTag(), pipelineStateDescriptor);
- pipelineStateDescriptor.m_inputStreamLayout.SetTopology(AZ::RHI::PrimitiveTopology::TriangleStrip);
- pipelineStateDescriptor.m_inputStreamLayout.Finalize();
- pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
- if (!pipelineState)
- {
- AZ_Error("Render", false, "Failed to acquire default pipeline state for shader %s", shaderFilepath);
- }
- // Load shader resource group layout
- srgLayout = shaderAsset->FindShaderResourceGroupLayout(AZ::Name(srgName));
- };
- // Create the example's main pipeline object
- {
- CreatePipeline("Shaders/tonemappingexample/renderimage.azshader", "RenderImageSrg", m_shaderAsset, m_srgLayout, m_pipelineState, m_drawListTag, m_scene);
- // Set the input indices
- m_imageInputIndex.Reset();
- m_positionInputIndex.Reset();
- m_sizeInputIndex.Reset();
- m_colorSpaceIndex.Reset();
- }
- m_drawImage.m_srg = RPI::ShaderResourceGroup::Create(m_shaderAsset, m_srgLayout->GetName());
- m_drawImage.m_wasStreamed = false;
- // Set the image to occupy the full screen.
- // The window's left bottom is (-1, -1). The window size is (2, 2)
- AZStd::array<float, 2> position, size;
- position[0] = -1.f;
- position[1] = -1.f;
- size[0] = 2.0f;
- size[1] = 2.0f;
- m_drawImage.m_srg->SetConstant(m_positionInputIndex, position);
- m_drawImage.m_srg->SetConstant(m_sizeInputIndex, size);
- m_drawImage.m_srg->SetConstant<int>(m_colorSpaceIndex, static_cast<int>(m_inputColorSpace));
- }
- void BloomExampleComponent::DrawImage(const ImageToDraw* imageInfo)
- {
- // Build draw packet
- RHI::DrawPacketBuilder drawPacketBuilder{RHI::MultiDevice::DefaultDevice};
- drawPacketBuilder.Begin(nullptr);
- m_geometryView.SetDrawArguments(RHI::DrawLinear(4, 0));
- drawPacketBuilder.SetGeometryView(&m_geometryView);
- RHI::DrawPacketBuilder::DrawRequest drawRequest;
- drawRequest.m_listTag = m_drawListTag;
- drawRequest.m_pipelineState = m_pipelineState.get();
- drawRequest.m_sortKey = 0;
- drawRequest.m_uniqueShaderResourceGroup = imageInfo->m_srg->GetRHIShaderResourceGroup();
- drawPacketBuilder.AddDrawItem(drawRequest);
- // Submit draw packet
- auto drawPacket{drawPacketBuilder.End()};
- m_dynamicDraw->AddDrawPacket(m_scene, AZStd::move(drawPacket));
- }
- RPI::ColorSpaceId BloomExampleComponent::GetColorSpaceIdForIndex(uint8_t colorSpaceIndex) const
- {
- const AZStd::vector<AZ::RPI::ColorSpaceId> colorSpaces =
- {
- RPI::ColorSpaceId::SRGB,
- RPI::ColorSpaceId::LinearSRGB,
- RPI::ColorSpaceId::ACEScg,
- RPI::ColorSpaceId::ACES2065
- };
- if (colorSpaceIndex >= colorSpaces.size())
- {
- AZ_Assert(false, "Invalid colorSpaceIndex");
- return RPI::ColorSpaceId::SRGB;
- }
- return colorSpaces[colorSpaceIndex];
- }
- void BloomExampleComponent::CreateBloomEntity()
- {
- m_bloomEntity = CreateEntity("Bloom", GetEntityContextId());
- // Bloom
- auto* bloomSettings = m_postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_bloomEntity->GetId());
- m_bloomSettings = bloomSettings->GetOrCreateBloomSettingsInterface();
- m_bloomSettings->SetEnabled(false);
- m_bloomEntity->Activate();
- AZ::EntityBus::MultiHandler::BusConnect(m_bloomEntity->GetId());
- }
- void BloomExampleComponent::QueueAssetPathForLoad(const AZStd::string& filePath)
- {
- AZ::Data::AssetId imageAssetId;
- AZ::Data::AssetCatalogRequestBus::BroadcastResult(
- imageAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, filePath.c_str(),
- azrtti_typeid <AZ::RPI::StreamingImageAsset>(), false);
- AZ_Assert(imageAssetId.IsValid(), "Unable to load file %s", filePath.c_str());
- QueueAssetIdForLoad(imageAssetId);
- }
- void BloomExampleComponent::QueueAssetIdForLoad(const AZ::Data::AssetId& imageAssetId)
- {
- if (imageAssetId.IsValid())
- {
- Data::Asset<AZ::RPI::StreamingImageAsset> imageAsset;
- if (!imageAsset.Create(imageAssetId))
- {
- auto assetId = imageAssetId.ToString<AZStd::string>();
- AZ_Assert(false, "Unable to create image asset for asset ID %s", assetId.c_str());
- return;
- }
- auto image = AZ::RPI::StreamingImage::FindOrCreate(imageAsset);
- if (image == nullptr)
- {
- auto imageAssetName = imageAssetId.ToString<AZStd::string>();
- AZ_Assert(false, "Failed to find or create an image instance from image asset %s", imageAssetName.c_str());
- return;
- }
- m_drawImage.m_assetId = imageAssetId;
- m_drawImage.m_image = image;
- m_drawImage.m_wasStreamed = false;
- m_drawImage.m_srg->SetImage(m_imageInputIndex, m_drawImage.m_image);
- }
- }
- } // namespace AtomSampleViewer
|