SsaoExampleComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. #include <SsaoExampleComponent.h>
  13. #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
  14. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  15. #include <Atom/Component/DebugCamera/NoClipControllerBus.h>
  16. #include <Atom/RPI.Public/View.h>
  17. #include <Atom/RPI.Public/Image/StreamingImage.h>
  18. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  19. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  20. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  21. #include <Utils/Utils.h>
  22. #include <EntityUtilityFunctions.h>
  23. #include <SampleComponentManager.h>
  24. #include <SampleComponentConfig.h>
  25. #include <Atom/Bootstrap/DefaultWindowBus.h>
  26. #include <Automation/ScriptableImGui.h>
  27. #include <Automation/ScriptRunnerBus.h>
  28. #include <AzFramework/Components/TransformComponent.h>
  29. #include <RHI/BasicRHIComponent.h>
  30. namespace AtomSampleViewer
  31. {
  32. using namespace AZ;
  33. using namespace AZ::Render;
  34. using namespace AZ::RPI;
  35. void SsaoExampleComponent::Reflect(AZ::ReflectContext* context)
  36. {
  37. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  38. {
  39. serializeContext->Class<SsaoExampleComponent, AZ::Component>()
  40. ->Version(0)
  41. ;
  42. }
  43. }
  44. // --- Activate/Deactivate ---
  45. void SsaoExampleComponent::Activate()
  46. {
  47. RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
  48. m_rayTracingEnabled = device->GetFeatures().m_rayTracing;
  49. AZ::TickBus::Handler::BusConnect();
  50. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusConnect();
  51. ActivateSsaoPipeline();
  52. ActivateCamera();
  53. ActivateModel();
  54. ActivatePostProcessSettings();
  55. m_imguiSidebar.Activate();
  56. SwitchAOType();
  57. }
  58. void SsaoExampleComponent::Deactivate()
  59. {
  60. m_imguiSidebar.Deactivate();
  61. DectivatePostProcessSettings();
  62. DeactivateModel();
  63. DeactivateCamera();
  64. DeactivateSsaoPipeline();
  65. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusDisconnect();
  66. AZ::TickBus::Handler::BusDisconnect();
  67. }
  68. // --- World Model ---
  69. void SsaoExampleComponent::OnModelReady(AZ::Data::Instance<AZ::RPI::Model> model)
  70. {
  71. m_worldModelAssetLoaded = true;
  72. }
  73. void SsaoExampleComponent::ActivateModel()
  74. {
  75. const char* modelPath = "Objects/Bistro/Bistro_Research_Exterior.azmodel";
  76. // Get Model and Material asset
  77. Data::Asset<RPI::ModelAsset> modelAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ModelAsset>(modelPath, RPI::AssetUtils::TraceLevel::Assert);
  78. Data::Asset<RPI::MaterialAsset> materialAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::MaterialAsset>(DefaultPbrMaterialPath, RPI::AssetUtils::TraceLevel::Assert);
  79. // Create Mesh and Model
  80. MeshFeatureProcessorInterface* meshFeatureProcessor = GetMeshFeatureProcessor();
  81. m_meshHandle = meshFeatureProcessor->AcquireMesh(modelAsset, RPI::Material::FindOrCreate(materialAsset));
  82. meshFeatureProcessor->SetTransform(m_meshHandle, Transform::CreateIdentity());
  83. Data::Instance<RPI::Model> model = meshFeatureProcessor->GetModel(m_meshHandle);
  84. // Async Model loading
  85. if (model)
  86. {
  87. OnModelReady(model);
  88. }
  89. else
  90. {
  91. meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_meshChangedHandler);
  92. }
  93. }
  94. void SsaoExampleComponent::DeactivateModel()
  95. {
  96. GetMeshFeatureProcessor()->ReleaseMesh(m_meshHandle);
  97. }
  98. // --- SSAO Pipeline ---
  99. void SsaoExampleComponent::CreateSsaoPipeline()
  100. {
  101. AZ::RPI::RenderPipelineDescriptor ssaoPipelineDesc;
  102. ssaoPipelineDesc.m_mainViewTagName = "MainCamera";
  103. ssaoPipelineDesc.m_name = "SsaoPipeline";
  104. ssaoPipelineDesc.m_rootPassTemplate = "SsaoPipeline";
  105. m_ssaoPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(ssaoPipelineDesc, *m_windowContext);
  106. if (m_rayTracingEnabled)
  107. {
  108. RPI::PassHierarchyFilter passFilter({ssaoPipelineDesc.m_name, "RayTracingAmbientOcclusionPass"});
  109. const AZStd::vector<RPI::Pass*>& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter);
  110. if (!passes.empty())
  111. {
  112. m_RTAOPass = azrtti_cast<Render::RayTracingAmbientOcclusionPass*>(passes.front());
  113. AZ_Assert(m_RTAOPass, "Couldn't find the RayTracingAmbientOcclusionPass from the SsaoPipeline");
  114. }
  115. }
  116. else
  117. {
  118. m_aoType = AmbientOcclusionType::SSAO;
  119. }
  120. RPI::PassHierarchyFilter passFilter({ssaoPipelineDesc.m_name, "SelectorPass"});
  121. const AZStd::vector<RPI::Pass*>& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter);
  122. if (!passes.empty())
  123. {
  124. m_selector = azrtti_cast<RPI::SelectorPass*>(passes.front());
  125. AZ_Assert(m_selector, "Couldn't find the SelectorPass from the SsaoPipeline");
  126. }
  127. }
  128. void SsaoExampleComponent::DestroySsaoPipeline()
  129. {
  130. m_ssaoPipeline = nullptr;
  131. }
  132. void SsaoExampleComponent::ActivateSsaoPipeline()
  133. {
  134. CreateSsaoPipeline();
  135. AZ::RPI::ScenePtr defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
  136. m_originalPipeline = defaultScene->GetDefaultRenderPipeline();
  137. defaultScene->AddRenderPipeline(m_ssaoPipeline);
  138. m_ssaoPipeline->SetDefaultView(m_originalPipeline->GetDefaultView());
  139. defaultScene->RemoveRenderPipeline(m_originalPipeline->GetId());
  140. // Create an ImGuiActiveContextScope to ensure the ImGui context on the new pipeline's ImGui pass is activated.
  141. m_imguiScope = AZ::Render::ImGuiActiveContextScope::FromPass(AZ::RPI::PassHierarchyFilter({ m_ssaoPipeline->GetId().GetCStr(), "ImGuiPass" }));
  142. }
  143. void SsaoExampleComponent::DeactivateSsaoPipeline()
  144. {
  145. m_imguiScope = {}; // restores previous ImGui context.
  146. AZ::RPI::ScenePtr defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
  147. defaultScene->AddRenderPipeline(m_originalPipeline);
  148. AZ::RPI::RenderPipelineDescriptor pipelineDesc;
  149. defaultScene->RemoveRenderPipeline(m_ssaoPipeline->GetId());
  150. DestroySsaoPipeline();
  151. }
  152. // --- SSAO Settings ---
  153. void SsaoExampleComponent::ActivatePostProcessSettings()
  154. {
  155. using namespace AZ;
  156. m_ssaoEntity = CreateEntity("SSAO", GetEntityContextId());
  157. Component* transformComponent = nullptr;
  158. ComponentDescriptorBus::EventResult(
  159. transformComponent,
  160. azrtti_typeid<AzFramework::TransformComponent>(),
  161. &ComponentDescriptorBus::Events::CreateComponent);
  162. m_ssaoEntity->AddComponent(transformComponent);
  163. RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get();
  164. m_postProcessFeatureProcessor = scene->GetFeatureProcessor<Render::PostProcessFeatureProcessorInterface>();
  165. auto* postProcessSettings = m_postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_ssaoEntity->GetId());
  166. m_ssaoSettings = postProcessSettings->GetOrCreateSsaoSettingsInterface();
  167. m_ssaoEntity->Activate();
  168. AZ::EntityBus::MultiHandler::BusConnect(m_ssaoEntity->GetId());
  169. }
  170. void SsaoExampleComponent::DectivatePostProcessSettings()
  171. {
  172. AZ::EntityBus::MultiHandler::BusDisconnect();
  173. if (m_ssaoEntity)
  174. {
  175. DestroyEntity(m_ssaoEntity, GetEntityContextId());
  176. }
  177. }
  178. // --- IMGUI ---
  179. void SsaoExampleComponent::DrawImGUI()
  180. {
  181. if (!m_worldModelAssetLoaded)
  182. {
  183. const ImGuiWindowFlags windowFlags =
  184. ImGuiWindowFlags_NoCollapse |
  185. ImGuiWindowFlags_NoResize |
  186. ImGuiWindowFlags_NoMove;
  187. if (ImGui::Begin("Asset", nullptr, windowFlags))
  188. {
  189. ImGui::Text("World Model: %s", m_worldModelAssetLoaded ? "Loaded" : "Loading...");
  190. ImGui::End();
  191. }
  192. return;
  193. }
  194. if (!m_imguiSidebar.Begin())
  195. {
  196. return;
  197. }
  198. DrawSidebar();
  199. m_imguiSidebar.End();
  200. }
  201. void SsaoExampleComponent::DrawSidebar()
  202. {
  203. ScriptableImGui::ScopedNameContext context{ "SSAO" };
  204. // only enable selecting AO type if ray tracing is enabled
  205. if (m_rayTracingEnabled)
  206. {
  207. ImGui::Text("Ambient Occlusion");
  208. bool aoTypeChanged = false;
  209. aoTypeChanged = ScriptableImGui::RadioButton("Screen space AO", &m_aoType, AmbientOcclusionType::SSAO);
  210. aoTypeChanged = aoTypeChanged | ScriptableImGui::RadioButton("Ray tracing AO", &m_aoType, AmbientOcclusionType::RTAO);
  211. if (aoTypeChanged)
  212. {
  213. SwitchAOType();
  214. }
  215. ImGui::NewLine();
  216. }
  217. if (m_aoType == AmbientOcclusionType::SSAO)
  218. {
  219. ImGui::Text("SSAO Params");
  220. bool enabled = m_ssaoSettings->GetEnabled();
  221. if (ScriptableImGui::Checkbox("Enable", &enabled))
  222. {
  223. m_ssaoSettings->SetEnabled(enabled);
  224. m_ssaoSettings->OnConfigChanged();
  225. }
  226. float strength = m_ssaoSettings->GetStrength();
  227. if (ScriptableImGui::SliderFloat("SSAO Strength", &strength, 0.0f, 2.0f))
  228. {
  229. m_ssaoSettings->SetStrength(strength);
  230. m_ssaoSettings->OnConfigChanged();
  231. }
  232. bool blurEnabled = m_ssaoSettings->GetEnableBlur();
  233. if (ScriptableImGui::Checkbox("Enable Blur", &blurEnabled))
  234. {
  235. m_ssaoSettings->SetEnableBlur(blurEnabled);
  236. m_ssaoSettings->OnConfigChanged();
  237. }
  238. float blurConstFalloff = m_ssaoSettings->GetBlurConstFalloff();
  239. if (ScriptableImGui::SliderFloat("Blur Strength", &blurConstFalloff, 0.0f, 0.95f))
  240. {
  241. m_ssaoSettings->SetBlurConstFalloff(blurConstFalloff);
  242. m_ssaoSettings->OnConfigChanged();
  243. }
  244. float blurDepthFalloffStrength = m_ssaoSettings->GetBlurDepthFalloffStrength();
  245. if (ScriptableImGui::SliderFloat("Blur Sharpness", &blurDepthFalloffStrength, 0.0f, 400.0f))
  246. {
  247. m_ssaoSettings->SetBlurDepthFalloffStrength(blurDepthFalloffStrength);
  248. m_ssaoSettings->OnConfigChanged();
  249. }
  250. float blurDepthFalloffThreshold = m_ssaoSettings->GetBlurDepthFalloffThreshold();
  251. if (ScriptableImGui::SliderFloat("Blur Edge Threshold", &blurDepthFalloffThreshold, 0.0f, 1.0f))
  252. {
  253. m_ssaoSettings->SetBlurDepthFalloffThreshold(blurDepthFalloffThreshold);
  254. m_ssaoSettings->OnConfigChanged();
  255. }
  256. bool downsampleEnabled = m_ssaoSettings->GetEnableDownsample();
  257. if (ScriptableImGui::Checkbox("Enable Downsample", &downsampleEnabled))
  258. {
  259. m_ssaoSettings->SetEnableDownsample(downsampleEnabled);
  260. m_ssaoSettings->OnConfigChanged();
  261. }
  262. }
  263. else if (m_aoType == AmbientOcclusionType::RTAO)
  264. {
  265. ImGui::Text("RTAO Params");
  266. float rayNear = m_RTAOPass->GetRayExtentMin();
  267. if (ScriptableImGui::SliderFloat("Ray near distance", &rayNear, 0.0f, 0.5f))
  268. {
  269. m_RTAOPass->SetRayExtentMin(rayNear);
  270. }
  271. float rayFar = m_RTAOPass->GetRayExtentMax();
  272. if (ScriptableImGui::SliderFloat("Ray far distance", &rayFar, 0.0f, 1.0f))
  273. {
  274. if (rayFar < rayNear)
  275. {
  276. rayFar = rayNear + 0.1f;
  277. }
  278. m_RTAOPass->SetRayExtentMax(rayFar);
  279. }
  280. int32_t maxNumberRays = m_RTAOPass->GetRayNumberPerPixel();
  281. if (ScriptableImGui::SliderInt("Number of rays", &maxNumberRays, 1, 30))
  282. {
  283. m_RTAOPass->SetRayNumberPerPixel(maxNumberRays);
  284. }
  285. }
  286. }
  287. void SsaoExampleComponent::SwitchAOType()
  288. {
  289. if (m_aoType == AmbientOcclusionType::SSAO)
  290. {
  291. m_selector->Connect(1, 0);
  292. }
  293. else if (m_aoType == AmbientOcclusionType::RTAO)
  294. {
  295. m_selector->Connect(0, 0);
  296. }
  297. m_ssaoSettings->SetEnabled(m_aoType == AmbientOcclusionType::SSAO);
  298. m_ssaoSettings->OnConfigChanged();
  299. if (m_RTAOPass)
  300. {
  301. m_RTAOPass->SetEnabled(m_aoType == AmbientOcclusionType::RTAO);
  302. }
  303. }
  304. // --- Camera ---
  305. void SsaoExampleComponent::ActivateCamera()
  306. {
  307. AZ::Debug::CameraControllerRequestBus::Event(
  308. GetCameraEntityId(),
  309. &AZ::Debug::CameraControllerRequestBus::Events::Enable,
  310. azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  311. Camera::CameraRequestBus::EventResult(
  312. m_originalFarClipDistance,
  313. GetCameraEntityId(),
  314. &Camera::CameraRequestBus::Events::GetFarClipDistance);
  315. const float FarClipDistance = 16384.0f;
  316. Camera::CameraRequestBus::Event(
  317. GetCameraEntityId(),
  318. &Camera::CameraRequestBus::Events::SetFarClipDistance,
  319. FarClipDistance);
  320. MoveCameraToStartPosition();
  321. }
  322. void SsaoExampleComponent::DeactivateCamera()
  323. {
  324. Camera::CameraRequestBus::Event(
  325. GetCameraEntityId(),
  326. &Camera::CameraRequestBus::Events::SetFarClipDistance,
  327. m_originalFarClipDistance);
  328. AZ::Debug::CameraControllerRequestBus::Event(
  329. GetCameraEntityId(),
  330. &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  331. }
  332. void SsaoExampleComponent::MoveCameraToStartPosition()
  333. {
  334. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, 200.0f);
  335. Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &Debug::NoClipControllerRequestBus::Events::SetPosition, Vector3(11.475539, -0.477937, 4.178957));
  336. Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &Debug::NoClipControllerRequestBus::Events::SetHeading, DegToRad(96.925217));
  337. Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &Debug::NoClipControllerRequestBus::Events::SetPitch, DegToRad(-11.936623));
  338. }
  339. // --- Events ---
  340. void SsaoExampleComponent::DefaultWindowCreated()
  341. {
  342. AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &AZ::Render::Bootstrap::DefaultWindowBus::Events::GetDefaultWindowContext);
  343. }
  344. void SsaoExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  345. {
  346. DrawImGUI();
  347. }
  348. void SsaoExampleComponent::OnEntityDestruction(const AZ::EntityId& entityId)
  349. {
  350. AZ::EntityBus::MultiHandler::BusDisconnect(entityId);
  351. if (m_ssaoEntity && m_ssaoEntity->GetId() == entityId)
  352. {
  353. m_postProcessFeatureProcessor->RemoveSettingsInterface(m_ssaoEntity->GetId());
  354. m_ssaoEntity = nullptr;
  355. }
  356. else
  357. {
  358. AZ_Assert(false, "unexpected entity destruction is signaled.");
  359. }
  360. }
  361. }