HighInstanceExampleComponent.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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 <Performance/HighInstanceExampleComponent.h>
  9. #include <SampleComponentManager.h>
  10. #include <SampleComponentConfig.h>
  11. #include <Atom/Component/DebugCamera/NoClipControllerBus.h>
  12. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  13. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  14. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  15. #include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
  16. #include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
  17. #include <Automation/ScriptRunnerBus.h>
  18. #include <AzCore/Serialization/SerializeContext.h>
  19. #include <AzFramework/Windowing/WindowBus.h>
  20. #include <RHI/BasicRHIComponent.h>
  21. AZ_DECLARE_BUDGET(AtomSampleViewer);
  22. namespace AtomSampleViewer
  23. {
  24. using namespace AZ;
  25. void HighInstanceTestComponent::Reflect(AZ::ReflectContext* context)
  26. {
  27. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  28. {
  29. serializeContext->Class<HighInstanceTestComponent, EntityLatticeTestComponent>()
  30. ->Version(0)
  31. ;
  32. }
  33. }
  34. HighInstanceTestComponent::HighInstanceTestComponent()
  35. : m_materialBrowser("@user@/HighInstanceTestComponent/material_browser.xml")
  36. , m_modelBrowser("@user@/HighInstanceTestComponent/model_browser.xml")
  37. , m_imguiSidebar("@user@/HighInstanceTestComponent/sidebar.xml")
  38. {
  39. m_materialBrowser.SetFilter([](const AZ::Data::AssetInfo& assetInfo)
  40. {
  41. return assetInfo.m_assetType == azrtti_typeid<AZ::RPI::MaterialAsset>();
  42. });
  43. m_modelBrowser.SetFilter([](const AZ::Data::AssetInfo& assetInfo)
  44. {
  45. return assetInfo.m_assetType == azrtti_typeid<AZ::RPI::ModelAsset>();
  46. });
  47. // Only use a diffuse white material so light colors are easily visible.
  48. const AZStd::vector<AZStd::string> materialAllowlist =
  49. {
  50. "materials/presets/macbeth/19_white_9-5_0-05d.azmaterial",
  51. };
  52. m_materialBrowser.SetDefaultPinnedAssets(materialAllowlist);
  53. m_pinnedMaterialCount = static_cast<uint32_t>(m_materialBrowser.GetPinnedAssets().size());
  54. m_expandedModelList =
  55. {
  56. "materialeditor/viewportmodels/cone.azmodel",
  57. "materialeditor/viewportmodels/cube.azmodel",
  58. "materialeditor/viewportmodels/cylinder.azmodel",
  59. "materialeditor/viewportmodels/platonicsphere.azmodel",
  60. "materialeditor/viewportmodels/polarsphere.azmodel",
  61. "materialeditor/viewportmodels/quadsphere.azmodel",
  62. "materialeditor/viewportmodels/torus.azmodel",
  63. "objects/cube.azmodel",
  64. "objects/cylinder.azmodel",
  65. };
  66. m_simpleModelList =
  67. {
  68. "objects/cube.azmodel"
  69. };
  70. m_modelBrowser.SetDefaultPinnedAssets(m_simpleModelList);
  71. }
  72. void HighInstanceTestComponent::Activate()
  73. {
  74. BuildDiskLightParameters();
  75. m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
  76. m_diskLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
  77. AZ::TickBus::Handler::BusConnect();
  78. m_imguiSidebar.Activate();
  79. m_imguiSidebar.SetHideSidebar(true);
  80. m_materialBrowser.Activate();
  81. m_modelBrowser.Activate();
  82. m_materialBrowser.ResetPinnedAssetsToDefault();
  83. m_modelBrowser.ResetPinnedAssetsToDefault();
  84. SetLatticeDimensions(
  85. m_testParameters.m_latticeSize[0],
  86. m_testParameters.m_latticeSize[1],
  87. m_testParameters.m_latticeSize[2]);
  88. SetLatticeSpacing(
  89. m_testParameters.m_latticeSpacing[0],
  90. m_testParameters.m_latticeSpacing[1],
  91. m_testParameters.m_latticeSpacing[2]);
  92. SetLatticeEntityScale(m_testParameters.m_entityScale);
  93. Base::Activate();
  94. AzFramework::NativeWindowHandle windowHandle = nullptr;
  95. AzFramework::WindowSystemRequestBus::BroadcastResult(
  96. windowHandle,
  97. &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  98. AzFramework::WindowRequestBus::EventResult(
  99. m_preActivateVSyncInterval,
  100. windowHandle,
  101. &AzFramework::WindowRequestBus::Events::GetSyncInterval);
  102. AzFramework::WindowRequestBus::Event(
  103. windowHandle,
  104. &AzFramework::WindowRequestBus::Events::SetSyncInterval,
  105. 0);
  106. SaveCameraConfiguration();
  107. ResetNoClipController();
  108. SetIBLExposure(m_testParameters.m_iblExposure);
  109. }
  110. void HighInstanceTestComponent::Deactivate()
  111. {
  112. DestroyLights();
  113. RestoreCameraConfiguration();
  114. AzFramework::NativeWindowHandle windowHandle = nullptr;
  115. AzFramework::WindowSystemRequestBus::BroadcastResult(
  116. windowHandle,
  117. &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  118. AzFramework::WindowRequestBus::Event(
  119. windowHandle,
  120. &AzFramework::WindowRequestBus::Events::SetSyncInterval,
  121. m_preActivateVSyncInterval);
  122. m_materialBrowser.Deactivate();
  123. m_modelBrowser.Deactivate();
  124. AZ::TickBus::Handler::BusDisconnect();
  125. m_imguiSidebar.Deactivate();
  126. Base::Deactivate();
  127. }
  128. void HighInstanceTestComponent::PrepareCreateLatticeInstances(uint32_t instanceCount)
  129. {
  130. m_modelInstanceData.reserve(instanceCount);
  131. DestroyLights();
  132. }
  133. void HighInstanceTestComponent::CreateLatticeInstance(const AZ::Transform& transform)
  134. {
  135. m_modelInstanceData.emplace_back<ModelInstanceData>({});
  136. ModelInstanceData& data = m_modelInstanceData.back();
  137. data.m_modelAssetId = GetRandomModelId();
  138. data.m_materialAssetId = GetRandomMaterialId();
  139. data.m_transform = transform;
  140. }
  141. void HighInstanceTestComponent::FinalizeLatticeInstances()
  142. {
  143. AZStd::set<AZ::Data::AssetId> assetIds;
  144. for (ModelInstanceData& instanceData : m_modelInstanceData)
  145. {
  146. if (instanceData.m_materialAssetId.IsValid())
  147. {
  148. assetIds.insert(instanceData.m_materialAssetId);
  149. }
  150. if (instanceData.m_modelAssetId.IsValid())
  151. {
  152. assetIds.insert(instanceData.m_modelAssetId);
  153. }
  154. }
  155. AZStd::vector<AZ::AssetCollectionAsyncLoader::AssetToLoadInfo> assetList;
  156. for (auto& assetId : assetIds)
  157. {
  158. AZ::Data::AssetInfo assetInfo;
  159. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId);
  160. if (assetInfo.m_assetId.IsValid())
  161. {
  162. AZ::AssetCollectionAsyncLoader::AssetToLoadInfo info;
  163. info.m_assetPath = assetInfo.m_relativePath;
  164. info.m_assetType = assetInfo.m_assetType;
  165. assetList.push_back(info);
  166. }
  167. }
  168. PreloadAssets(assetList);
  169. // pause script and tick until assets are ready
  170. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScriptWithTimeout, 120.0f);
  171. AZ::TickBus::Handler::BusDisconnect();
  172. if (m_testParameters.m_numShadowCastingSpotLights > 0 && m_diskLightsEnabled)
  173. {
  174. CreateSpotLights();
  175. }
  176. if (m_testParameters.m_activateDirectionalLight && m_directionalLightEnabled)
  177. {
  178. CreateDirectionalLight();
  179. }
  180. }
  181. void HighInstanceTestComponent::OnAllAssetsReadyActivate()
  182. {
  183. AZ::Render::MaterialAssignmentMap materials;
  184. for (ModelInstanceData& instanceData : m_modelInstanceData)
  185. {
  186. AZ::Render::MaterialAssignment& defaultAssignment = materials[AZ::Render::DefaultMaterialAssignmentId];
  187. defaultAssignment = {};
  188. if (instanceData.m_materialAssetId.IsValid())
  189. {
  190. defaultAssignment.m_materialAsset.Create(instanceData.m_materialAssetId);
  191. defaultAssignment.m_materialInstance = AZ::RPI::Material::FindOrCreate(defaultAssignment.m_materialAsset);
  192. // cache the material when its loaded
  193. m_cachedMaterials.insert(defaultAssignment.m_materialAsset);
  194. }
  195. if (instanceData.m_modelAssetId.IsValid())
  196. {
  197. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset;
  198. modelAsset.Create(instanceData.m_modelAssetId);
  199. instanceData.m_meshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, materials);
  200. GetMeshFeatureProcessor()->SetTransform(instanceData.m_meshHandle, instanceData.m_transform);
  201. }
  202. }
  203. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  204. AZ::TickBus::Handler::BusConnect();
  205. }
  206. void HighInstanceTestComponent::DestroyLatticeInstances()
  207. {
  208. DestroyHandles();
  209. m_modelInstanceData.clear();
  210. }
  211. void HighInstanceTestComponent::DestroyLights()
  212. {
  213. m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
  214. m_directionalLightHandle = {};
  215. for (int index = 0; index < m_diskLights.size(); ++index)
  216. {
  217. DiskLightHandle& handle = m_diskLights[index].m_handle;
  218. m_diskLightFeatureProcessor->ReleaseLight(handle);
  219. handle = {};
  220. }
  221. }
  222. void HighInstanceTestComponent::DestroyHandles()
  223. {
  224. for (ModelInstanceData& instanceData : m_modelInstanceData)
  225. {
  226. GetMeshFeatureProcessor()->ReleaseMesh(instanceData.m_meshHandle);
  227. instanceData.m_meshHandle = {};
  228. }
  229. }
  230. AZ::Data::AssetId HighInstanceTestComponent::GetRandomModelId() const
  231. {
  232. auto& modelAllowlist = m_modelBrowser.GetPinnedAssets();
  233. if (modelAllowlist.size())
  234. {
  235. const size_t randomModelIndex = rand() % modelAllowlist.size();
  236. return modelAllowlist[randomModelIndex].m_assetId;
  237. }
  238. else
  239. {
  240. return AZ::RPI::AssetUtils::GetAssetIdForProductPath("testdata/objects/cube/cube.azmodel", AZ::RPI::AssetUtils::TraceLevel::Error);
  241. }
  242. }
  243. AZ::Data::AssetId HighInstanceTestComponent::GetRandomMaterialId() const
  244. {
  245. auto& materialAllowlist = m_materialBrowser.GetPinnedAssets();
  246. if (materialAllowlist.size())
  247. {
  248. const size_t randomMaterialIndex = rand() % materialAllowlist.size();
  249. return materialAllowlist[randomMaterialIndex].m_assetId;
  250. }
  251. else
  252. {
  253. return AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultPbrMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error);
  254. }
  255. }
  256. void HighInstanceTestComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint scriptTime)
  257. {
  258. AZ_PROFILE_FUNCTION(AtomSampleViewer);
  259. if (m_updateTransformEnabled)
  260. {
  261. float radians = static_cast<float>(fmod(scriptTime.GetSeconds(), AZ::Constants::TwoPi));
  262. AZ::Vector3 rotation(radians, radians, radians);
  263. AZ::Transform rotationTransform;
  264. rotationTransform.SetFromEulerRadians(rotation);
  265. for (ModelInstanceData& instanceData : m_modelInstanceData)
  266. {
  267. GetMeshFeatureProcessor()->SetTransform(instanceData.m_meshHandle, instanceData.m_transform * rotationTransform);
  268. }
  269. }
  270. bool currentUseSimpleModels = m_useSimpleModels;
  271. bool diskLightsEnabled = m_diskLightsEnabled;
  272. bool directionalLightEnabled = m_directionalLightEnabled;
  273. if (m_imguiSidebar.Begin())
  274. {
  275. ImGui::Checkbox("Update Transforms Every Frame", &m_updateTransformEnabled);
  276. ImGui::Spacing();
  277. ImGui::Separator();
  278. ImGui::Spacing();
  279. RenderImGuiLatticeControls();
  280. ImGui::Spacing();
  281. ImGui::Separator();
  282. ImGui::Spacing();
  283. ImGui::Checkbox("Use simple models", &m_useSimpleModels);
  284. ImGui::Spacing();
  285. ImGui::Separator();
  286. ImGui::Spacing();
  287. ImGui::Checkbox("Display SpotLight Debug", &m_drawDiskLightDebug);
  288. ImGui::Spacing();
  289. ImGui::Separator();
  290. ImGui::Spacing();
  291. if (m_testParameters.m_numShadowCastingSpotLights > 0)
  292. {
  293. ImGui::Checkbox("Enable SpotLights", &m_diskLightsEnabled);
  294. }
  295. if (m_testParameters.m_activateDirectionalLight)
  296. {
  297. ImGui::Checkbox("Enable Directional Light", &m_directionalLightEnabled);
  298. }
  299. m_imguiSidebar.End();
  300. }
  301. if(diskLightsEnabled != m_diskLightsEnabled || directionalLightEnabled != m_directionalLightEnabled)
  302. {
  303. DestroyLights();
  304. if (m_testParameters.m_numShadowCastingSpotLights > 0 && m_diskLightsEnabled)
  305. {
  306. CreateSpotLights();
  307. }
  308. if(m_testParameters.m_activateDirectionalLight && m_directionalLightEnabled)
  309. {
  310. CreateDirectionalLight();
  311. }
  312. }
  313. if (currentUseSimpleModels != m_useSimpleModels)
  314. {
  315. m_modelBrowser.SetPinnedAssets(m_useSimpleModels?m_simpleModelList:m_expandedModelList);
  316. for (ModelInstanceData& instanceData : m_modelInstanceData)
  317. {
  318. instanceData.m_modelAssetId = GetRandomModelId();
  319. }
  320. DestroyHandles();
  321. DestroyLights();
  322. FinalizeLatticeInstances();
  323. }
  324. DrawDiskLightDebugObjects();
  325. }
  326. void HighInstanceTestComponent::ResetNoClipController()
  327. {
  328. using namespace AZ;
  329. using namespace AZ::Debug;
  330. AZ::Vector3 camPos = AZ::Vector3::CreateFromFloat3(m_testParameters.m_cameraPosition);
  331. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, 2000.0f);
  332. NoClipControllerRequestBus::Event(GetCameraEntityId(), &NoClipControllerRequestBus::Events::SetPosition, camPos);
  333. NoClipControllerRequestBus::Event(GetCameraEntityId(), &NoClipControllerRequestBus::Events::SetHeading, AZ::DegToRad(m_testParameters.m_cameraHeadingDeg));
  334. NoClipControllerRequestBus::Event(GetCameraEntityId(), &NoClipControllerRequestBus::Events::SetPitch, AZ::DegToRad(m_testParameters.m_cameraPitchDeg));
  335. }
  336. void HighInstanceTestComponent::SaveCameraConfiguration()
  337. {
  338. Camera::CameraRequestBus::EventResult(m_originalFarClipDistance, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance);
  339. }
  340. void HighInstanceTestComponent::RestoreCameraConfiguration()
  341. {
  342. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, m_originalFarClipDistance);
  343. }
  344. void HighInstanceTestComponent::CreateSpotLights()
  345. {
  346. for (int index = 0; index < m_testParameters.m_numShadowCastingSpotLights; ++index)
  347. {
  348. CreateSpotLight(index);
  349. }
  350. }
  351. void HighInstanceTestComponent::CreateSpotLight(int index)
  352. {
  353. Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
  354. const DiskLightHandle handle = featureProcessor->AcquireLight();
  355. AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(m_diskLights[index].m_color * m_testParameters.m_shadowSpotlightIntensity);
  356. featureProcessor->SetRgbIntensity(handle, lightColor);
  357. featureProcessor->SetAttenuationRadius(handle, m_testParameters.m_shadowSpotlightMaxDistance);
  358. featureProcessor->SetConeAngles(
  359. handle,
  360. DegToRad(m_testParameters.m_shadowSpotlightInnerAngleDeg),
  361. DegToRad(m_testParameters.m_shadowSpotlightOuterAngleDeg));
  362. featureProcessor->SetShadowsEnabled(handle, true);
  363. featureProcessor->SetShadowmapMaxResolution(handle, m_testParameters.m_shadowmapSize);
  364. featureProcessor->SetShadowFilterMethod(handle, m_testParameters.m_shadowFilterMethod);
  365. featureProcessor->SetFilteringSampleCount(handle, 1);
  366. const Vector3 aabbOffset = m_diskLights[index].m_relativePosition.GetNormalized() * (0.5f * m_testParameters.m_shadowSpotlightMaxDistance);
  367. const Vector3 position = m_worldAabb.GetCenter() + aabbOffset;
  368. featureProcessor->SetPosition(handle, position);
  369. featureProcessor->SetDirection(handle, (-aabbOffset).GetNormalized());
  370. m_diskLights[index].m_handle = handle;
  371. }
  372. const AZ::Color& HighInstanceTestComponent::GetNextLightColor()
  373. {
  374. static uint16_t colorIndex = 0;
  375. static const AZStd::vector<AZ::Color> colors =
  376. {
  377. AZ::Colors::Red,
  378. AZ::Colors::Green,
  379. AZ::Colors::Blue,
  380. AZ::Colors::Cyan,
  381. AZ::Colors::Fuchsia,
  382. AZ::Colors::Yellow,
  383. AZ::Colors::SpringGreen
  384. };
  385. const AZ::Color& result = colors[colorIndex];
  386. colorIndex = (colorIndex + 1) % colors.size();
  387. return result;
  388. }
  389. AZ::Vector3 HighInstanceTestComponent::GetRandomDirection()
  390. {
  391. return AZ::Vector3(
  392. m_random.GetRandomFloat() - 0.5f,
  393. m_random.GetRandomFloat() - 0.5f,
  394. m_random.GetRandomFloat() - 0.5f).GetNormalized();
  395. }
  396. void HighInstanceTestComponent::BuildDiskLightParameters()
  397. {
  398. m_random.SetSeed(0);
  399. m_diskLights.clear();
  400. m_diskLights.reserve(m_testParameters.m_numShadowCastingSpotLights);
  401. for (int index = 0; index < m_testParameters.m_numShadowCastingSpotLights; ++index)
  402. {
  403. m_diskLights.emplace_back(
  404. GetNextLightColor(),
  405. GetRandomDirection(),
  406. m_testParameters.m_shadowmapSize);
  407. }
  408. }
  409. void HighInstanceTestComponent::CreateDirectionalLight()
  410. {
  411. Render::DirectionalLightFeatureProcessorInterface* featureProcessor = m_directionalLightFeatureProcessor;
  412. const DirectionalLightHandle handle = featureProcessor->AcquireLight();
  413. const auto lightTransform = Transform::CreateLookAt(
  414. -m_worldAabb.GetMax(),
  415. Vector3::CreateZero());
  416. featureProcessor->SetDirection(
  417. handle,
  418. lightTransform.GetBasis(1));
  419. featureProcessor->SetRgbIntensity(handle, AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux>(AZ::Color::CreateOne() * m_testParameters.m_directionalLightIntensity));
  420. featureProcessor->SetCascadeCount(handle, m_testParameters.m_numDirectionalLightShadowCascades);
  421. featureProcessor->SetShadowmapSize(handle, m_testParameters.m_shadowmapSize);
  422. featureProcessor->SetViewFrustumCorrectionEnabled(handle, false);
  423. featureProcessor->SetShadowFilterMethod(handle, m_testParameters.m_shadowFilterMethod);
  424. featureProcessor->SetFilteringSampleCount(handle, 1);
  425. featureProcessor->SetGroundHeight(handle, 0.f);
  426. m_directionalLightHandle = handle;
  427. }
  428. void HighInstanceTestComponent::DrawDiskLightDebugObjects()
  429. {
  430. if (auto auxGeom = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(m_scene);
  431. m_drawDiskLightDebug && auxGeom)
  432. {
  433. for (int i = 0; i < m_diskLights.size(); ++i)
  434. {
  435. const auto& light = m_diskLights[i];
  436. if (light.m_handle.IsValid())
  437. {
  438. const Render::DiskLightData& lightData = m_diskLightFeatureProcessor->GetDiskData(light.m_handle);
  439. const float lightDistance = sqrt(1.0f/lightData.m_invAttenuationRadiusSquared);
  440. AZ::Vector3 position = AZ::Vector3::CreateFromFloat3(lightData.m_position.data());
  441. AZ::Vector3 direction = AZ::Vector3::CreateFromFloat3(lightData.m_direction.data()).GetNormalized();
  442. position += direction * lightDistance;
  443. direction *= -1.0f;
  444. float coneSlantLength = lightDistance / lightData.m_cosOuterConeAngle;
  445. float farEndCapRadius = sqrt(coneSlantLength * coneSlantLength - lightDistance * lightDistance);
  446. auxGeom->DrawCone(position, direction, farEndCapRadius, lightDistance, light.m_color, AZ::RPI::AuxGeomDraw::DrawStyle::Line);
  447. }
  448. }
  449. }
  450. }
  451. } // namespace AtomSampleViewer