MSAA_RPI_ExampleComponent.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 <MSAA_RPI_ExampleComponent.h>
  13. #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
  14. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  15. #include <Atom/RPI.Public/View.h>
  16. #include <Atom/RPI.Public/Image/StreamingImage.h>
  17. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  18. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  19. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  20. #include <Utils/Utils.h>
  21. #include <SampleComponentManager.h>
  22. #include <SampleComponentConfig.h>
  23. #include <Atom/Bootstrap/DefaultWindowBus.h>
  24. #include <Automation/ScriptableImGui.h>
  25. #include <Automation/ScriptRunnerBus.h>
  26. #include <RHI/BasicRHIComponent.h>
  27. namespace AtomSampleViewer
  28. {
  29. static const char* GetPipelineName(int numSamples)
  30. {
  31. switch (numSamples)
  32. {
  33. case 1:
  34. return "No_MSAA_RPI_Pipeline";
  35. case 2:
  36. return "MSAA_2x_RPI_Pipeline";
  37. case 4:
  38. return "MSAA_4x_RPI_Pipeline";
  39. case 8:
  40. return "MSAA_8x_RPI_Pipeline";
  41. }
  42. AZ_Warning("MSAA_RPI_ExampleComponent", false, "Unsupported number of samples, defaulting to 1");
  43. return "No_MSAA_RPI_Pipeline";
  44. }
  45. void MSAA_RPI_ExampleComponent::Reflect(AZ::ReflectContext* context)
  46. {
  47. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  48. {
  49. serializeContext->Class < MSAA_RPI_ExampleComponent, AZ::Component>()
  50. ->Version(0)
  51. ;
  52. }
  53. }
  54. void MSAA_RPI_ExampleComponent::Activate()
  55. {
  56. m_imguiSidebar.Activate();
  57. AZ::TickBus::Handler::BusConnect();
  58. ExampleComponentRequestBus::Handler::BusConnect(GetEntityId());
  59. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusConnect();
  60. ActivateMSAAPipeline();
  61. EnableArcBallCameraController();
  62. ActivateModel();
  63. ActivateIbl();
  64. }
  65. void MSAA_RPI_ExampleComponent::Deactivate()
  66. {
  67. DeactivateIbl();
  68. DeactivateModel();
  69. DisableArcBallCameraController();
  70. DeactivateMSAAPipeline();
  71. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusDisconnect();
  72. ExampleComponentRequestBus::Handler::BusDisconnect();
  73. AZ::TickBus::Handler::BusDisconnect();
  74. m_imguiSidebar.Deactivate();
  75. }
  76. void MSAA_RPI_ExampleComponent::EnableArcBallCameraController()
  77. {
  78. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable,
  79. azrtti_typeid<AZ::Debug::ArcBallControllerComponent>());
  80. }
  81. void MSAA_RPI_ExampleComponent::DisableArcBallCameraController()
  82. {
  83. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  84. }
  85. void MSAA_RPI_ExampleComponent::OnModelReady(AZ::Data::Instance<AZ::RPI::Model> model)
  86. {
  87. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = model->GetModelAsset();
  88. m_meshChangedHandler.Disconnect();
  89. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  90. }
  91. void MSAA_RPI_ExampleComponent::ActivateMSAAPipeline()
  92. {
  93. CreateMSAAPipeline(m_numSamples);
  94. AZ::RPI::ScenePtr defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
  95. m_originalPipeline = defaultScene->GetDefaultRenderPipeline();
  96. defaultScene->AddRenderPipeline(m_msaaPipeline);
  97. m_msaaPipeline->SetDefaultView(m_originalPipeline->GetDefaultView());
  98. defaultScene->RemoveRenderPipeline(m_originalPipeline->GetId());
  99. // Create an ImGuiActiveContextScope to ensure the ImGui context on the new pipeline's ImGui pass is activated.
  100. m_imguiScope = AZ::Render::ImGuiActiveContextScope::FromPass(AZ::RPI::PassHierarchyFilter({ m_msaaPipeline->GetId().GetCStr(), "ImGuiPass" }));
  101. }
  102. void MSAA_RPI_ExampleComponent::DeactivateMSAAPipeline()
  103. {
  104. m_imguiScope = {}; // restores previous ImGui context.
  105. AZ::RPI::ScenePtr defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
  106. defaultScene->AddRenderPipeline(m_originalPipeline);
  107. AZ::RPI::RenderPipelineDescriptor pipelineDesc;
  108. defaultScene->RemoveRenderPipeline(m_msaaPipeline->GetId());
  109. DestroyMSAAPipeline();
  110. }
  111. void MSAA_RPI_ExampleComponent::CreateMSAAPipeline(int numSamples)
  112. {
  113. AZ::RPI::RenderPipelineDescriptor pipelineDesc;
  114. pipelineDesc.m_mainViewTagName = "MainCamera";
  115. pipelineDesc.m_name = "MSAA";
  116. pipelineDesc.m_rootPassTemplate = GetPipelineName(numSamples);
  117. m_msaaPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext);
  118. }
  119. void MSAA_RPI_ExampleComponent::ResetCamera()
  120. {
  121. const float pitch = -AZ::Constants::QuarterPi - 0.025f;
  122. const float heading = AZ::Constants::QuarterPi - 0.05f;
  123. const float distance = 3.0f;
  124. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetCenter, AZ::Vector3(0.f));
  125. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetDistance, distance);
  126. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetMaxDistance, 50.0f);
  127. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetPitch, pitch);
  128. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetHeading, heading);
  129. }
  130. void MSAA_RPI_ExampleComponent::DefaultWindowCreated()
  131. {
  132. AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &AZ::Render::Bootstrap::DefaultWindowBus::Events::GetDefaultWindowContext);
  133. }
  134. void MSAA_RPI_ExampleComponent::DestroyMSAAPipeline()
  135. {
  136. m_msaaPipeline = nullptr;
  137. }
  138. AZ::Data::Asset<AZ::RPI::MaterialAsset> MSAA_RPI_ExampleComponent::GetMaterialAsset()
  139. {
  140. AZ::RPI::AssetUtils::TraceLevel traceLevel = AZ::RPI::AssetUtils::TraceLevel::Assert;
  141. return AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>(DefaultPbrMaterialPath, traceLevel);
  142. }
  143. AZ::Data::Asset<AZ::RPI::ModelAsset> MSAA_RPI_ExampleComponent::GetModelAsset()
  144. {
  145. AZ::RPI::AssetUtils::TraceLevel traceLevel = AZ::RPI::AssetUtils::TraceLevel::Assert;
  146. switch (m_modelType)
  147. {
  148. case 0:
  149. return AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cylinder.azmodel", traceLevel);
  150. case 1:
  151. return AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cube.azmodel", traceLevel);
  152. case 2:
  153. return AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/shaderball_simple.azmodel", traceLevel);
  154. }
  155. AZ_Warning("MSAA_RPI_ExampleComponent", false, "Unsupported model type");
  156. return AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cylinder.azmodel", traceLevel);
  157. }
  158. void MSAA_RPI_ExampleComponent::ActivateModel()
  159. {
  160. m_meshHandle = GetMeshFeatureProcessor()->AcquireMesh(GetModelAsset(), AZ::RPI::Material::FindOrCreate(GetMaterialAsset()));
  161. GetMeshFeatureProcessor()->SetTransform(m_meshHandle, AZ::Transform::CreateIdentity());
  162. AZ::Data::Instance<AZ::RPI::Model> model = GetMeshFeatureProcessor()->GetModel(m_meshHandle);
  163. if (model)
  164. {
  165. OnModelReady(model);
  166. }
  167. else
  168. {
  169. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScript);
  170. GetMeshFeatureProcessor()->ConnectModelChangeEventHandler(m_meshHandle, m_meshChangedHandler);
  171. }
  172. }
  173. void MSAA_RPI_ExampleComponent::DeactivateModel()
  174. {
  175. GetMeshFeatureProcessor()->ReleaseMesh(m_meshHandle);
  176. }
  177. void MSAA_RPI_ExampleComponent::ActivateIbl()
  178. {
  179. m_defaultIbl.Init(AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get());
  180. // reduce the exposure so the model isn't overly bright
  181. m_defaultIbl.SetExposure(-0.5f);
  182. }
  183. void MSAA_RPI_ExampleComponent::DeactivateIbl()
  184. {
  185. m_defaultIbl.Reset();
  186. }
  187. void MSAA_RPI_ExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  188. {
  189. DrawSidebar();
  190. }
  191. void MSAA_RPI_ExampleComponent::DrawSidebar()
  192. {
  193. if (!m_imguiSidebar.Begin())
  194. {
  195. return;
  196. }
  197. bool refresh = false;
  198. refresh = DrawSidebarModeChooser(refresh);
  199. refresh = DrawSideBarModelChooser(refresh);
  200. m_imguiSidebar.End();
  201. if (refresh)
  202. {
  203. // Note that the model's have some multisample information embedded into their pipeline state, so delete and recreate the model
  204. DeactivateModel();
  205. DeactivateMSAAPipeline();
  206. ActivateMSAAPipeline();
  207. ActivateModel();
  208. }
  209. }
  210. bool MSAA_RPI_ExampleComponent::DrawSidebarModeChooser(bool refresh)
  211. {
  212. ScriptableImGui::ScopedNameContext context{ "Mode" };
  213. ImGui::Text("Num Samples");
  214. refresh |= ScriptableImGui::RadioButton("MSAA None", &m_numSamples, 1);
  215. refresh |= ScriptableImGui::RadioButton("MSAA 2x", &m_numSamples, 2);
  216. refresh |= ScriptableImGui::RadioButton("MSAA 4x", &m_numSamples, 4);
  217. refresh |= ScriptableImGui::RadioButton("MSAA 8x", &m_numSamples, 8);
  218. return refresh;
  219. }
  220. bool MSAA_RPI_ExampleComponent::DrawSideBarModelChooser(bool refresh)
  221. {
  222. ScriptableImGui::ScopedNameContext context{ "Model" };
  223. ImGui::NewLine();
  224. ImGui::Text("Model");
  225. refresh |= ScriptableImGui::RadioButton("Cylinder", &m_modelType, 0);
  226. refresh |= ScriptableImGui::RadioButton("Cube", &m_modelType, 1);
  227. refresh |= ScriptableImGui::RadioButton("ShaderBall", &m_modelType, 2);
  228. return refresh;
  229. }
  230. }