123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- /*
- * 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 <ShadowExampleComponent.h>
- #include <Automation/ScriptableImGui.h>
- #include <Automation/ScriptRunnerBus.h>
- #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
- #include <Atom/RPI.Public/RPISystemInterface.h>
- #include <Atom/RPI.Public/Scene.h>
- #include <Atom/RPI.Public/Model/Model.h>
- #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
- #include <Atom/RPI.Reflect/Model/ModelAsset.h>
- #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
- #include <AzCore/Component/Entity.h>
- #include <AzFramework/Components/CameraBus.h>
- #include <SampleComponentManager.h>
- #include <SampleComponentConfig.h>
- #include <RHI/BasicRHIComponent.h>
- #include <Atom/RPI.Public/ColorManagement/TransformColor.h>
- namespace AtomSampleViewer
- {
- const AZ::Color ShadowExampleComponent::DirectionalLightColor = AZ::Color::CreateOne();
- AZ::Color ShadowExampleComponent::s_positionalLightColors[] = {
- // they will be initialized in the constructor.
- AZ::Color::CreateZero(),
- AZ::Color::CreateZero(),
- AZ::Color::CreateZero()
- };
- const AZ::Render::ShadowmapSize ShadowExampleComponent::s_shadowmapImageSizes[] =
- {
- AZ::Render::ShadowmapSize::Size256,
- AZ::Render::ShadowmapSize::Size512,
- AZ::Render::ShadowmapSize::Size1024,
- AZ::Render::ShadowmapSize::Size2048
- };
- const char* ShadowExampleComponent::s_shadowmapImageSizeLabels[] =
- {
- "256",
- "512",
- "1024",
- "2048"
- };
- const AZ::Render::ShadowFilterMethod ShadowExampleComponent::s_shadowFilterMethods[] =
- {
- AZ::Render::ShadowFilterMethod::None,
- AZ::Render::ShadowFilterMethod::Pcf,
- AZ::Render::ShadowFilterMethod::Esm,
- AZ::Render::ShadowFilterMethod::EsmPcf
- };
- const char* ShadowExampleComponent::s_shadowFilterMethodLabels[] =
- {
- "None",
- "PCF",
- "ESM",
- "ESM+PCF"
- };
- ShadowExampleComponent::ShadowExampleComponent()
- : m_imguiSidebar("@user@/ShadowExampleComponent/sidebar.xml")
- {
- s_positionalLightColors[0] = AZ::Colors::Red;
- s_positionalLightColors[1] = AZ::Colors::Green;
- s_positionalLightColors[2] = AZ::Colors::Blue;
- }
- void ShadowExampleComponent::Reflect(AZ::ReflectContext* context)
- {
- if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<ShadowExampleComponent, AZ::Component>()
- ->Version(0)
- ;
- }
- }
- void ShadowExampleComponent::Activate()
- {
- using namespace AZ;
- m_sampleName = "ShadowExampleComponent";
- // Don't continue the script until assets are ready and scene is setup
- ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScriptWithTimeout, 120.0f);
- // preload assets
- AZStd::vector<AssetCollectionAsyncLoader::AssetToLoadInfo> assetList = {
- {DefaultPbrMaterialPath, azrtti_typeid<RPI::MaterialAsset>()},
- {BunnyModelFilePath, azrtti_typeid<RPI::ModelAsset>()},
- {CubeModelFilePath, azrtti_typeid<RPI::ModelAsset>()}
- };
- PreloadAssets(assetList);
- // initialize and then reset IBL, which will disable it by binding the default cubemaps
- m_defaultIbl.Init(m_scene);
- m_defaultIbl.Reset();
- }
- void ShadowExampleComponent::OnAllAssetsReadyActivate()
- {
- using namespace AZ;
- // Load the assets
- m_bunnyModelAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ModelAsset>(BunnyModelFilePath, RPI::AssetUtils::TraceLevel::Assert);
- m_floorModelAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ModelAsset>(CubeModelFilePath, RPI::AssetUtils::TraceLevel::Assert);
- m_materialAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::MaterialAsset>(DefaultPbrMaterialPath, RPI::AssetUtils::TraceLevel::Assert);
- m_bunnyMeshIsReady = false;
- m_floorMeshIsReady = false;
- m_directionalLightImageSizeIndex = 2; // image size is 1024.
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- m_positionalLightImageSizeIndices[index] = 2; // image size is 1024.
- }
- m_cascadeCount = 2;
- m_ratioLogarithmUniform = 0.5f;
- UseArcBallCameraController();
- m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
- m_diskLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
- m_pointLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::PointLightFeatureProcessorInterface>();
- CreateMeshes();
- CreateDirectionalLight();
- CreateDiskLights();
- m_elapsedTime = 0.f;
- m_imguiSidebar.Activate();
- AZ::TickBus::Handler::BusConnect();
- }
- void ShadowExampleComponent::Deactivate()
- {
- AZ::TickBus::Handler::BusDisconnect();
- RestoreCameraConfiguration();
- RemoveController();
- GetMeshFeatureProcessor()->ReleaseMesh(m_floorMeshHandle);
- GetMeshFeatureProcessor()->ReleaseMesh(m_bunnyMeshHandle);
- DestroyDiskLights();
- DestroyPointLights();
- m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
- m_imguiSidebar.Deactivate();
- }
- void ShadowExampleComponent::OnTick(float deltaTime, AZ::ScriptTimePoint)
- {
- using namespace AZ;
- constexpr float directionalLightPeriodTime = 5.f; // 5 seconds for a rotation of directional light position.
- constexpr float lightPeriodTime = 7.f; // 7 seconds for a rotation of light positions.
- if (m_elapsedTime == 0.f)
- {
- SaveCameraConfiguration();
- SetInitialArcBallControllerParams();
- SetInitialShadowParams();
- }
- m_elapsedTime += deltaTime;
- if (m_isDirectionalLightAutoRotate)
- {
- m_directionalLightRotationAngle = fmodf(m_directionalLightRotationAngle + deltaTime * Constants::TwoPi / directionalLightPeriodTime, Constants::TwoPi);
- }
- if (m_isPositionalLightAutoRotate)
- {
- m_positionalLightRotationAngle = fmodf(m_positionalLightRotationAngle - deltaTime * Constants::TwoPi / lightPeriodTime + Constants::TwoPi, Constants::TwoPi);
- }
- UpdateDirectionalLight();
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- const auto transform = GetTransformForLight(index);
- if (m_diskLightHandles[index].IsValid())
- {
- m_diskLightFeatureProcessor->SetPosition(m_diskLightHandles[index], transform.GetTranslation());
- m_diskLightFeatureProcessor->SetDirection(m_diskLightHandles[index], transform.GetBasis(1));
- }
- if (m_pointLightHandles[index].IsValid())
- {
- m_pointLightFeatureProcessor->SetPosition(m_pointLightHandles[index], transform.GetTranslation());
- }
- }
- Camera::CameraRequestBus::Event(
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::SetFovRadians,
- m_cameraFovY);
- DrawSidebar();
- }
- AZ::Transform ShadowExampleComponent::GetTransformForLight(const uint32_t index) const
- {
- constexpr float diskLightDist = 5.f;
- using namespace AZ;
- const float angle = m_positionalLightRotationAngle + index * Constants::TwoPi / 3;
- const auto location = Vector3(diskLightDist * sinf(angle), diskLightDist * cosf(angle), m_positionalLightHeights[index]);
- const auto transform = Transform::CreateLookAt(location, Vector3::CreateZero());
- return transform;
- }
- float ShadowExampleComponent::GetAttenuationForLight(const uint32_t index) const
- {
- return sqrtf(m_lightIntensities[index] / CutoffIntensity);
- }
- AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> ShadowExampleComponent::GetRgbIntensityForLight(
- const uint32_t index) const
- {
- AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightRgbIntensity(
- s_positionalLightColors[index] * m_lightIntensities[index]);
-
- return lightRgbIntensity;
- }
- AZStd::pair<float, float> ShadowExampleComponent::GetConeAnglesForLight(const uint32_t index) const
- {
- const float innerConeAngle = AZ::DegToRad(m_outerConeAngles[index]) * ConeAngleInnerRatio;
- const float outerConeAngle = AZ::DegToRad(m_outerConeAngles[index]);
- return AZStd::make_pair(innerConeAngle, outerConeAngle);
- }
- void ShadowExampleComponent::UpdateDirectionalLight()
- {
- using namespace AZ;
- constexpr float directionalLightDist = 10.f;
- // Directional Light Transform
- {
- const auto lightLocation = Vector3(
- directionalLightDist * sinf(m_directionalLightRotationAngle), directionalLightDist * cosf(m_directionalLightRotationAngle),
- m_directionalLightHeight);
- const auto lightTransform = Transform::CreateLookAt(lightLocation, Vector3::CreateZero());
- m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightTransform.GetBasis(1));
- }
- // Camera Configuration
- {
- Camera::Configuration config;
- Camera::CameraRequestBus::EventResult(config, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration);
- m_directionalLightFeatureProcessor->SetCameraConfiguration(m_directionalLightHandle, config);
- }
- // Camera Transform
- {
- Transform transform = Transform::CreateIdentity();
- TransformBus::EventResult(transform, GetCameraEntityId(), &TransformBus::Events::GetWorldTM);
- m_directionalLightFeatureProcessor->SetCameraTransform(m_directionalLightHandle, transform);
- }
- }
- void ShadowExampleComponent::SaveCameraConfiguration()
- {
- Camera::CameraRequestBus::EventResult(
- m_originalFarClipDistance,
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::GetFarClipDistance);
- Camera::CameraRequestBus::EventResult(
- m_originalCameraFovRadians,
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::GetFovRadians);
- }
- void ShadowExampleComponent::RestoreCameraConfiguration()
- {
- Camera::CameraRequestBus::Event(
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::SetFarClipDistance,
- m_originalFarClipDistance);
- Camera::CameraRequestBus::Event(
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::SetFovRadians,
- m_originalCameraFovRadians);
- }
- void ShadowExampleComponent::UseArcBallCameraController()
- {
- using namespace AZ;
- Debug::CameraControllerRequestBus::Event(
- GetCameraEntityId(),
- &Debug::CameraControllerRequestBus::Events::Enable,
- azrtti_typeid<Debug::ArcBallControllerComponent>());
- }
- void ShadowExampleComponent::SetInitialArcBallControllerParams()
- {
- using namespace AZ;
- const auto cameraLocation = Vector3(0.f, -2.f, 2.f);
- Debug::ArcBallControllerRequestBus::Event(
- GetCameraEntityId(),
- &Debug::ArcBallControllerRequestBus::Events::SetCenter,
- cameraLocation);
- Debug::ArcBallControllerRequestBus::Event(
- GetCameraEntityId(),
- &Debug::ArcBallControllerRequestBus::Events::SetPitch,
- -Constants::QuarterPi);
- Debug::ArcBallControllerRequestBus::Event(
- GetCameraEntityId(),
- &Debug::ArcBallControllerRequestBus::Events::SetDistance,
- 50.f);
- }
- void ShadowExampleComponent::SetInitialShadowParams()
- {
- Camera::CameraRequestBus::Event(
- GetCameraEntityId(),
- &Camera::CameraRequestBus::Events::SetFovRadians,
- AZ::Constants::QuarterPi);
- }
- void ShadowExampleComponent::RemoveController()
- {
- AZ::Debug::CameraControllerRequestBus::Event(
- GetCameraEntityId(),
- &AZ::Debug::CameraControllerRequestBus::Events::Disable);
- }
- void ShadowExampleComponent::CreateMeshes()
- {
- using namespace AZ;
- auto updateFloorTransform = [&](const Data::Instance<RPI::Model>& model)
- {
- const AZ::Aabb& aabb = model->GetModelAsset()->GetAabb();
- const float maxZ = aabb.GetMax().GetZ();
- const AZ::Vector3 nonUniformScale{ 12.f, 12.f, 0.1f };
- const AZ::Vector3 translation{ 0.f, 0.f, -maxZ * nonUniformScale.GetZ() };
- const auto transform = AZ::Transform::CreateTranslation(translation);
- GetMeshFeatureProcessor()->SetTransform(m_floorMeshHandle, transform, nonUniformScale);
- m_floorMeshIsReady = true;
- if (m_bunnyMeshIsReady || m_floorMeshIsReady)
- {
- // Now that the models are initialized, we can allow the script to continue.
- ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
- }
- };
- auto updateBunnyTransform = [&](const Data::Instance<RPI::Model>& model)
- {
- const AZ::Aabb& aabb = model->GetModelAsset()->GetAabb();
- const float minZ = aabb.GetMin().GetZ();
- const AZ::Vector3 translation{ 0.f, 0.f, -minZ };
- auto transform = AZ::Transform::CreateTranslation(translation);
- transform.SetUniformScale(1.5f);
- GetMeshFeatureProcessor()->SetTransform(m_bunnyMeshHandle, transform);
- m_bunnyMeshIsReady = true;
- if (m_bunnyMeshIsReady || m_floorMeshIsReady)
- {
- // Now that the models are initialized, we can allow the script to continue.
- ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
- }
- };
- m_materialInstance = RPI::Material::FindOrCreate(m_materialAsset);
- {
- Render::MeshHandleDescriptor descriptor(m_floorModelAsset, m_materialInstance);
- descriptor.m_modelChangedEventHandler = AZ::Render::MeshHandleDescriptor::ModelChangedEvent::Handler(updateFloorTransform);
- m_floorMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(descriptor);
- }
- {
- Render::MeshHandleDescriptor descriptor(m_bunnyModelAsset, m_materialInstance);
- descriptor.m_modelChangedEventHandler = AZ::Render::MeshHandleDescriptor::ModelChangedEvent::Handler(updateBunnyTransform);
- m_bunnyMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(descriptor);
- }
- }
- void ShadowExampleComponent::CreateDirectionalLight()
- {
- using namespace AZ;
- Render::DirectionalLightFeatureProcessorInterface* const featureProcessor = m_directionalLightFeatureProcessor;
- const DirectionalLightHandle handle = featureProcessor->AcquireLight();
- AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> lightColor(DirectionalLightColor * m_directionalLightIntensity);
- featureProcessor->SetRgbIntensity(handle, lightColor);
- featureProcessor->SetShadowEnabled(handle, m_shadowEnabled);
- featureProcessor->SetShadowmapSize(handle, s_shadowmapImageSizes[m_directionalLightImageSizeIndex]);
- featureProcessor->SetShadowFarClipDistance(handle, FarClipDistance);
- featureProcessor->SetCascadeCount(handle, static_cast<uint16_t>(m_cascadeCount));
- featureProcessor->SetShadowmapFrustumSplitSchemeRatio(handle, m_ratioLogarithmUniform);
- featureProcessor->SetViewFrustumCorrectionEnabled(handle, m_isCascadeCorrectionEnabled);
- featureProcessor->SetShadowFilterMethod(handle, s_shadowFilterMethods[m_shadowFilterMethodIndexDirectional]);
- featureProcessor->SetFilteringSampleCount(handle, static_cast<uint16_t>(m_filteringSampleCountDirectional));
- featureProcessor->SetGroundHeight(handle, 0.f);
- featureProcessor->SetFullscreenBlurEnabled(handle, m_useFullscreenBlur);
- m_directionalLightHandle = handle;
- SetupDebugFlags();
- }
- void ShadowExampleComponent::CreateDiskLights()
- {
- DestroyDiskLights();
- using namespace AZ;
- Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- const DiskLightHandle handle = featureProcessor->AcquireLight();
- AZ_Assert(m_diskLightHandles[index].IsNull(), "Unreleased light");
- m_diskLightHandles[index] = handle;
- }
- ApplyDiskLightSettings();
- }
- void ShadowExampleComponent::CreatePointLights()
- {
- DestroyPointLights();
- using namespace AZ;
- Render::PointLightFeatureProcessorInterface* const featureProcessor = m_pointLightFeatureProcessor;
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- const PointLightHandle handle = featureProcessor->AcquireLight();
- AZ_Assert(m_pointLightHandles[index].IsNull(), "Unreleased light");
- m_pointLightHandles[index] = handle;
- }
- ApplyPointLightSettings();
- }
- void ShadowExampleComponent::DrawSidebar()
- {
- using namespace AZ::Render;
- if (m_imguiSidebar.Begin())
- {
- ImGui::Spacing();
- DrawSidebarDirectionalLight();
- ImGui::Separator();
- if (DrawSidebarPositionalLights())
- {
- ApplyDiskLightSettings();
- ApplyPointLightSettings();
- }
- ImGui::Separator();
- DrawSidebarCamera();
- ImGui::Separator();
- if (ScriptableImGui::Button("Material Details..."))
- {
- m_imguiMaterialDetails.OpenDialog();
- }
- m_imguiSidebar.End();
- }
- m_imguiMaterialDetails.Tick(&GetMeshFeatureProcessor()->GetDrawPackets(m_bunnyMeshHandle), "Bunny Mesh");
- }
- void ShadowExampleComponent::DrawSidebarDirectionalLight()
- {
- ImGui::Indent();
- if (ImGui::CollapsingHeader("Directional Light", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
- {
- ScriptableImGui::SliderFloat("Height##Directional", &m_directionalLightHeight, 1.f, 30.f, "%.1f", ImGuiSliderFlags_Logarithmic);
- ScriptableImGui::Checkbox("Auto Rotation##Directional", &m_isDirectionalLightAutoRotate);
- ScriptableImGui::SliderAngle("Direction##Directional", &m_directionalLightRotationAngle, 0, 360);
- if (ScriptableImGui::SliderFloat(
- "Intensity##Directional", &m_directionalLightIntensity, 0.f, 20.f, "%.1f", ImGuiSliderFlags_Logarithmic))
- {
- AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> lightColor(
- DirectionalLightColor * m_directionalLightIntensity);
- m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, lightColor);
- }
- ImGui::Text("Shadowmap Size");
- if (ScriptableImGui::Combo(
- "Size##Directional", &m_directionalLightImageSizeIndex, s_shadowmapImageSizeLabels,
- aznumeric_cast<int>(AZStd::size(s_shadowmapImageSizeLabels))))
- {
- m_directionalLightFeatureProcessor->SetShadowmapSize(
- m_directionalLightHandle, s_shadowmapImageSizes[m_directionalLightImageSizeIndex]);
- }
- ImGui::Text("Number of cascades");
- bool cascadesChanged = false;
- cascadesChanged = cascadesChanged || ScriptableImGui::RadioButton("1", &m_cascadeCount, 1);
- ImGui::SameLine();
- cascadesChanged = cascadesChanged || ScriptableImGui::RadioButton("2", &m_cascadeCount, 2);
- ImGui::SameLine();
- cascadesChanged = cascadesChanged || ScriptableImGui::RadioButton("3", &m_cascadeCount, 3);
- ImGui::SameLine();
- cascadesChanged = cascadesChanged || ScriptableImGui::RadioButton("4", &m_cascadeCount, 4);
- if (cascadesChanged)
- {
- m_directionalLightFeatureProcessor->SetCascadeCount(m_directionalLightHandle, static_cast<uint16_t>(m_cascadeCount));
- }
- ImGui::Spacing();
- bool cascadeDepthIsChanged = ScriptableImGui::Checkbox("Automatic Cascade Split", &m_shadowmapFrustumSplitIsAutomatic);
- if (m_shadowmapFrustumSplitIsAutomatic)
- {
- ImGui::Text("Cascade partition scheme");
- ImGui::Text(" (uniform <--> logarithm)");
- cascadeDepthIsChanged =
- cascadeDepthIsChanged || ScriptableImGui::SliderFloat("Ratio", &m_ratioLogarithmUniform, 0.f, 1.f, "%0.3f");
- if (cascadeDepthIsChanged)
- {
- m_directionalLightFeatureProcessor->SetShadowmapFrustumSplitSchemeRatio(
- m_directionalLightHandle, m_ratioLogarithmUniform);
- }
- }
- else
- {
- for (int cascadeIndex = 0; cascadeIndex < m_cascadeCount; ++cascadeIndex)
- {
- const AZStd::string label = AZStd::string::format("FarDepth %d", cascadeIndex);
- cascadeDepthIsChanged =
- cascadeDepthIsChanged || ScriptableImGui::SliderFloat(label.c_str(), &m_cascadeFarDepth[cascadeIndex], 0.01f, 20.f);
- }
- if (cascadeDepthIsChanged)
- {
- for (int cascadeIndex = 0; cascadeIndex < m_cascadeCount; ++cascadeIndex)
- {
- m_directionalLightFeatureProcessor->SetCascadeFarDepth(
- m_directionalLightHandle, aznumeric_cast<uint16_t>(cascadeIndex), m_cascadeFarDepth[cascadeIndex]);
- }
- }
- }
- ImGui::Spacing();
- ImGui::Text("Filtering");
- if (ScriptableImGui::Combo(
- "Filter Method##Directional", &m_shadowFilterMethodIndexDirectional, s_shadowFilterMethodLabels,
- aznumeric_cast<int>(AZStd::size(s_shadowFilterMethodLabels))))
- {
- m_directionalLightFeatureProcessor->SetShadowFilterMethod(
- m_directionalLightHandle, s_shadowFilterMethods[m_shadowFilterMethodIndexDirectional]);
- }
- if (m_shadowFilterMethodIndexDirectional == aznumeric_cast<int>(AZ::Render::ShadowFilterMethod::Pcf) ||
- m_shadowFilterMethodIndexDirectional == aznumeric_cast<int>(AZ::Render::ShadowFilterMethod::EsmPcf))
- {
- ImGui::Spacing();
- ImGui::Text("Filtering (PCF specific)");
- if (ScriptableImGui::SliderInt("Filtering # ##Directional", &m_filteringSampleCountDirectional, 4, 64))
- {
- m_directionalLightFeatureProcessor->SetFilteringSampleCount(
- m_directionalLightHandle, static_cast<uint16_t>(m_filteringSampleCountDirectional));
- }
- }
- ImGui::Spacing();
- bool debugFlagsChanged = false;
- debugFlagsChanged = ScriptableImGui::Checkbox("Debug Coloring", &m_isDebugColoringEnabled) || debugFlagsChanged;
- debugFlagsChanged = ScriptableImGui::Checkbox("Debug Bounding Box", &m_isDebugBoundingBoxEnabled) || debugFlagsChanged;
- if (debugFlagsChanged)
- {
- SetupDebugFlags();
- }
- if (ScriptableImGui::Checkbox("Cascade Position Correction", &m_isCascadeCorrectionEnabled))
- {
- m_directionalLightFeatureProcessor->SetViewFrustumCorrectionEnabled(m_directionalLightHandle, m_isCascadeCorrectionEnabled);
- }
- if (ScriptableImGui::Checkbox("Use Fullscreen Blur", &m_useFullscreenBlur))
- {
- m_directionalLightFeatureProcessor->SetFullscreenBlurEnabled(m_directionalLightHandle, m_useFullscreenBlur);
- }
- }
- ImGui::Unindent();
- }
- bool ShadowExampleComponent::DrawSidebarPositionalLights()
- {
- using namespace AZ::Render;
- bool settingsChanged = false;
- ImGui::Indent();
- if (ImGui::CollapsingHeader("Positional Lights", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
- {
- ImGui::Text("Light Type");
- if (ScriptableImGui::RadioButton("Disk", &m_positionalLightTypeActive, 0))
- {
- DestroyPointLights();
- CreateDiskLights();
- settingsChanged = true;
- }
- if (ScriptableImGui::RadioButton("Point", &m_positionalLightTypeActive, 1))
- {
- DestroyDiskLights();
- CreatePointLights();
- settingsChanged = true;
- }
- ScriptableImGui::Checkbox("Auto Rotation##Positional", &m_isPositionalLightAutoRotate);
- ScriptableImGui::SliderAngle("Base Direction##Positional", &m_positionalLightRotationAngle, 0, 360);
- ImGui::Spacing();
- ImGui::Text("Control Target");
- ScriptableImGui::RadioButton("Red", &m_controlTargetPositionalLightIndex, 0);
- ImGui::SameLine();
- ScriptableImGui::RadioButton("Green", &m_controlTargetPositionalLightIndex, 1);
- ImGui::SameLine();
- ScriptableImGui::RadioButton("Blue", &m_controlTargetPositionalLightIndex, 2);
- const int index = m_controlTargetPositionalLightIndex;
- ScriptableImGui::SliderFloat(
- "Height##Positional", &m_positionalLightHeights[index], 1.f, 30.f, "%.1f", ImGuiSliderFlags_Logarithmic);
- if (ScriptableImGui::SliderFloat("Cone Angle", &m_outerConeAngles[index], 0.f, 120.f))
- {
- settingsChanged = true;
- }
- if (ScriptableImGui::SliderFloat(
- "Intensity##Positional", &m_lightIntensities[index], 0.f, 20000.f, "%.1f", ImGuiSliderFlags_Logarithmic))
- {
- settingsChanged = true;
- }
- bool shadowmapSizeChanged = ScriptableImGui::Checkbox("Enable Shadow", &m_positionalLightShadowEnabled[index]);
- ImGui::Text("Shadowmap Size");
- shadowmapSizeChanged = shadowmapSizeChanged ||
- ScriptableImGui::Combo("Size##Positional", &m_positionalLightImageSizeIndices[index], s_shadowmapImageSizeLabels,
- aznumeric_cast<int>(AZStd::size(s_shadowmapImageSizeLabels)));
- if (shadowmapSizeChanged)
- {
- // Reset shadow parameters when shadow is disabled.
- if (!m_positionalLightShadowEnabled[index])
- {
- m_shadowFilterMethodIndicesPositional[index] = 0;
- m_filteringSampleCountsPositional[index] = 0;
- }
- settingsChanged = true;
- }
- ImGui::Spacing();
- ImGui::Text("Filtering");
- if (ScriptableImGui::Combo(
- "Filter Method##Positional", &m_shadowFilterMethodIndicesPositional[index], s_shadowFilterMethodLabels,
- aznumeric_cast<int>(AZStd::size(s_shadowFilterMethodLabels))))
- {
- settingsChanged = true;
- }
- if (m_shadowFilterMethodIndicesPositional[index] == aznumeric_cast<int>(ShadowFilterMethod::Pcf) ||
- m_shadowFilterMethodIndicesPositional[index] == aznumeric_cast<int>(ShadowFilterMethod::EsmPcf))
- {
- ImGui::Spacing();
- ImGui::Text("Filtering (PCF specific)");
- if (ScriptableImGui::SliderInt("Filtering # ##Positional", &m_filteringSampleCountsPositional[index], 4, 64))
- {
- settingsChanged = true;
- }
- }
- }
- ImGui::Unindent();
- return settingsChanged;
- }
- void ShadowExampleComponent::DrawSidebarCamera()
- {
- ImGui::Indent();
- if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
- {
- using namespace AZ;
- ScriptableImGui::SliderAngle("FoVY", &m_cameraFovY, 1.f, 120.f);
- ImGui::Spacing();
- Transform cameraTransform;
- TransformBus::EventResult(cameraTransform, GetCameraEntityId(), &TransformBus::Events::GetWorldTM);
- const Vector3 eularDegrees = cameraTransform.GetEulerDegrees();
- float cameraPitch = eularDegrees.GetElement(0);
- const float cameraYaw = eularDegrees.GetElement(1);
- if (cameraPitch > 180.f)
- {
- cameraPitch -= 360.f;
- }
- ImGui::Text("Pitch: %f", cameraPitch);
- ImGui::Text("Yaw: %f", cameraYaw);
- }
- ImGui::Unindent();
- }
- void ShadowExampleComponent::SetupDebugFlags()
- {
- int flags = AZ::Render::DirectionalLightFeatureProcessorInterface::DebugDrawFlags::DebugDrawNone;
- if (m_isDebugColoringEnabled)
- {
- flags |= AZ::Render::DirectionalLightFeatureProcessorInterface::DebugDrawFlags::DebugDrawColoring;
- }
- if (m_isDebugBoundingBoxEnabled)
- {
- flags |= AZ::Render::DirectionalLightFeatureProcessorInterface::DebugDrawFlags::DebugDrawBoundingBoxes;
- }
- m_directionalLightFeatureProcessor->SetDebugFlags(m_directionalLightHandle,
- static_cast<AZ::Render::DirectionalLightFeatureProcessorInterface::DebugDrawFlags>(flags));
- }
- void ShadowExampleComponent::DestroyDiskLights()
- {
- for (DiskLightHandle& handle : m_diskLightHandles)
- {
- m_diskLightFeatureProcessor->ReleaseLight(handle);
- }
- }
- void ShadowExampleComponent::DestroyPointLights()
- {
- for (PointLightHandle& handle : m_pointLightHandles)
- {
- m_pointLightFeatureProcessor->ReleaseLight(handle);
- }
- }
- void ShadowExampleComponent::ApplyDiskLightSettings()
- {
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- auto lightHandle = m_diskLightHandles[index];
- if (lightHandle.IsValid())
- {
- auto [innerConeAngle, outerConeAngle] = GetConeAnglesForLight(index);
- m_diskLightFeatureProcessor->SetConeAngles(lightHandle, innerConeAngle, outerConeAngle);
- m_diskLightFeatureProcessor->SetPosition(lightHandle, GetTransformForLight(index).GetTranslation());
- m_diskLightFeatureProcessor->SetDirection(lightHandle, GetTransformForLight(index).GetBasis(1));
- m_diskLightFeatureProcessor->SetAttenuationRadius(lightHandle, GetAttenuationForLight(index));
- m_diskLightFeatureProcessor->SetRgbIntensity(lightHandle, GetRgbIntensityForLight(index));
- const bool shadowEnabled = m_positionalLightShadowEnabled[index];
- m_diskLightFeatureProcessor->SetShadowsEnabled(lightHandle, shadowEnabled);
- if (shadowEnabled)
- {
- m_diskLightFeatureProcessor->SetShadowmapMaxResolution(
- lightHandle, s_shadowmapImageSizes[m_positionalLightImageSizeIndices[index]]);
- m_diskLightFeatureProcessor->SetShadowFilterMethod(
- lightHandle, s_shadowFilterMethods[m_shadowFilterMethodIndicesPositional[index]]);
- m_diskLightFeatureProcessor->SetFilteringSampleCount(lightHandle, static_cast<uint16_t>(m_filteringSampleCountsPositional[index]));
- }
- }
- }
- }
- void ShadowExampleComponent::ApplyPointLightSettings()
- {
- for (uint32_t index = 0; index < PositionalLightCount; ++index)
- {
- auto lightHandle = m_pointLightHandles[index];
- if (lightHandle.IsValid())
- {
- m_pointLightFeatureProcessor->SetPosition(lightHandle, GetTransformForLight(index).GetTranslation());
- m_pointLightFeatureProcessor->SetBulbRadius(lightHandle, 0.0f);
- m_pointLightFeatureProcessor->SetAttenuationRadius(lightHandle, GetAttenuationForLight(index));
- m_pointLightFeatureProcessor->SetRgbIntensity(lightHandle, GetRgbIntensityForLight(index));
- const bool shadowEnabled = m_positionalLightShadowEnabled[index];
- m_pointLightFeatureProcessor->SetShadowsEnabled(lightHandle, shadowEnabled);
- if (shadowEnabled)
- {
- m_pointLightFeatureProcessor->SetShadowmapMaxResolution(
- lightHandle, s_shadowmapImageSizes[m_positionalLightImageSizeIndices[index]]);
- m_pointLightFeatureProcessor->SetShadowFilterMethod(
- lightHandle, s_shadowFilterMethods[m_shadowFilterMethodIndicesPositional[index]]);
- m_pointLightFeatureProcessor->SetFilteringSampleCount(lightHandle, static_cast<uint16_t>(m_filteringSampleCountsPositional[index]));
- }
- }
- }
- }
- } // namespace AtomSampleViewer
|