/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include namespace AtomSampleViewer { void DepthOfFieldExampleComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(0) ; } } void DepthOfFieldExampleComponent::Activate() { using namespace AZ; m_postProcessFeatureProcessor = m_scene->GetFeatureProcessor(); m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); // Create the assets m_bunnyModelAsset = RPI::AssetUtils::GetAssetByProductPath("objects/bunny.fbx.azmodel", RPI::AssetUtils::TraceLevel::Assert); m_materialAsset = RPI::AssetUtils::GetAssetByProductPath(DefaultPbrMaterialPath, RPI::AssetUtils::TraceLevel::Assert); CreateMeshes(); CreateLight(); CreateDepthOfFieldEntity(); UseArcBallCameraController(); m_imguiSidebar.Activate(); AZ::TickBus::Handler::BusConnect(); } void DepthOfFieldExampleComponent::Deactivate() { Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetNearClipDistance, m_saveDefaultNearOnAtomSampleViewer); Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, m_saveDefaultFarOnAtomSampleViewer); Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFovDegrees, m_saveDefaultFovDegreesOnAtomSampleViewer); AZ::TickBus::Handler::BusDisconnect(); RemoveController(); AZ::EntityBus::MultiHandler::BusDisconnect(); if (m_postProcessSettings) { m_postProcessSettings->RemoveDepthOfFieldSettingsInterface(); } m_postProcessSettings = nullptr; if (m_depthOfFieldEntity) { DestroyEntity(m_depthOfFieldEntity, GetEntityContextId()); } if (m_directionalLightHandle.IsValid()) { m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle); } for (MeshHandle& meshHandle : m_meshHandles) { GetMeshFeatureProcessor()->ReleaseMesh(meshHandle); } m_imguiSidebar.Deactivate(); } void DepthOfFieldExampleComponent::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint) { if (!m_isInitCamera) { const AZ::Vector3 InitTranslation = DistanceBetweenUnits * AZ::Vector3(BunnyNumber / 8, BunnyNumber / 16, 0.5f); constexpr float InitPitch = 0.0f; constexpr float InitHeading = -0.65f; AZ::Debug::ArcBallControllerRequestBus::Event( GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetCenter, InitTranslation); AZ::Debug::ArcBallControllerRequestBus::Event( GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetPitch, InitPitch); AZ::Debug::ArcBallControllerRequestBus::Event( GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetHeading, InitHeading); } m_isInitCamera = true; DrawSidebar(); } void DepthOfFieldExampleComponent::OnEntityDestruction(const AZ::EntityId& entityId) { AZ::EntityBus::MultiHandler::BusDisconnect(entityId); if (m_depthOfFieldEntity && m_depthOfFieldEntity->GetId() == entityId) { m_postProcessFeatureProcessor->RemoveSettingsInterface(m_depthOfFieldEntity->GetId()); m_depthOfFieldEntity = nullptr; } else { AZ_Assert(false, "unexpected entity destruction is signaled."); } } void DepthOfFieldExampleComponent::UseArcBallCameraController() { using namespace AZ; Debug::CameraControllerRequestBus::Event( GetCameraEntityId(), &Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); Camera::CameraRequestBus::EventResult( m_saveDefaultNearOnAtomSampleViewer, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetNearClipDistance); Camera::CameraRequestBus::EventResult( m_saveDefaultFarOnAtomSampleViewer, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance); Camera::CameraRequestBus::EventResult( m_saveDefaultFovDegreesOnAtomSampleViewer, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFovDegrees); Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetNearClipDistance, ViewNear); Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, ViewFar); Camera::CameraRequestBus::Event( GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFovDegrees, ViewFovDegrees); } void DepthOfFieldExampleComponent::RemoveController() { AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable); } void DepthOfFieldExampleComponent::CreateMeshes() { using namespace AZ; auto materialInstance = RPI::Material::FindOrCreate(m_materialAsset); Vector3 translation = Vector3::CreateZero(); Transform scaleTransform = Transform::CreateUniformScale(ModelScaleRatio); for (MeshHandle& meshHandle : m_meshHandles) { meshHandle = GetMeshFeatureProcessor()->AcquireMesh(Render::MeshHandleDescriptor(m_bunnyModelAsset, materialInstance)); auto transform = AZ::Transform::CreateTranslation(translation); transform *= scaleTransform; GetMeshFeatureProcessor()->SetTransform(meshHandle, transform); translation += Vector3(DistanceBetweenUnits, DistanceBetweenUnits, 0.0f); } } void DepthOfFieldExampleComponent::CreateLight() { using namespace AZ; Render::DirectionalLightFeatureProcessorInterface* const fp = m_directionalLightFeatureProcessor; DirectionalLightHandle handle = fp->AcquireLight(); fp->SetRgbIntensity(handle, Render::PhotometricColor(Color(5.f, 5.f, 5.f, 1.f))); fp->SetDirection(handle, Vector3(-1.f, 1.f, -1.f).GetNormalized()); m_directionalLightHandle = handle; } void DepthOfFieldExampleComponent::CreateDepthOfFieldEntity() { using namespace AZ; m_depthOfFieldEntity = CreateEntity("DepthOfField", GetEntityContextId()); // Transform Component* transformComponent = nullptr; ComponentDescriptorBus::EventResult( transformComponent, azrtti_typeid(), &ComponentDescriptorBus::Events::CreateComponent); m_depthOfFieldEntity->AddComponent(transformComponent); // DepthOfField m_postProcessSettings = m_postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_depthOfFieldEntity->GetId()); m_depthOfFieldSettings = m_postProcessSettings->GetOrCreateDepthOfFieldSettingsInterface(); m_depthOfFieldSettings->SetQualityLevel(1); m_depthOfFieldSettings->SetApertureF(0.5f); m_depthOfFieldSettings->SetFocusDistance(FocusDefault); m_depthOfFieldSettings->SetEnableDebugColoring(false); m_depthOfFieldSettings->SetEnableAutoFocus(false); m_depthOfFieldSettings->SetAutoFocusScreenPosition(AZ::Vector2{ 0.5f, 0.5f }); m_depthOfFieldSettings->SetAutoFocusSensitivity(1.0f); m_depthOfFieldSettings->SetAutoFocusSpeed(Render::DepthOfField::AutoFocusSpeedMax); m_depthOfFieldSettings->SetAutoFocusDelay(0.2f); m_depthOfFieldSettings->SetCameraEntityId(GetCameraEntityId()); m_depthOfFieldSettings->SetEnabled(true); m_depthOfFieldSettings->OnConfigChanged(); m_depthOfFieldEntity->Activate(); AZ::EntityBus::MultiHandler::BusConnect(m_depthOfFieldEntity->GetId()); } void DepthOfFieldExampleComponent::DrawSidebar() { using namespace AZ::Render; if (GetCameraEntityId() != m_depthOfFieldSettings->GetCameraEntityId()) { m_depthOfFieldSettings->SetCameraEntityId(GetCameraEntityId()); m_depthOfFieldSettings->OnConfigChanged(); } if (!m_imguiSidebar.Begin()) { return; } ImGui::Spacing(); ImGui::Text("Depth of Field"); ImGui::Indent(); { int32_t qualityLevel = aznumeric_cast(m_depthOfFieldSettings->GetQualityLevel()); if (ImGui::SliderInt("Quality Level", &qualityLevel, 0, DepthOfField::QualityLevelMax - 1, "%d") || !m_isInitParameters) { m_depthOfFieldSettings->SetQualityLevel(aznumeric_cast(qualityLevel)); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); float apertureF = m_depthOfFieldSettings->GetApertureF(); if (ImGui::SliderFloat("Aperture F", &apertureF, 0.0f, 1.0f, "%0.4f") || !m_isInitParameters) { m_depthOfFieldSettings->SetApertureF(apertureF); m_depthOfFieldSettings->OnConfigChanged(); } constexpr float Min = DepthOfField::ApertureFMin; constexpr float Max = DepthOfField::ApertureFMax; float viewApertureF = 1.0f / Max + (1.0f / Min - 1.0f / Max) * apertureF; viewApertureF = 1.0f / viewApertureF; ImGui::Text("f / %f", viewApertureF); ImGui::Spacing(); float viewNear = 1.f; float viewFar = 100.f; Camera::CameraRequestBus::EventResult(viewNear, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetNearClipDistance); Camera::CameraRequestBus::EventResult(viewFar, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance); float focusDistance = m_depthOfFieldSettings->GetFocusDistance(); if (ImGui::SliderFloat("Focus Distance", &focusDistance, ViewNear, ViewFar, "%0.3f") || !m_isInitParameters) { m_depthOfFieldSettings->SetFocusDistance(focusDistance); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); bool dofEnabled = m_depthOfFieldSettings->GetEnabled(); if (ImGui::Checkbox("Enabled Depth of Field", &dofEnabled) || !m_isInitParameters) { m_depthOfFieldSettings->SetEnabled(dofEnabled); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); bool enabledDebugColoring = m_depthOfFieldSettings->GetEnableDebugColoring(); if (ImGui::Checkbox("Enabled Debug Color", &enabledDebugColoring) || !m_isInitParameters) { m_depthOfFieldSettings->SetEnableDebugColoring(enabledDebugColoring); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); ImGui::Spacing(); ImGui::Spacing(); ImGui::Text("Auto Focus"); ImGui::Spacing(); bool enabledAutoFocus = m_depthOfFieldSettings->GetEnableAutoFocus(); if (ImGui::Checkbox("Enabled Auto Focus", &enabledAutoFocus) || !m_isInitParameters) { m_depthOfFieldSettings->SetEnableAutoFocus(enabledAutoFocus); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); float screenPosition[2]; AZ::Vector2 autoFocusScreenPosition = m_depthOfFieldSettings->GetAutoFocusScreenPosition(); screenPosition[0] = autoFocusScreenPosition.GetX(); screenPosition[1] = autoFocusScreenPosition.GetY(); if (ImGui::SliderFloat2("Screen Position", screenPosition, 0.0f, 1.0f, "%0.3f") || !m_isInitParameters) { autoFocusScreenPosition.SetX(screenPosition[0]); autoFocusScreenPosition.SetY(screenPosition[1]); m_depthOfFieldSettings->SetAutoFocusScreenPosition(autoFocusScreenPosition); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); float autoFocusSensitivity = m_depthOfFieldSettings->GetAutoFocusSensitivity(); if (ImGui::SliderFloat("Sensitivity", &autoFocusSensitivity, 0.0f, 1.0f , "%0.3f") || !m_isInitParameters) { m_depthOfFieldSettings->SetAutoFocusSensitivity(autoFocusSensitivity); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); float autoFocusSpeed = m_depthOfFieldSettings->GetAutoFocusSpeed(); if (ImGui::SliderFloat("Speed", &autoFocusSpeed, 0.0f, DepthOfField::AutoFocusSpeedMax, "%0.3f") || !m_isInitParameters) { m_depthOfFieldSettings->SetAutoFocusSpeed(autoFocusSpeed); m_depthOfFieldSettings->OnConfigChanged(); } ImGui::Spacing(); float autoFocusDelay = m_depthOfFieldSettings->GetAutoFocusDelay(); if (ImGui::SliderFloat("Delay", &autoFocusDelay, 0.0f, DepthOfField::AutoFocusDelayMax, "%0.3f") || !m_isInitParameters) { m_depthOfFieldSettings->SetAutoFocusDelay(autoFocusDelay); m_depthOfFieldSettings->OnConfigChanged(); } m_isInitParameters = true; } ImGui::Unindent(); ImGui::Separator(); m_imguiSidebar.End(); } } // namespace AtomSampleViewer