ImageBasedLightComponentController.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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 <ImageBasedLights/ImageBasedLightComponentController.h>
  9. #include <AtomLyIntegration/CommonFeatures/ImageBasedLights/ImageBasedLightComponentConstants.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <Atom/RPI.Public/Scene.h>
  13. #include <Atom/Utils/Utils.h>
  14. namespace AZ
  15. {
  16. namespace Render
  17. {
  18. void ImageBasedLightComponentController::Reflect(ReflectContext* context)
  19. {
  20. ImageBasedLightComponentConfig::Reflect(context);
  21. if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
  22. {
  23. serializeContext->Class<ImageBasedLightComponentController>()
  24. ->Version(0)
  25. ->Field("Configuration", &ImageBasedLightComponentController::m_configuration)
  26. ;
  27. }
  28. if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
  29. {
  30. behaviorContext->EBus<ImageBasedLightComponentRequestBus>("ImageBasedLightComponentRequestBus")
  31. ->Event("SetSpecularImageAssetId", &ImageBasedLightComponentRequestBus::Events::SetSpecularImageAssetId)
  32. ->Event("GetSpecularImageAssetId", &ImageBasedLightComponentRequestBus::Events::GetSpecularImageAssetId)
  33. ->Event("SetDiffuseImageAssetId", &ImageBasedLightComponentRequestBus::Events::SetDiffuseImageAssetId)
  34. ->Event("GetDiffuseImageAssetId", &ImageBasedLightComponentRequestBus::Events::GetDiffuseImageAssetId)
  35. ->Event("SetSpecularImageAssetPath", &ImageBasedLightComponentRequestBus::Events::SetSpecularImageAssetPath)
  36. ->Event("GetSpecularImageAssetPath", &ImageBasedLightComponentRequestBus::Events::GetSpecularImageAssetPath)
  37. ->Event("SetDiffuseImageAssetPath", &ImageBasedLightComponentRequestBus::Events::SetDiffuseImageAssetPath)
  38. ->Event("GetDiffuseImageAssetPath", &ImageBasedLightComponentRequestBus::Events::GetDiffuseImageAssetPath)
  39. ->VirtualProperty("SpecularImageAssetId", "GetSpecularImageAssetId", "SetSpecularImageAssetId")
  40. ->VirtualProperty("DiffuseImageAssetId", "GetDiffuseImageAssetId", "SetDiffuseImageAssetId")
  41. ->VirtualProperty("SpecularImageAssetPath", "GetSpecularImageAssetPath", "SetSpecularImageAssetPath")
  42. ->VirtualProperty("DiffuseImageAssetPath", "GetDiffuseImageAssetPath", "SetDiffuseImageAssetPath")
  43. ;
  44. }
  45. }
  46. void ImageBasedLightComponentController::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
  47. {
  48. provided.push_back(AZ_CRC_CE("ImageBasedLightService"));
  49. }
  50. void ImageBasedLightComponentController::GetIncompatibleServices(ComponentDescriptor::DependencyArrayType& incompatible)
  51. {
  52. incompatible.push_back(AZ_CRC_CE("ImageBasedLightService"));
  53. }
  54. ImageBasedLightComponentController::ImageBasedLightComponentController(const ImageBasedLightComponentConfig& config)
  55. : m_configuration(config)
  56. {
  57. }
  58. void ImageBasedLightComponentController::Activate(EntityId entityId)
  59. {
  60. m_entityId = entityId;
  61. m_featureProcessor = RPI::Scene::GetFeatureProcessorForEntity<ImageBasedLightFeatureProcessorInterface>(m_entityId);
  62. AZ_Error("ImageBasedLightComponentController", m_featureProcessor, "Unable to find a ImageBasedLightFeatureProcessorInterface on this entity's scene.");
  63. if (m_featureProcessor)
  64. {
  65. LoadImage(m_configuration.m_specularImageAsset);
  66. LoadImage(m_configuration.m_diffuseImageAsset);
  67. m_featureProcessor->SetExposure(m_configuration.m_exposure);
  68. TransformInterface* transformInterface = TransformBus::FindFirstHandler(m_entityId);
  69. AZ_Assert(transformInterface, "Unable to attach to a TransformBus handler. Entity transform will not affect IBL.");
  70. const AZ::Transform& transform = transformInterface ? transformInterface->GetWorldTM() : Transform::Identity();
  71. m_featureProcessor->SetOrientation(transform.GetRotation());
  72. TransformNotificationBus::Handler::BusConnect(m_entityId);
  73. ImageBasedLightComponentRequestBus::Handler::BusConnect(m_entityId);
  74. transformInterface = nullptr;
  75. }
  76. }
  77. void ImageBasedLightComponentController::Deactivate()
  78. {
  79. ImageBasedLightComponentRequestBus::Handler::BusDisconnect();
  80. TransformNotificationBus::Handler::BusDisconnect();
  81. ReleaseImages();
  82. if (m_featureProcessor)
  83. {
  84. m_featureProcessor->Reset();
  85. m_featureProcessor = nullptr;
  86. }
  87. m_entityId = EntityId(EntityId::InvalidEntityId);
  88. }
  89. void ImageBasedLightComponentController::SetConfiguration(const ImageBasedLightComponentConfig& config)
  90. {
  91. m_configuration = config;
  92. }
  93. const ImageBasedLightComponentConfig& ImageBasedLightComponentController::GetConfiguration() const
  94. {
  95. return m_configuration;
  96. }
  97. void ImageBasedLightComponentController::OnAssetReady(Data::Asset<Data::AssetData> asset)
  98. {
  99. UpdateWithAsset(asset);
  100. }
  101. void ImageBasedLightComponentController::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
  102. {
  103. UpdateWithAsset(asset);
  104. }
  105. void ImageBasedLightComponentController::OnAssetError(Data::Asset<Data::AssetData> asset)
  106. {
  107. UpdateWithAsset(asset);
  108. }
  109. void ImageBasedLightComponentController::UpdateWithAsset(Data::Asset<Data::AssetData> updatedAsset)
  110. {
  111. if (m_configuration.m_specularImageAsset.GetId() == updatedAsset.GetId())
  112. {
  113. if (m_featureProcessor && HandleAssetUpdate(updatedAsset, m_configuration.m_specularImageAsset))
  114. {
  115. m_featureProcessor->SetSpecularImage(m_configuration.m_specularImageAsset);
  116. ImageBasedLightComponentNotificationBus::Event(m_entityId, &ImageBasedLightComponentNotifications::OnSpecularImageUpdated);
  117. }
  118. }
  119. else if (m_configuration.m_diffuseImageAsset.GetId() == updatedAsset.GetId())
  120. {
  121. if (m_featureProcessor && HandleAssetUpdate(updatedAsset, m_configuration.m_diffuseImageAsset))
  122. {
  123. m_featureProcessor->SetDiffuseImage(m_configuration.m_diffuseImageAsset);
  124. ImageBasedLightComponentNotificationBus::Event(m_entityId, &ImageBasedLightComponentNotifications::OnDiffuseImageUpdated);
  125. }
  126. }
  127. }
  128. bool ImageBasedLightComponentController::HandleAssetUpdate(Data::Asset<Data::AssetData> updatedAsset, Data::Asset<RPI::StreamingImageAsset>& configAsset)
  129. {
  130. configAsset = updatedAsset;
  131. if (updatedAsset.IsReady())
  132. {
  133. auto& descriptor = configAsset->GetImageDescriptor();
  134. bool isCubemap = descriptor.m_isCubemap || descriptor.m_arraySize == 6;
  135. if (isCubemap)
  136. {
  137. return true;
  138. }
  139. }
  140. return false;
  141. }
  142. void ImageBasedLightComponentController::SetSpecularImageAsset(const Data::Asset<RPI::StreamingImageAsset>& imageAsset)
  143. {
  144. Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_specularImageAsset.GetId());
  145. m_configuration.m_specularImageAsset = imageAsset;
  146. if (imageAsset.GetId().IsValid())
  147. {
  148. LoadImage(m_configuration.m_specularImageAsset);
  149. }
  150. else if (m_featureProcessor)
  151. {
  152. // Clear out current image asset
  153. m_featureProcessor->SetSpecularImage(m_configuration.m_specularImageAsset);
  154. }
  155. }
  156. void ImageBasedLightComponentController::SetDiffuseImageAsset(const Data::Asset<RPI::StreamingImageAsset>& imageAsset)
  157. {
  158. Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_diffuseImageAsset.GetId());
  159. m_configuration.m_diffuseImageAsset = imageAsset;
  160. if (imageAsset.GetId().IsValid())
  161. {
  162. LoadImage(m_configuration.m_diffuseImageAsset);
  163. }
  164. else if (m_featureProcessor)
  165. {
  166. // Clear out current image asset
  167. m_featureProcessor->SetDiffuseImage(m_configuration.m_diffuseImageAsset);
  168. }
  169. }
  170. Data::Asset<RPI::StreamingImageAsset> ImageBasedLightComponentController::GetSpecularImageAsset() const
  171. {
  172. return m_configuration.m_specularImageAsset;
  173. }
  174. Data::Asset<RPI::StreamingImageAsset> ImageBasedLightComponentController::GetDiffuseImageAsset() const
  175. {
  176. return m_configuration.m_diffuseImageAsset;
  177. }
  178. void ImageBasedLightComponentController::SetSpecularImageAssetId(const Data::AssetId imageAssetId)
  179. {
  180. SetSpecularImageAsset(GetAssetFromId<RPI::StreamingImageAsset>(imageAssetId, m_configuration.m_specularImageAsset.GetAutoLoadBehavior()));
  181. }
  182. void ImageBasedLightComponentController::SetDiffuseImageAssetId(const Data::AssetId imageAssetId)
  183. {
  184. SetDiffuseImageAsset(GetAssetFromId<RPI::StreamingImageAsset>(imageAssetId, m_configuration.m_diffuseImageAsset.GetAutoLoadBehavior()));
  185. }
  186. void ImageBasedLightComponentController::SetSpecularImageAssetPath(const AZStd::string path)
  187. {
  188. SetSpecularImageAsset(GetAssetFromPath<RPI::StreamingImageAsset>(path, m_configuration.m_specularImageAsset.GetAutoLoadBehavior()));
  189. }
  190. void ImageBasedLightComponentController::SetDiffuseImageAssetPath(const AZStd::string path)
  191. {
  192. SetDiffuseImageAsset(GetAssetFromPath<RPI::StreamingImageAsset>(path, m_configuration.m_diffuseImageAsset.GetAutoLoadBehavior()));
  193. }
  194. AZStd::string ImageBasedLightComponentController::GetSpecularImageAssetPath() const
  195. {
  196. AZStd::string assetPathString;
  197. Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &Data::AssetCatalogRequests::GetAssetPathById, m_configuration.m_specularImageAsset.GetId());
  198. return assetPathString;
  199. }
  200. AZStd::string ImageBasedLightComponentController::GetDiffuseImageAssetPath() const
  201. {
  202. AZStd::string assetPathString;
  203. Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &Data::AssetCatalogRequests::GetAssetPathById, m_configuration.m_diffuseImageAsset.GetId());
  204. return assetPathString;
  205. }
  206. Data::AssetId ImageBasedLightComponentController::GetSpecularImageAssetId() const
  207. {
  208. return m_configuration.m_specularImageAsset.GetId();
  209. }
  210. Data::AssetId ImageBasedLightComponentController::GetDiffuseImageAssetId() const
  211. {
  212. return m_configuration.m_diffuseImageAsset.GetId();
  213. }
  214. void ImageBasedLightComponentController::SetExposure(float exposure)
  215. {
  216. m_configuration.m_exposure = exposure;
  217. if (m_featureProcessor)
  218. {
  219. m_featureProcessor->SetExposure(exposure);
  220. }
  221. }
  222. float ImageBasedLightComponentController::GetExposure() const
  223. {
  224. return m_configuration.m_exposure;
  225. }
  226. void ImageBasedLightComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
  227. {
  228. const Quaternion& rotation = world.GetRotation();
  229. if (m_featureProcessor)
  230. {
  231. m_featureProcessor->SetOrientation(rotation);
  232. }
  233. }
  234. void ImageBasedLightComponentController::LoadImage(Data::Asset<RPI::StreamingImageAsset>& imageAsset)
  235. {
  236. Data::AssetBus::MultiHandler::BusDisconnect(imageAsset.GetId());
  237. if (imageAsset.GetId().IsValid())
  238. {
  239. // If the asset is already loaded it'll call OnAssetReady() immediately on BusConnect().
  240. Data::AssetBus::MultiHandler::BusConnect(imageAsset.GetId());
  241. imageAsset.QueueLoad();
  242. }
  243. else
  244. {
  245. // Call update for invalid assets so current assets can be cleared if necessary.
  246. UpdateWithAsset(imageAsset);
  247. }
  248. }
  249. void ImageBasedLightComponentController::ReleaseImages()
  250. {
  251. Data::AssetBus::MultiHandler::BusDisconnect();
  252. m_configuration.m_specularImageAsset.Release();
  253. m_configuration.m_diffuseImageAsset.Release();
  254. }
  255. } // namespace Render
  256. } // namespace AZ