/* * 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 #include #include #include #include #include #include #include #include #include #include #include namespace AtomSampleViewer { const char* DiffuseGIExampleComponent::CornellBoxColorNames[] = { "Red", "Green", "Blue", "Yellow", "White" }; const AZ::Render::ShadowmapSize DiffuseGIExampleComponent::s_shadowmapSizes[] = { AZ::Render::ShadowmapSize::Size256, AZ::Render::ShadowmapSize::Size512, AZ::Render::ShadowmapSize::Size1024, AZ::Render::ShadowmapSize::Size2048 }; void DiffuseGIExampleComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(0) ; } } void DiffuseGIExampleComponent::Activate() { m_imguiSidebar.Activate(); AZ::TickBus::Handler::BusConnect(); // setup the camera Camera::CameraRequestBus::EventResult(m_originalFarClipDistance, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance); Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, 180.f); // disable global Ibl in the example scene since we're controlling it separately DisableGlobalIbl(); LoadSampleSceneAssets(); } void DiffuseGIExampleComponent::UnloadSampleScene(bool geometryOnly) { // release meshes AZ::Render::MeshFeatureProcessorInterface* meshFeatureProcessor = m_scene->GetFeatureProcessor(); for (auto& meshHandle : m_meshHandles) { meshFeatureProcessor->ReleaseMesh(meshHandle); } // unload everything else if necessary if (!geometryOnly) { if (m_diffuseProbeGrid) { AZ::Render::DiffuseProbeGridFeatureProcessorInterface* diffuseProbeGridFeatureProcessor = m_scene->GetFeatureProcessor(); diffuseProbeGridFeatureProcessor->RemoveProbeGrid(m_diffuseProbeGrid); } if (m_directionalLightHandle.IsValid()) { AZ::Render::DirectionalLightFeatureProcessorInterface* directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle); } if (m_pointLightHandle.IsValid()) { AZ::Render::PointLightFeatureProcessorInterface* pointLightFeatureProcessor = m_scene->GetFeatureProcessor(); pointLightFeatureProcessor->ReleaseLight(m_pointLightHandle); } } } void DiffuseGIExampleComponent::SetSampleScene(bool geometryOnly /*= false*/) { UnloadSampleScene(geometryOnly); // set new scene switch (m_sampleScene) { case SampleScene::CornellBox: CreateCornellBoxScene(geometryOnly); break; case SampleScene::Sponza: CreateSponzaScene(); break; }; } void DiffuseGIExampleComponent::Deactivate() { // disable camera Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, m_originalFarClipDistance); AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable); AZ::TickBus::Handler::BusDisconnect(); m_imguiSidebar.Deactivate(); m_defaultIbl.Reset(); UnloadSampleScene(false); } float DiffuseGIExampleComponent::ComputePointLightAttenuationRadius(AZ::Color color, float intensity) { static const float CutoffIntensity = 0.1f; float luminance = AZ::Render::PhotometricValue::GetPerceptualLuminance(color * intensity); return sqrt(luminance / CutoffIntensity); } void DiffuseGIExampleComponent::LoadSampleSceneAssets() { // load plane and cube models // all geometry in the CornellBox is created from planes and boxes static constexpr const char PlaneModelPath[] = "objects/plane.fbx.azmodel"; AZ::Data::AssetId planeAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(PlaneModelPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_planeModelAsset.Create(planeAssetId); static constexpr const char CubeModelPath[] = "objects/cube.fbx.azmodel"; AZ::Data::AssetId cubeAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(CubeModelPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_cubeModelAsset.Create(cubeAssetId); // materials for the CornellBox static constexpr const char RedMaterialPath[] = "materials/diffusegiexample/red.azmaterial"; AZ::Data::AssetId redMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(RedMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_redMaterialAsset.Create(redMaterialAssetId); static constexpr const char GreenMaterialPath[] = "materials/diffusegiexample/green.azmaterial"; AZ::Data::AssetId greenMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(GreenMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_greenMaterialAsset.Create(greenMaterialAssetId); static constexpr const char BlueMaterialPath[] = "materials/diffusegiexample/blue.azmaterial"; AZ::Data::AssetId blueMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(BlueMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_blueMaterialAsset.Create(blueMaterialAssetId); static constexpr const char YellowMaterialPath[] = "materials/diffusegiexample/yellow.azmaterial"; AZ::Data::AssetId yellowMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(YellowMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_yellowMaterialAsset.Create(yellowMaterialAssetId); static constexpr const char WhiteMaterialPath[] = "materials/diffusegiexample/white.azmaterial"; AZ::Data::AssetId whiteMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(WhiteMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_whiteMaterialAsset.Create(whiteMaterialAssetId); // Sponza models static constexpr const char InteriorModelPath[] = "objects/sponza.fbx.azmodel"; AZ::Data::AssetId interiorAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(InteriorModelPath, AZ::RPI::AssetUtils::TraceLevel::Error); m_sponzaModelAsset.Create(interiorAssetId); // diffuse IBL cubemap const constexpr char* DiffuseAssetPath = "lightingpresets/lowcontrast/palermo_sidewalk_4k_iblskyboxcm_ibldiffuse.exr.streamingimage"; if (!m_diffuseImageAsset.IsReady()) { m_diffuseImageAsset = AZ::RPI::AssetUtils::GetAssetByProductPath(DiffuseAssetPath, AZ::RPI::AssetUtils::TraceLevel::Assert); m_diffuseImageAsset.QueueLoad(); } } AZ::Data::Asset& DiffuseGIExampleComponent::GetCornellBoxMaterialAsset(CornellBoxColors color) { switch (color) { case CornellBoxColors::Red: return m_redMaterialAsset; case CornellBoxColors::Green: return m_greenMaterialAsset; case CornellBoxColors::Blue: return m_blueMaterialAsset; case CornellBoxColors::Yellow: return m_yellowMaterialAsset; case CornellBoxColors::White: return m_whiteMaterialAsset; }; AZ_Assert(false, "Unknown material color"); return m_whiteMaterialAsset; } void DiffuseGIExampleComponent::CreateCornellBoxScene(bool geometryOnly) { m_meshHandles.resize(aznumeric_cast(CornellBoxMeshes::Count)); // left wall if (m_leftWallVisible) { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(-5.0f, 0.0f, 0.0f); transform *= AZ::Transform::CreateRotationY(AZ::Constants::HalfPi); AZ::Vector3 nonUniformScale(10.05f, 10.05f, 1.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::LeftWall)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor( m_planeModelAsset, AZ::RPI::Material::FindOrCreate(GetCornellBoxMaterialAsset(m_leftWallColor)))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::LeftWall)], transform, nonUniformScale); } // right wall if (m_rightWallVisible) { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(5.0f, 0.0f, 0.0f); transform *= AZ::Transform::CreateRotationY(-AZ::Constants::HalfPi); AZ::Vector3 nonUniformScale(10.05f, 10.05f, 1.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::RightWall)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor( m_planeModelAsset, AZ::RPI::Material::FindOrCreate(GetCornellBoxMaterialAsset(m_rightWallColor)))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::RightWall)], transform, nonUniformScale); } // back wall if (m_backWallVisible) { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(0.0f, 5.0f, 0.0f); transform *= AZ::Transform::CreateRotationX(AZ::Constants::HalfPi); AZ::Vector3 nonUniformScale(10.05f, 10.05f, 1.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::BackWall)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor( m_planeModelAsset, AZ::RPI::Material::FindOrCreate(GetCornellBoxMaterialAsset(m_backWallColor)))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::BackWall)], transform, nonUniformScale); } // ceiling if (m_ceilingVisible) { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(0.0f, 0.0f, 5.0f); transform *= AZ::Transform::CreateRotationX(AZ::Constants::Pi); AZ::Vector3 nonUniformScale(10.05f, 10.05f, 1.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::Ceiling)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor( m_planeModelAsset, AZ::RPI::Material::FindOrCreate(GetCornellBoxMaterialAsset(m_ceilingColor)))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::Ceiling)], transform, nonUniformScale); } // floor if (m_floorVisible) { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(0.0f, 0.0f, -5.0f); AZ::Vector3 nonUniformScale(10.05f, 10.05f, 1.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::Floor)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor( m_planeModelAsset, AZ::RPI::Material::FindOrCreate(GetCornellBoxMaterialAsset(m_floorColor)))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::Floor)], transform, nonUniformScale); } // large box { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(-2.0f, 0.0f, -2.0f); transform *= AZ::Transform::CreateRotationZ(AZ::Constants::HalfPi * 0.2f); AZ::Vector3 nonUniformScale(3.0f, 3.0f, 6.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::LargeBox)] = GetMeshFeatureProcessor()->AcquireMesh( AZ::Render::MeshHandleDescriptor(m_cubeModelAsset, AZ::RPI::Material::FindOrCreate(m_whiteMaterialAsset))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::LargeBox)], transform, nonUniformScale); } // small box { AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(2.0f, -1.5f, -3.5f); transform *= AZ::Transform::CreateRotationZ(-AZ::Constants::HalfPi * 0.2f); AZ::Vector3 nonUniformScale(3.0f, 3.0f, 3.0f); m_meshHandles[aznumeric_cast(CornellBoxMeshes::SmallBox)] = GetMeshFeatureProcessor()->AcquireMesh( AZ::Render::MeshHandleDescriptor(m_cubeModelAsset, AZ::RPI::Material::FindOrCreate(m_whiteMaterialAsset))); GetMeshFeatureProcessor()->SetTransform( m_meshHandles[aznumeric_cast(CornellBoxMeshes::SmallBox)], transform, nonUniformScale); } // stop now if we were only loading the geometry if (geometryOnly) { return; } m_pointLightPos = AZ::Vector3(0.0f, -1.0f, 4.0f); m_pointLightColor = AZ::Color(1.0f, 1.0f, 1.0f, 1.0f); m_pointLightIntensity = 20.0f; // point light { AZ::Render::PointLightFeatureProcessorInterface* pointLightFeatureProcessor = m_scene->GetFeatureProcessor(); m_pointLightHandle = pointLightFeatureProcessor->AcquireLight(); pointLightFeatureProcessor->SetPosition(m_pointLightHandle, m_pointLightPos); pointLightFeatureProcessor->SetRgbIntensity( m_pointLightHandle, AZ::Render::PhotometricColor(m_pointLightIntensity * m_pointLightColor)); pointLightFeatureProcessor->SetBulbRadius(m_pointLightHandle, 1.0f); pointLightFeatureProcessor->SetAttenuationRadius( m_pointLightHandle, ComputePointLightAttenuationRadius(m_pointLightColor, m_pointLightIntensity)); } // diffuse probe grid { AZ::Render::DiffuseProbeGridFeatureProcessorInterface* diffuseProbeGridFeatureProcessor = m_scene->GetFeatureProcessor(); AZ::Transform transform = AZ::Transform::CreateIdentity(); m_origin.Set(-0.8f, 0.5f, -0.055f); transform.SetTranslation(m_origin); m_diffuseProbeGrid = diffuseProbeGridFeatureProcessor->AddProbeGrid(transform, AZ::Vector3(12.0f, 12.0f, 12.0f), AZ::Vector3(1.5f, 1.5f, 2.0f)); diffuseProbeGridFeatureProcessor->SetAmbientMultiplier(m_diffuseProbeGrid, m_ambientMultiplier); m_viewBias = 0.5f; diffuseProbeGridFeatureProcessor->SetViewBias(m_diffuseProbeGrid, m_viewBias); m_normalBias = 0.1f; diffuseProbeGridFeatureProcessor->SetNormalBias(m_diffuseProbeGrid, m_normalBias); AZ::Render::DiffuseGlobalIlluminationFeatureProcessorInterface* diffuseGlobalIlluminationFeatureProcessor = m_scene->GetFeatureProcessor(); diffuseGlobalIlluminationFeatureProcessor->SetQualityLevel(AZ::Render::DiffuseGlobalIlluminationQualityLevel::Medium); } // camera m_cameraTranslation = AZ::Vector3(0.0f, -17.5f, 0.0f); m_cameraHeading = 0.0f; // disable diffuse Ibl DisableGlobalIbl(); } void DiffuseGIExampleComponent::CreateSponzaScene() { m_meshHandles.resize(aznumeric_cast(SponzaMeshes::Count)); AZ::Transform transform = AZ::Transform::CreateIdentity(); m_meshHandles[aznumeric_cast(SponzaMeshes::Inside)] = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor(m_sponzaModelAsset)); GetMeshFeatureProcessor()->SetTransform(m_meshHandles[aznumeric_cast(SponzaMeshes::Inside)], transform); m_directionalLightPitch = AZ::DegToRad(-65.0f); m_directionalLightYaw = AZ::DegToRad(65.0f); m_directionalLightColor = AZ::Color(1.0f, 0.9f, 0.6f, 1.0f); m_directionalLightIntensity = 20.0f; m_pointLightPos = AZ::Vector3(9.2f, -3.7f, 1.0f); m_pointLightColor = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f); m_pointLightIntensity = 10.0f; m_ambientMultiplier = 1.0f; // directional light { AZ::Render::DirectionalLightFeatureProcessorInterface* directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); m_directionalLightHandle = directionalLightFeatureProcessor->AcquireLight(); const auto lightTransform = AZ::Transform::CreateRotationZ(m_directionalLightYaw) * AZ::Transform::CreateRotationX(m_directionalLightPitch); directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightTransform.GetBasis(1)); directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, AZ::Render::PhotometricColor(m_directionalLightIntensity * m_directionalLightColor)); directionalLightFeatureProcessor->SetShadowEnabled(m_directionalLightHandle, true); directionalLightFeatureProcessor->SetCascadeCount(m_directionalLightHandle, 4); directionalLightFeatureProcessor->SetShadowmapSize(m_directionalLightHandle, AZ::Render::ShadowmapSize::Size2048); directionalLightFeatureProcessor->SetViewFrustumCorrectionEnabled(m_directionalLightHandle, false); directionalLightFeatureProcessor->SetShadowFilterMethod(m_directionalLightHandle, AZ::Render::ShadowFilterMethod::EsmPcf); directionalLightFeatureProcessor->SetFilteringSampleCount(m_directionalLightHandle, 16); directionalLightFeatureProcessor->SetGroundHeight(m_directionalLightHandle, 0.0f); } // point light { AZ::Render::PointLightFeatureProcessorInterface* pointLightFeatureProcessor = m_scene->GetFeatureProcessor(); m_pointLightHandle = pointLightFeatureProcessor->AcquireLight(); pointLightFeatureProcessor->SetPosition(m_pointLightHandle, m_pointLightPos); pointLightFeatureProcessor->SetRgbIntensity(m_pointLightHandle, AZ::Render::PhotometricColor(m_pointLightIntensity * m_pointLightColor)); pointLightFeatureProcessor->SetBulbRadius(m_pointLightHandle, 1.0f); pointLightFeatureProcessor->SetAttenuationRadius(m_pointLightHandle, ComputePointLightAttenuationRadius(m_pointLightColor, m_pointLightIntensity)); } // diffuse probe grid { AZ::Render::DiffuseProbeGridFeatureProcessorInterface* diffuseProbeGridFeatureProcessor = m_scene->GetFeatureProcessor(); transform = AZ::Transform::CreateIdentity(); m_origin.Set(0.0f, -0.275f, 5.0f); transform.SetTranslation(m_origin); m_diffuseProbeGrid = diffuseProbeGridFeatureProcessor->AddProbeGrid(transform, AZ::Vector3(35.0f, 45.0f, 25.0f), AZ::Vector3(3.0f, 3.0f, 4.0f)); diffuseProbeGridFeatureProcessor->SetAmbientMultiplier(m_diffuseProbeGrid, m_ambientMultiplier); m_viewBias = 0.55f; diffuseProbeGridFeatureProcessor->SetViewBias(m_diffuseProbeGrid, m_viewBias); m_normalBias = 0.4f; diffuseProbeGridFeatureProcessor->SetNormalBias(m_diffuseProbeGrid, m_normalBias); AZ::Render::DiffuseGlobalIlluminationFeatureProcessorInterface* diffuseGlobalIlluminationFeatureProcessor = m_scene->GetFeatureProcessor(); diffuseGlobalIlluminationFeatureProcessor->SetQualityLevel(AZ::Render::DiffuseGlobalIlluminationQualityLevel::Medium); } // camera m_cameraTranslation = AZ::Vector3(5.0f, 0.0f, 5.0f); m_cameraHeading = 90.0f; // diffuse Ibl EnableDiffuseIbl(); } void DiffuseGIExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { if (m_resetCamera) { AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Reset); AZ::TransformBus::Event(GetCameraEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, m_cameraTranslation); AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequestBus::Events::SetHeading, AZ::DegToRad(m_cameraHeading)); m_resetCamera = false; } // ImGui sidebar AZ::Render::DiffuseProbeGridFeatureProcessorInterface* diffuseProbeGridFeatureProcessor = m_scene->GetFeatureProcessor(); AZ::Render::PointLightFeatureProcessorInterface* pointLightFeatureProcessor = m_scene->GetFeatureProcessor(); AZ::Render::DirectionalLightFeatureProcessorInterface* directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); bool sceneChanged = false; // initialize the scene in OnTick() in order to delay a frame between samples if (m_sampleScene == SampleScene::None) { m_sampleScene = CornellBox; sceneChanged = true; } if (m_imguiSidebar.Begin()) { // sample scene { ImGui::Text("Scene"); sceneChanged |= ImGui::RadioButton("Cornell Box", (int*)&m_sampleScene, aznumeric_cast(CornellBox)); sceneChanged |= ImGui::RadioButton("Sponza", (int*)&m_sampleScene, aznumeric_cast(Sponza)); ImGui::NewLine(); } // diffuse probe grid settings { bool diffuseProbeGridChanged = false; diffuseProbeGridChanged |= ImGui::Checkbox("Enable Diffuse GI", &m_enableDiffuseGI); diffuseProbeGridChanged |= ImGui::SliderFloat("##AmbientMultiplier", &m_ambientMultiplier, 0.0f, 10.0f); ImGui::NewLine(); ImGui::Text("View Bias"); diffuseProbeGridChanged |= ImGui::SliderFloat("##ViewBias", &m_viewBias, 0.01f, 2.0f); ImGui::Text("Normal Bias"); diffuseProbeGridChanged |= ImGui::SliderFloat("##NormalBias", &m_normalBias, 0.01f, 2.0f); diffuseProbeGridChanged |= ImGui::Checkbox("GI Shadows", &m_giShadows); ImGui::NewLine(); ImGui::Text("Grid Origin"); float originX = m_origin.GetX(); diffuseProbeGridChanged |= ImGui::SliderFloat("##OriginX", &originX, -10.0f, 10.0f); float originY = m_origin.GetY(); diffuseProbeGridChanged |= ImGui::SliderFloat("##OriginY", &originY, -10.0f, 10.0f); float originZ = m_origin.GetZ(); diffuseProbeGridChanged |= ImGui::SliderFloat("##OriginZ", &originZ, -10.0f, 10.0f); m_origin.SetX(originX); m_origin.SetY(originY); m_origin.SetZ(originZ); if (diffuseProbeGridChanged && diffuseProbeGridFeatureProcessor->IsValidProbeGridHandle(m_diffuseProbeGrid)) { diffuseProbeGridFeatureProcessor->Enable(m_diffuseProbeGrid, m_enableDiffuseGI); diffuseProbeGridFeatureProcessor->SetAmbientMultiplier(m_diffuseProbeGrid, m_ambientMultiplier); diffuseProbeGridFeatureProcessor->SetViewBias(m_diffuseProbeGrid, m_viewBias); diffuseProbeGridFeatureProcessor->SetNormalBias(m_diffuseProbeGrid, m_normalBias); diffuseProbeGridFeatureProcessor->SetGIShadows(m_diffuseProbeGrid, m_giShadows); AZ::Transform transform = AZ::Transform::CreateIdentity(); transform.SetTranslation(m_origin); diffuseProbeGridFeatureProcessor->SetTransform(m_diffuseProbeGrid, transform); } ImGui::NewLine(); } // diffuse IBL (Sponza only) if (m_sampleScene == SampleScene::Sponza) { bool diffuseIblChanged = false; diffuseIblChanged |= ImGui::Checkbox("Diffuse IBL (Sky Light)", &m_useDiffuseIbl); diffuseIblChanged |= ImGui::SliderFloat("Exposure", &m_diffuseIblExposure, -10.0f, 10.0f); if (diffuseIblChanged && diffuseProbeGridFeatureProcessor->IsValidProbeGridHandle(m_diffuseProbeGrid)) { diffuseProbeGridFeatureProcessor->SetUseDiffuseIbl(m_diffuseProbeGrid, m_useDiffuseIbl); if (m_useDiffuseIbl) { EnableDiffuseIbl(); } else { DisableGlobalIbl(); } } ImGui::NewLine(); } // directional light if (m_directionalLightHandle.IsValid()) { bool directionalLightChanged = false; ImGui::Text("Directional Light"); directionalLightChanged |= ImGui::SliderAngle("Pitch", &m_directionalLightPitch, -90.0f, 0.f); directionalLightChanged |= ImGui::SliderAngle("Yaw", &m_directionalLightYaw, 0.f, 360.f); ImGui::Text("Color"); float directionalLightColor[4]; m_directionalLightColor.StoreToFloat4(&directionalLightColor[0]); directionalLightChanged |= ImGui::ColorEdit3("", &directionalLightColor[0]); ImGui::Text("Intensity"); directionalLightChanged |= ImGui::SliderFloat("##DirectionalLightIntensity", &m_directionalLightIntensity, 0, 100); if (directionalLightChanged) { const auto lightTransform = AZ::Transform::CreateRotationZ(m_directionalLightYaw) * AZ::Transform::CreateRotationX(m_directionalLightPitch); directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightTransform.GetBasis(1)); m_directionalLightColor = AZ::Color(directionalLightColor[0], directionalLightColor[1], directionalLightColor[2], 1.0f); directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, AZ::Render::PhotometricColor(m_directionalLightColor * m_directionalLightIntensity)); } // Camera Configuration { Camera::Configuration config; Camera::CameraRequestBus::EventResult( config, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); directionalLightFeatureProcessor->SetCameraConfiguration( m_directionalLightHandle, config); } // Camera Transform { AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult( transform, GetCameraEntityId(), &AZ::TransformBus::Events::GetWorldTM); directionalLightFeatureProcessor->SetCameraTransform( m_directionalLightHandle, transform); } ImGui::NewLine(); } // point light if (m_pointLightHandle.IsValid()) { bool pointLightChanged = false; ImGui::Text("Point Light"); float lightX = m_pointLightPos.GetX(); pointLightChanged |= ImGui::SliderFloat("##PointLightX", &lightX, -10.0f, 10.0f); float lightY = m_pointLightPos.GetY(); pointLightChanged |= ImGui::SliderFloat("##PointLightY", &lightY, -10.0f, 10.0f); float lightZ = m_pointLightPos.GetZ(); pointLightChanged |= ImGui::SliderFloat("##PointLightZ", &lightZ, -10.0f, 10.0f); m_pointLightPos.SetX(lightX); m_pointLightPos.SetY(lightY); m_pointLightPos.SetZ(lightZ); float pointLightColor[4]; m_pointLightColor.StoreToFloat4(&pointLightColor[0]); pointLightChanged |= ImGui::ColorEdit3("Point Light Color", &pointLightColor[0]); ImGui::Text("Intensity"); pointLightChanged |= ImGui::SliderFloat("##PointLightIntensity", &m_pointLightIntensity, 0, 100); if (pointLightChanged) { m_pointLightColor = AZ::Color(pointLightColor[0], pointLightColor[1], pointLightColor[2], 1.0f); pointLightFeatureProcessor->SetPosition(m_pointLightHandle, m_pointLightPos); pointLightFeatureProcessor->SetRgbIntensity(m_pointLightHandle, AZ::Render::PhotometricColor(m_pointLightColor * m_pointLightIntensity)); pointLightFeatureProcessor->SetAttenuationRadius(m_pointLightHandle, ComputePointLightAttenuationRadius(m_pointLightColor, m_pointLightIntensity)); } ImGui::NewLine(); } // Cornell Box specific if (m_sampleScene == CornellBox) { bool geometryChanged = false; geometryChanged |= ImGui::Checkbox("Left Wall Visible", &m_leftWallVisible); geometryChanged |= ImGui::Combo("Left Wall Color", (int*)&m_leftWallColor, CornellBoxColorNames, CornellBoxColorNamesCount); geometryChanged |= ImGui::Checkbox("Right Wall Visible", &m_rightWallVisible); geometryChanged |= ImGui::Combo("Right Wall Color", (int*)&m_rightWallColor, CornellBoxColorNames, CornellBoxColorNamesCount); geometryChanged |= ImGui::Checkbox("Back Wall Visible", &m_backWallVisible); geometryChanged |= ImGui::Combo("Back Wall Color", (int*)&m_backWallColor, CornellBoxColorNames, CornellBoxColorNamesCount); geometryChanged |= ImGui::Checkbox("Floor Visible", &m_floorVisible); geometryChanged |= ImGui::Combo("Floor Color", (int*)&m_floorColor, CornellBoxColorNames, CornellBoxColorNamesCount); geometryChanged |= ImGui::Checkbox("Ceiling Visible", &m_ceilingVisible); geometryChanged |= ImGui::Combo("Ceiling Color", (int*)&m_ceilingColor, CornellBoxColorNames, CornellBoxColorNamesCount); if (geometryChanged) { SetSampleScene(true); } } m_imguiSidebar.End(); } if (sceneChanged) { m_resetCamera = true; SetSampleScene(); } } void DiffuseGIExampleComponent::OnEntityDestruction(const AZ::EntityId& entityId) { AZ::EntityBus::MultiHandler::BusDisconnect(entityId); } void DiffuseGIExampleComponent::DisableGlobalIbl() { // disable Ibl by setting the empty cubemap const constexpr char* DiffuseAssetPath = "textures/default/default_iblglobalcm_ibldiffuse.dds.streamingimage"; const constexpr char* SpecularAssetPath = "textures/default/default_iblglobalcm_iblspecular.dds.streamingimage"; auto assertTraceLevel = AZ::RPI::AssetUtils::TraceLevel::Assert; AZ::Data::Asset diffuseImageAsset = AZ::RPI::AssetUtils::GetAssetByProductPath (DiffuseAssetPath, assertTraceLevel); AZ::Data::Asset specularImageAsset = AZ::RPI::AssetUtils::GetAssetByProductPath (SpecularAssetPath, assertTraceLevel); auto featureProcessor = m_scene->GetFeatureProcessor(); AZ_Assert(featureProcessor, "Unable to find ImageBasedLightFeatureProcessorInterface on scene."); featureProcessor->SetDiffuseImage(diffuseImageAsset); featureProcessor->SetSpecularImage(specularImageAsset); } void DiffuseGIExampleComponent::EnableDiffuseIbl() { AZ::Render::ImageBasedLightFeatureProcessorInterface* imageBaseLightFeatureProcessor = m_scene->GetFeatureProcessor(); AZ_Assert(imageBaseLightFeatureProcessor, "Unable to find ImageBasedLightFeatureProcessorInterface on scene."); imageBaseLightFeatureProcessor->SetDiffuseImage(m_diffuseImageAsset); imageBaseLightFeatureProcessor->SetExposure(m_diffuseIblExposure); } } // namespace AtomSampleViewer