MultiSceneExampleComponent.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AtomSampleViewerOptions.h>
  9. #include <MultiSceneExampleComponent.h>
  10. #include <Atom/Component/DebugCamera/CameraComponent.h>
  11. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  12. #include <Atom/RPI.Public/RenderPipeline.h>
  13. #include <Atom/RPI.Public/Scene.h>
  14. #include <Atom/RHI/RHISystemInterface.h>
  15. #include <Atom/RPI.Public/RPISystemInterface.h>
  16. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  17. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  18. #include <Automation/ScriptRunnerBus.h>
  19. #include <AzCore/Math/MatrixUtils.h>
  20. #include <AzCore/Component/Entity.h>
  21. #include <AzFramework/Components/TransformComponent.h>
  22. #include <AzFramework/Scene/SceneSystemInterface.h>
  23. #include <AzFramework/Entity/GameEntityContextComponent.h>
  24. #include <SampleComponentConfig.h>
  25. #include <SampleComponentManager.h>
  26. #include <EntityUtilityFunctions.h>
  27. #include <RHI/BasicRHIComponent.h>
  28. namespace AtomSampleViewer
  29. {
  30. using namespace AZ;
  31. //////////////////////////////////////////////////////////////////////////
  32. // SecondWindowedScene
  33. SecondWindowedScene::SecondWindowedScene(AZStd::string_view sceneName, MultiSceneExampleComponent* parent)
  34. {
  35. using namespace AZ;
  36. m_sceneName = sceneName;
  37. m_parent = parent;
  38. // Create a new EntityContext and AzFramework::Scene, and link them together via SetSceneForEntityContextId
  39. m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
  40. m_entityContext->InitContext();
  41. // Create the scene
  42. auto sceneSystem = AzFramework::SceneSystemInterface::Get();
  43. AZ_Assert(sceneSystem, "Unable to retrieve scene system.");
  44. Outcome<AZStd::shared_ptr<AzFramework::Scene>, AZStd::string> createSceneOutcome = sceneSystem->CreateScene(m_sceneName);
  45. AZ_Assert(createSceneOutcome, "%s", createSceneOutcome.GetError().data());
  46. m_frameworkScene = createSceneOutcome.TakeValue();
  47. m_frameworkScene->SetSubsystem<AzFramework::EntityContext::SceneStorageType>(m_entityContext.get());
  48. // Create a NativeWindow and WindowContext
  49. m_nativeWindow = AZStd::make_unique<AzFramework::NativeWindow>("Multi Scene: Second Window", AzFramework::WindowGeometry(0, 0, 1280, 720));
  50. m_nativeWindow->Activate();
  51. RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
  52. m_windowContext = AZStd::make_shared<RPI::WindowContext>();
  53. m_windowContext->Initialize(*device, m_nativeWindow->GetWindowHandle());
  54. // Create the RPI::Scene, add some feature processors
  55. RPI::SceneDescriptor sceneDesc;
  56. sceneDesc.m_nameId = AZ::Name("SecondScene");
  57. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimplePointLightFeatureProcessor");
  58. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimpleSpotLightFeatureProcessor");
  59. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::CapsuleLightFeatureProcessor");
  60. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DecalTextureArrayFeatureProcessor");
  61. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DirectionalLightFeatureProcessor");
  62. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DiskLightFeatureProcessor");
  63. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ImageBasedLightFeatureProcessor");
  64. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor");
  65. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor");
  66. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PostProcessFeatureProcessor");
  67. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::QuadLightFeatureProcessor");
  68. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ReflectionProbeFeatureProcessor");
  69. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SkyBoxFeatureProcessor");
  70. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor");
  71. sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ProjectedShadowFeatureProcessor");
  72. m_scene = RPI::Scene::CreateScene(sceneDesc);
  73. // Link our RPI::Scene to the AzFramework::Scene
  74. m_frameworkScene->SetSubsystem(m_scene);
  75. // Create a custom pipeline descriptor
  76. RPI::RenderPipelineDescriptor pipelineDesc;
  77. pipelineDesc.m_mainViewTagName = "MainCamera"; // Surface shaders render to the "MainCamera" tag
  78. pipelineDesc.m_name = "SecondPipeline"; // Sets the debug name for this pipeline
  79. pipelineDesc.m_rootPassTemplate = "MainPipeline"; // References a template in AtomSampleViewer\Passes\MainPipeline.pass
  80. pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 1;
  81. SampleComponentManagerRequestBus::BroadcastResult(
  82. pipelineDesc.m_renderSettings.m_multisampleState.m_samples,
  83. &SampleComponentManagerRequests::GetNumMSAASamples);
  84. pipelineDesc.m_allowModification = true;
  85. m_pipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext);
  86. m_scene->AddRenderPipeline(m_pipeline);
  87. m_scene->Activate();
  88. RPI::RPISystemInterface::Get()->RegisterScene(m_scene);
  89. // Create a camera entity, hook it up to the RenderPipeline
  90. m_cameraEntity = CreateEntity("WindowedSceneCamera", m_entityContext->GetContextId());
  91. Debug::CameraComponentConfig cameraConfig(m_windowContext);
  92. cameraConfig.m_fovY = Constants::HalfPi;
  93. m_cameraEntity->CreateComponent(azrtti_typeid<Debug::CameraComponent>())->SetConfiguration(cameraConfig);
  94. m_cameraEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
  95. m_cameraEntity->CreateComponent(azrtti_typeid<Debug::NoClipControllerComponent>());
  96. m_cameraEntity->Init();
  97. m_cameraEntity->Activate();
  98. m_pipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
  99. // Create a Depth of Field entity
  100. m_depthOfFieldEntity = CreateEntity("DepthOfField", m_entityContext->GetContextId());
  101. m_depthOfFieldEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
  102. // Get the FeatureProcessors
  103. m_meshFeatureProcessor = m_scene->GetFeatureProcessor<Render::MeshFeatureProcessorInterface>();
  104. m_skyBoxFeatureProcessor = m_scene->GetFeatureProcessor<Render::SkyBoxFeatureProcessorInterface>();
  105. m_pointLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::PointLightFeatureProcessorInterface>();
  106. m_diskLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
  107. m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
  108. m_reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<Render::ReflectionProbeFeatureProcessorInterface>();
  109. m_postProcessFeatureProcessor = m_scene->GetFeatureProcessor<Render::PostProcessFeatureProcessorInterface>();
  110. // Helper function to load meshes
  111. const auto LoadMesh = [this](const char* modelPath) -> Render::MeshFeatureProcessorInterface::MeshHandle
  112. {
  113. AZ_Assert(m_meshFeatureProcessor, "Cannot find mesh feature processor on scene");
  114. auto meshAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ModelAsset>(modelPath, RPI::AssetUtils::TraceLevel::Assert);
  115. auto materialAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::MaterialAsset>(DefaultPbrMaterialPath,
  116. RPI::AssetUtils::TraceLevel::Assert);
  117. auto material = AZ::RPI::Material::FindOrCreate(materialAsset);
  118. Render::MeshFeatureProcessorInterface::MeshHandle meshHandle = m_meshFeatureProcessor->AcquireMesh(Render::MeshHandleDescriptor{ meshAsset }, material);
  119. return meshHandle;
  120. };
  121. // Create the ShaderBalls
  122. {
  123. for (uint32_t i = 0u; i < ShaderBallCount; i++)
  124. {
  125. m_shaderBallMeshHandles.push_back(LoadMesh(ShaderBallModelFilePath));
  126. auto updateShaderBallTransform = [this, i](Data::Instance<RPI::Model> model)
  127. {
  128. const Aabb& aabb = model->GetModelAsset()->GetAabb();
  129. const Vector3 translation{ 0.0f, -aabb.GetMin().GetZ() * aznumeric_cast<float>(i), -aabb.GetMin().GetY() };
  130. const auto transform = Transform::CreateTranslation(translation);
  131. m_meshFeatureProcessor->SetTransform(m_shaderBallMeshHandles[i], transform);
  132. };
  133. // If the model is available already, set the tranform immediately, else utilize the EBus::Event feature
  134. Data::Instance<RPI::Model> shaderBallModel = m_meshFeatureProcessor->GetModel(m_shaderBallMeshHandles[i]);
  135. if (shaderBallModel)
  136. {
  137. updateShaderBallTransform(shaderBallModel);
  138. }
  139. else
  140. {
  141. m_shaderBallChangedHandles.push_back(ModelChangedHandler(updateShaderBallTransform));
  142. m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_shaderBallMeshHandles[i], m_shaderBallChangedHandles.back());
  143. }
  144. }
  145. }
  146. // Create the floor
  147. {
  148. const Vector3 nonUniformScale{ 24.f, 24.f, 1.0f };
  149. const Vector3 translation{ 0.f, 0.f, 0.0f };
  150. const auto transform = Transform::CreateTranslation(translation);
  151. m_floorMeshHandle = LoadMesh(CubeModelFilePath);
  152. m_meshFeatureProcessor->SetTransform(m_floorMeshHandle, transform, nonUniformScale);
  153. }
  154. // Create the Skybox
  155. {
  156. m_skyBoxFeatureProcessor->SetSkyboxMode(Render::SkyBoxMode::PhysicalSky);
  157. m_skyBoxFeatureProcessor->Enable(true);
  158. }
  159. // Create PointLight
  160. {
  161. m_pointLightHandle = m_pointLightFeatureProcessor->AcquireLight();
  162. const Vector3 pointLightPosition(4.0f, 0.0f, 5.0f);
  163. m_pointLightFeatureProcessor->SetPosition(m_pointLightHandle, pointLightPosition);
  164. Render::PhotometricValue rgbIntensity;
  165. rgbIntensity.SetEffectiveSolidAngle(Render::PhotometricValue::OmnidirectionalSteradians);
  166. m_pointLightFeatureProcessor->SetRgbIntensity(m_pointLightHandle, rgbIntensity.GetCombinedRgb<Render::PhotometricUnit::Candela>());
  167. m_pointLightFeatureProcessor->SetBulbRadius(m_pointLightHandle, 4.0f);
  168. }
  169. // Create DiskLight
  170. {
  171. m_diskLightHandle = m_diskLightFeatureProcessor->AcquireLight();
  172. const Vector3 diskLightPosition(3.0f, 0.0f, 4.0f);
  173. m_diskLightFeatureProcessor->SetPosition(m_diskLightHandle, diskLightPosition);
  174. Render::PhotometricValue rgbIntensity;
  175. m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(Color::CreateOne() * 2000.0f));
  176. const auto lightDir = Transform::CreateLookAt(
  177. diskLightPosition,
  178. Vector3::CreateZero());
  179. m_diskLightFeatureProcessor->SetDirection(m_diskLightHandle, lightDir.GetBasis(1));
  180. const float radius = sqrtf(2000.0f / 0.5f);
  181. m_diskLightFeatureProcessor->SetAttenuationRadius(m_diskLightHandle, radius);
  182. m_diskLightFeatureProcessor->SetShadowsEnabled(m_diskLightHandle, true);
  183. m_diskLightFeatureProcessor->SetShadowmapMaxResolution(m_diskLightHandle, Render::ShadowmapSize::Size512);
  184. m_diskLightFeatureProcessor->SetConeAngles(m_diskLightHandle, DegToRad(22.5f), DegToRad(27.5f));
  185. }
  186. // Create DirectionalLight
  187. {
  188. m_directionalLightHandle = m_directionalLightFeatureProcessor->AcquireLight();
  189. // Get the camera configuration
  190. {
  191. Camera::Configuration config;
  192. Camera::CameraRequestBus::EventResult(
  193. config,
  194. m_cameraEntity->GetId(),
  195. &Camera::CameraRequestBus::Events::GetCameraConfiguration);
  196. m_directionalLightFeatureProcessor->SetCameraConfiguration(
  197. m_directionalLightHandle,
  198. config);
  199. }
  200. // Camera Transform
  201. {
  202. Transform transform = Transform::CreateIdentity();
  203. TransformBus::EventResult(
  204. transform,
  205. m_cameraEntity->GetId(),
  206. &TransformBus::Events::GetWorldTM);
  207. m_directionalLightFeatureProcessor->SetCameraTransform(
  208. m_directionalLightHandle, transform);
  209. }
  210. Render::PhotometricColor<Render::PhotometricUnit::Lux> lightColor(Color::CreateOne() * 50.0f);
  211. m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, lightColor);
  212. const Vector3 helperPosition(-3.0f, 0.0f, 4.0f);
  213. const auto lightDir = Transform::CreateLookAt(
  214. helperPosition,
  215. Vector3::CreateZero());
  216. m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightDir.GetBasis(1));
  217. m_directionalLightFeatureProcessor->SetShadowmapSize(m_directionalLightHandle, Render::ShadowmapSize::Size512);
  218. m_directionalLightFeatureProcessor->SetCascadeCount(m_directionalLightHandle, 2);
  219. }
  220. // Create ReflectionProbe
  221. {
  222. const Vector3 probePosition{ -5.0f, 0.0f, 1.5f };
  223. const Transform probeTransform = Transform::CreateTranslation(probePosition);
  224. m_reflectionProbeHandle = m_reflectionProbeFeatureProcessor->AddReflectionProbe(probeTransform, true);
  225. m_reflectionProbeFeatureProcessor->ShowVisualization(m_reflectionProbeHandle, true);
  226. }
  227. // Enable Depth of Field
  228. {
  229. // Setup the depth of field
  230. auto* postProcessSettings = m_postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_depthOfFieldEntity->GetId());
  231. m_depthOfFieldSettings = postProcessSettings->GetOrCreateDepthOfFieldSettingsInterface();
  232. m_depthOfFieldSettings->SetQualityLevel(1u);
  233. m_depthOfFieldSettings->SetApertureF(0.5f);
  234. m_depthOfFieldSettings->SetEnableDebugColoring(false);
  235. m_depthOfFieldSettings->SetEnableAutoFocus(true);
  236. m_depthOfFieldSettings->SetAutoFocusScreenPosition(Vector2{ 0.5f, 0.5f });
  237. m_depthOfFieldSettings->SetAutoFocusSensitivity(1.0f);
  238. m_depthOfFieldSettings->SetAutoFocusSpeed(Render::DepthOfField::AutoFocusSpeedMax);
  239. m_depthOfFieldSettings->SetAutoFocusDelay(0.2f);
  240. m_depthOfFieldSettings->SetCameraEntityId(m_cameraEntity->GetId());
  241. m_depthOfFieldSettings->SetEnabled(true);
  242. m_depthOfFieldSettings->OnConfigChanged();
  243. m_depthOfFieldEntity->Init();
  244. m_depthOfFieldEntity->Activate();
  245. }
  246. // IBL
  247. m_defaultIbl.Init(m_scene.get());
  248. TickBus::Handler::BusConnect();
  249. AzFramework::WindowNotificationBus::Handler::BusConnect(m_nativeWindow->GetWindowHandle());
  250. }
  251. SecondWindowedScene::~SecondWindowedScene()
  252. {
  253. using namespace AZ;
  254. // Disconnect hte busses
  255. TickBus::Handler::BusDisconnect();
  256. AzFramework::WindowNotificationBus::Handler::BusDisconnect(m_nativeWindow->GetWindowHandle());
  257. m_defaultIbl.Reset();
  258. // Release all the light types
  259. m_pointLightFeatureProcessor->ReleaseLight(m_pointLightHandle);
  260. m_diskLightFeatureProcessor->ReleaseLight(m_diskLightHandle);
  261. m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
  262. // Release the probe
  263. m_reflectionProbeFeatureProcessor->RemoveReflectionProbe(m_reflectionProbeHandle);
  264. m_reflectionProbeHandle = {};
  265. // Release all meshes
  266. for (auto& shaderBallMeshHandle : m_shaderBallMeshHandles)
  267. {
  268. m_meshFeatureProcessor->ReleaseMesh(shaderBallMeshHandle);
  269. }
  270. m_meshFeatureProcessor->ReleaseMesh(m_floorMeshHandle);
  271. DestroyEntity(m_cameraEntity);
  272. DestroyEntity(m_depthOfFieldEntity);
  273. m_frameworkScene->UnsetSubsystem<RPI::Scene>();
  274. // Remove the scene
  275. m_scene->Deactivate();
  276. m_scene->RemoveRenderPipeline(m_pipeline->GetId());
  277. RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
  278. auto sceneSystem = AzFramework::SceneSystemInterface::Get();
  279. AZ_Assert(sceneSystem, "Scene system wasn't found to remove scene '%s' from.", m_sceneName.c_str());
  280. [[maybe_unused]] bool sceneRemovedSuccessfully = sceneSystem->RemoveScene(m_sceneName);
  281. AZ_Assert(sceneRemovedSuccessfully, "Unable to remove scene '%s'.", m_sceneName.c_str());
  282. m_scene = nullptr;
  283. m_windowContext->Shutdown();
  284. }
  285. void SecondWindowedScene::MoveCamera(bool enabled)
  286. {
  287. m_moveCamera = enabled;
  288. }
  289. // AZ::TickBus::Handler overrides ...
  290. void SecondWindowedScene::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  291. {
  292. using namespace AZ;
  293. // Move the camera a bit each frame
  294. // Note: view space in this scene is right-handed, Z-up, Y-forward
  295. const float dynamicOffsetScale = 4.0f;
  296. if (m_moveCamera)
  297. {
  298. m_dynamicCameraOffset = Vector3(dynamicOffsetScale * sinf(aznumeric_cast<float>(timePoint.GetSeconds())), 0.0f, 0.0f);
  299. }
  300. Vector3 cameraPosition = m_cameraOffset + m_dynamicCameraOffset;
  301. TransformBus::Event(m_cameraEntity->GetId(), &TransformBus::Events::SetLocalTranslation, cameraPosition);
  302. const auto cameraDirection = Transform::CreateLookAt(
  303. cameraPosition,
  304. Vector3::CreateZero());
  305. TransformBus::Event(m_cameraEntity->GetId(), &TransformBus::Events::SetLocalRotationQuaternion, cameraDirection.GetRotation());
  306. }
  307. void SecondWindowedScene::OnWindowClosed()
  308. {
  309. m_parent->OnChildWindowClosed();
  310. }
  311. AzFramework::NativeWindowHandle SecondWindowedScene::GetNativeWindowHandle()
  312. {
  313. if (m_nativeWindow)
  314. {
  315. return m_nativeWindow->GetWindowHandle();
  316. }
  317. else
  318. {
  319. return nullptr;
  320. }
  321. }
  322. //////////////////////////////////////////////////////////////////////////
  323. // MultiSceneExampleComponent
  324. void MultiSceneExampleComponent::Reflect(AZ::ReflectContext* context)
  325. {
  326. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  327. {
  328. serializeContext->Class<MultiSceneExampleComponent, AZ::Component>()
  329. ->Version(0)
  330. ;
  331. }
  332. }
  333. MultiSceneExampleComponent::MultiSceneExampleComponent()
  334. {
  335. }
  336. void MultiSceneExampleComponent::Activate()
  337. {
  338. using namespace AZ;
  339. // Setup primary camera controls
  340. Debug::CameraControllerRequestBus::Event(
  341. GetCameraEntityId(), &Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid<Debug::NoClipControllerComponent>());
  342. m_defaultIbl.PreloadAssets();
  343. // preload assets
  344. AZStd::vector<AssetCollectionAsyncLoader::AssetToLoadInfo> assetList = {
  345. { DefaultPbrMaterialPath, azrtti_typeid<RPI::MaterialAsset>() },
  346. { BunnyModelFilePath, azrtti_typeid<RPI::ModelAsset>() },
  347. { CubeModelFilePath, azrtti_typeid<RPI::ModelAsset>() },
  348. { ShaderBallModelFilePath, azrtti_typeid<RPI::ModelAsset>() }
  349. };
  350. PreloadAssets(assetList);
  351. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScriptWithTimeout, 120.0f);
  352. }
  353. void MultiSceneExampleComponent::OnAllAssetsReadyActivate()
  354. {
  355. using namespace AZ;
  356. // Setup Main Mesh Entity
  357. {
  358. auto materialAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::MaterialAsset>(DefaultPbrMaterialPath,
  359. RPI::AssetUtils::TraceLevel::Assert);
  360. auto material = AZ::RPI::Material::FindOrCreate(materialAsset);
  361. auto bunnyAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::ModelAsset>(BunnyModelFilePath,
  362. RPI::AssetUtils::TraceLevel::Assert);
  363. m_meshHandle = GetMeshFeatureProcessor()->AcquireMesh(Render::MeshHandleDescriptor{ bunnyAsset }, material);
  364. GetMeshFeatureProcessor()->SetTransform(m_meshHandle, Transform::CreateRotationZ(Constants::Pi));
  365. }
  366. // IBL
  367. {
  368. m_defaultIbl.Init(m_scene);
  369. }
  370. if (SupportsMultipleWindows())
  371. {
  372. OpenSecondSceneWindow();
  373. }
  374. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  375. TickBus::Handler::BusConnect();
  376. }
  377. void MultiSceneExampleComponent::Deactivate()
  378. {
  379. using namespace AZ;
  380. TickBus::Handler::BusDisconnect();
  381. Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &Debug::CameraControllerRequestBus::Events::Disable);
  382. m_defaultIbl.Reset();
  383. GetMeshFeatureProcessor()->ReleaseMesh(m_meshHandle);
  384. if (m_windowedScene)
  385. {
  386. m_windowedScene = nullptr;
  387. }
  388. }
  389. void MultiSceneExampleComponent::OnChildWindowClosed()
  390. {
  391. m_windowedScene = nullptr;
  392. }
  393. void MultiSceneExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  394. {
  395. if (ImGui::Begin("Multi Scene Panel"))
  396. {
  397. if (m_windowedScene)
  398. {
  399. static bool moveCamera = false;
  400. if (ImGui::Button("Close Second Scene Window"))
  401. {
  402. m_windowedScene = nullptr;
  403. moveCamera = false;
  404. }
  405. if (ImGui::Checkbox("Move camera##MultiSceneExample", &moveCamera))
  406. {
  407. if (m_windowedScene)
  408. {
  409. m_windowedScene->MoveCamera(moveCamera);
  410. }
  411. }
  412. }
  413. else
  414. {
  415. if (ImGui::Button("Open Second Scene Window"))
  416. {
  417. OpenSecondSceneWindow();
  418. }
  419. }
  420. }
  421. ImGui::End();
  422. }
  423. void MultiSceneExampleComponent::OpenSecondSceneWindow()
  424. {
  425. if (!m_windowedScene)
  426. {
  427. m_windowedScene = AZStd::make_unique<SecondWindowedScene>("SecondScene", this);
  428. }
  429. }
  430. } // namespace AtomSampleViewer