3
0

HDRiSkyboxComponentController.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 <Atom/Feature/SkyBox/SkyboxConstants.h>
  9. #include <SkyBox/HDRiSkyboxComponentController.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <Atom/RPI.Public/Scene.h>
  13. namespace AZ
  14. {
  15. namespace Render
  16. {
  17. void HDRiSkyboxComponentController::Reflect(ReflectContext* context)
  18. {
  19. HDRiSkyboxComponentConfig::Reflect(context);
  20. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  21. {
  22. serializeContext->Class<HDRiSkyboxComponentController>()
  23. ->Version(1)
  24. ->Field("Configuration", &HDRiSkyboxComponentController::m_configuration);
  25. }
  26. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  27. {
  28. behaviorContext->EBus<HDRiSkyboxRequestBus>("HDRiSkyboxRequestBus")
  29. ->Event("SetExposure", &HDRiSkyboxRequestBus::Events::SetExposure)
  30. ->Event("GetExposure", &HDRiSkyboxRequestBus::Events::GetExposure)
  31. ->VirtualProperty("Exposure", "GetExposure", "SetExposure")
  32. ;
  33. }
  34. }
  35. void HDRiSkyboxComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  36. {
  37. provided.push_back(AZ_CRC("SkyBoxService", 0x8169a709));
  38. }
  39. void HDRiSkyboxComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  40. {
  41. incompatible.push_back(AZ_CRC("SkyBoxService", 0x8169a709));
  42. incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
  43. }
  44. void HDRiSkyboxComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  45. {
  46. required.push_back(AZ_CRC("TransformService"));
  47. }
  48. HDRiSkyboxComponentController::HDRiSkyboxComponentController(const HDRiSkyboxComponentConfig& config)
  49. : m_configuration(config)
  50. {
  51. }
  52. void HDRiSkyboxComponentController::Activate(EntityId entityId)
  53. {
  54. m_featureProcessorInterface = RPI::Scene::GetFeatureProcessorForEntity<SkyBoxFeatureProcessorInterface>(entityId);
  55. // only activate if there is no other skybox activate
  56. if (m_featureProcessorInterface && !m_featureProcessorInterface->IsEnabled())
  57. {
  58. m_featureProcessorInterface->SetSkyboxMode(SkyBoxMode::Cubemap);
  59. m_featureProcessorInterface->Enable(true);
  60. m_entityId = entityId;
  61. SetCubemapAsset(m_configuration.m_cubemapAsset);
  62. SetExposure(m_configuration.m_exposure);
  63. m_transformInterface = TransformBus::FindFirstHandler(m_entityId);
  64. AZ_Assert(m_transformInterface, "Unable to attach to a TransformBus handler. Entity transform will not affect to skybox.");
  65. const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity();
  66. m_featureProcessorInterface->SetCubemapRotationMatrix(GetInverseTransform(transform));
  67. HDRiSkyboxRequestBus::Handler::BusConnect(m_entityId);
  68. TransformNotificationBus::Handler::BusConnect(m_entityId);
  69. m_isActive = true;
  70. }
  71. else
  72. {
  73. m_featureProcessorInterface = nullptr;
  74. AZ_Warning("HDRiSkyboxComponentController", false, "There is already another HDRi Skybox or Physical Sky component in the scene!");
  75. }
  76. }
  77. void HDRiSkyboxComponentController::Deactivate()
  78. {
  79. // Run deactivate if this skybox is activate
  80. if (m_isActive)
  81. {
  82. HDRiSkyboxRequestBus::Handler::BusDisconnect(m_entityId);
  83. TransformNotificationBus::Handler::BusDisconnect(m_entityId);
  84. Data::AssetBus::MultiHandler::BusDisconnect();
  85. m_configuration.m_cubemapAsset.Release();
  86. m_featureProcessorInterface->Enable(false);
  87. m_featureProcessorInterface = nullptr;
  88. m_transformInterface = nullptr;
  89. m_isActive = false;
  90. }
  91. }
  92. void HDRiSkyboxComponentController::SetConfiguration(const HDRiSkyboxComponentConfig& config)
  93. {
  94. m_configuration = config;
  95. }
  96. const HDRiSkyboxComponentConfig& HDRiSkyboxComponentController::GetConfiguration() const
  97. {
  98. return m_configuration;
  99. }
  100. void HDRiSkyboxComponentController::OnAssetReady(Data::Asset<Data::AssetData> asset)
  101. {
  102. UpdateWithAsset(asset);
  103. }
  104. void HDRiSkyboxComponentController::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
  105. {
  106. UpdateWithAsset(asset);
  107. }
  108. void HDRiSkyboxComponentController::OnAssetError(Data::Asset<Data::AssetData> asset)
  109. {
  110. UpdateWithAsset(asset);
  111. }
  112. void HDRiSkyboxComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
  113. {
  114. m_featureProcessorInterface->SetCubemapRotationMatrix(GetInverseTransform(world));
  115. }
  116. Data::Asset<RPI::StreamingImageAsset> HDRiSkyboxComponentController::GetCubemapAsset() const
  117. {
  118. return m_configuration.m_cubemapAsset;
  119. }
  120. void HDRiSkyboxComponentController::SetCubemapAsset(const Data::Asset<RPI::StreamingImageAsset>& cubemapAsset)
  121. {
  122. Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_cubemapAsset.GetId());
  123. m_configuration.m_cubemapAsset = cubemapAsset;
  124. LoadImage(m_configuration.m_cubemapAsset);
  125. }
  126. void HDRiSkyboxComponentController::SetExposure(float exposure)
  127. {
  128. m_configuration.m_exposure = exposure;
  129. m_featureProcessorInterface->SetCubemapExposure(exposure);
  130. }
  131. float HDRiSkyboxComponentController::GetExposure() const
  132. {
  133. return m_configuration.m_exposure;
  134. }
  135. void HDRiSkyboxComponentController::LoadImage(Data::Asset<RPI::StreamingImageAsset>& imageAsset)
  136. {
  137. Data::AssetBus::MultiHandler::BusDisconnect(imageAsset.GetId());
  138. if (imageAsset.GetId().IsValid())
  139. {
  140. // If the asset is already loaded it'll call OnAssetReady() immediately on BusConnect().
  141. Data::AssetBus::MultiHandler::BusConnect(imageAsset.GetId());
  142. imageAsset.QueueLoad();
  143. }
  144. else
  145. {
  146. // Call update for invalid assets so current assets can be cleared if necessary.
  147. UpdateWithAsset(imageAsset);
  148. }
  149. }
  150. void HDRiSkyboxComponentController::UpdateWithAsset(Data::Asset<Data::AssetData> updatedAsset)
  151. {
  152. if (m_configuration.m_cubemapAsset.GetId() == updatedAsset.GetId())
  153. {
  154. m_configuration.m_cubemapAsset = updatedAsset;
  155. if (IsAssetValid(m_configuration.m_cubemapAsset))
  156. {
  157. m_featureProcessorInterface->SetCubemap(RPI::StreamingImage::FindOrCreate(m_configuration.m_cubemapAsset));
  158. }
  159. else
  160. {
  161. m_featureProcessorInterface->SetCubemap(nullptr);
  162. }
  163. }
  164. }
  165. bool HDRiSkyboxComponentController::IsAssetValid(Data::Asset<RPI::StreamingImageAsset>& asset)
  166. {
  167. if (asset.GetId().IsValid() && asset->IsReady())
  168. {
  169. auto& descriptor = asset->GetImageDescriptor();
  170. bool isCubemap = descriptor.m_isCubemap || descriptor.m_arraySize == 6;
  171. if (isCubemap)
  172. {
  173. return true;
  174. }
  175. }
  176. return false;
  177. }
  178. AZ::Matrix4x4 HDRiSkyboxComponentController::GetInverseTransform(const AZ::Transform& world)
  179. {
  180. float matrix[16];
  181. // remove scale
  182. Transform worldNoScale = world;
  183. worldNoScale.ExtractUniformScale();
  184. AZ::Matrix3x4 transformMatrix = AZ::Matrix3x4::CreateFromTransform(worldNoScale);
  185. transformMatrix.StoreToRowMajorFloat12(matrix);
  186. // remove translation
  187. matrix[3] = 0;
  188. matrix[7] = 0;
  189. matrix[11] = 0;
  190. matrix[12] = 0;
  191. matrix[13] = 0;
  192. matrix[14] = 0;
  193. matrix[15] = 1;
  194. return AZ::Matrix4x4::CreateFromRowMajorFloat16(matrix).GetInverseFast();
  195. }
  196. } // namespace Render
  197. } // namespace AZ