PostFxLayerComponentController.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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 <PostProcess/PostFxLayerComponentController.h>
  9. #include <AtomLyIntegration/CommonFeatures/PostProcess/PostFxWeightRequestBus.h>
  10. #include <LmbrCentral/Scripting/TagComponentBus.h>
  11. #include <LmbrCentral/Scripting/EditorTagComponentBus.h>
  12. #include <AzCore/Component/TransformBus.h>
  13. #include <AzCore/RTTI/BehaviorContext.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <Atom/RPI.Public/ViewProviderBus.h>
  16. #include <Atom/RPI.Public/ViewportContextBus.h>
  17. namespace AZ
  18. {
  19. namespace Render
  20. {
  21. void PostFxLayerComponentController::Reflect(ReflectContext* context)
  22. {
  23. PostFxLayerComponentConfig::Reflect(context);
  24. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  25. {
  26. serializeContext->Class<PostFxLayerComponentController>()
  27. ->Version(0)
  28. ->Field("Configuration", &PostFxLayerComponentController::m_configuration);
  29. }
  30. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  31. {
  32. behaviorContext->EBus<PostFxLayerRequestBus>("PostFxLayerRequestBus")
  33. // Auto-gen behavior context...
  34. #define PARAM_EVENT_BUS PostFxLayerRequestBus::Events
  35. #include <Atom/Feature/ParamMacros/StartParamBehaviorContext.inl>
  36. #include <Atom/Feature/PostProcess/PostProcessParams.inl>
  37. #include <Atom/Feature/ParamMacros/EndParams.inl>
  38. #undef PARAM_EVENT_BUS
  39. ;
  40. }
  41. }
  42. void PostFxLayerComponentController::OnTick(float deltaTime, ScriptTimePoint time)
  43. {
  44. AZ_UNUSED(deltaTime);
  45. AZ_UNUSED(time);
  46. // get all camera entities if no tags were set in the PostFx layer
  47. const AZStd::unordered_set<AZ::EntityId>& cameraEntityList = GetCameraEntityList();
  48. // Get views of each camera
  49. AZStd::unordered_set<AZ::RPI::View*> allSceneViews;
  50. for (const AZ::EntityId& cameraEntityId : cameraEntityList)
  51. {
  52. for (uint32_t i = 0; i < AZ::RPI::MaxViewTypes; i++)
  53. {
  54. if (i == AZ::RPI::DefaultViewType)
  55. {
  56. // Get the view pointer associated to each camera entity
  57. AZ::RPI::ViewPtr view = nullptr;
  58. AZ::RPI::ViewProviderBus::EventResult(view, cameraEntityId, &AZ::RPI::ViewProvider::GetView);
  59. if (view != nullptr)
  60. {
  61. allSceneViews.insert(view.get());
  62. }
  63. }
  64. else
  65. {
  66. AZ::RPI::ViewPtr stereoscopicView = nullptr;
  67. AZ::RPI::ViewProviderBus::EventResult(
  68. stereoscopicView, cameraEntityId, &AZ::RPI::ViewProvider::GetStereoscopicView, static_cast<AZ::RPI::ViewType>(i));
  69. if (stereoscopicView != nullptr)
  70. {
  71. allSceneViews.insert(stereoscopicView.get());
  72. }
  73. }
  74. }
  75. }
  76. // Add the current view which can potentially be the editor view
  77. auto atomViewportRequests = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
  78. const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName();
  79. auto currentView = atomViewportRequests->GetCurrentViewGroup(contextName)->GetView();
  80. if (IsEditorView(currentView))
  81. {
  82. allSceneViews.insert(currentView.get());
  83. }
  84. // calculate blend weights for all cameras
  85. PostProcessSettingsInterface::ViewBlendWeightMap perViewBlendWeights;
  86. for (auto view : allSceneViews)
  87. {
  88. if (view)
  89. {
  90. // get the view position
  91. AZ::Vector3 viewPosition = view->GetViewToWorldMatrix().GetTranslation();
  92. // calculate blend weight based on proximity to weight modifier
  93. float blendWeightResult = 1.0f;
  94. AZ::Render::PostFxWeightRequestBus::EventResult(
  95. blendWeightResult,
  96. m_entityId,
  97. &AZ::Render::PostFxWeightRequests::GetWeightAtPosition,
  98. viewPosition
  99. );
  100. // store result
  101. perViewBlendWeights[view] = blendWeightResult;
  102. }
  103. }
  104. // copy cameraToBlendWeight data to settings
  105. if (m_postProcessInterface)
  106. {
  107. m_postProcessInterface = m_featureProcessorInterface->GetOrCreateSettingsInterface(m_entityId);
  108. m_postProcessInterface->CopyViewToBlendWeightSettings(perViewBlendWeights);
  109. m_postProcessInterface->OnConfigChanged();
  110. }
  111. }
  112. void PostFxLayerComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  113. {
  114. provided.push_back(AZ_CRC_CE("PostFXLayerService"));
  115. }
  116. void PostFxLayerComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  117. {
  118. incompatible.push_back(AZ_CRC_CE("PostFXLayerService"));
  119. }
  120. PostFxLayerComponentController::PostFxLayerComponentController(const PostFxLayerComponentConfig& config)
  121. : m_configuration(config)
  122. {
  123. }
  124. void PostFxLayerComponentController::OnEntityTagAdded(const AZ::EntityId& entityId)
  125. {
  126. // If the entity contains an exclusion tag, do not add it to the tagged camera entities
  127. if (!HasTags(entityId, m_configuration.m_exclusionTags))
  128. {
  129. m_taggedCameraEntities.insert(entityId);
  130. }
  131. }
  132. void PostFxLayerComponentController::OnEntityTagRemoved(const AZ::EntityId& entityId)
  133. {
  134. m_taggedCameraEntities.erase(entityId);
  135. }
  136. void PostFxLayerComponentController::OnCameraAdded(const AZ::EntityId& cameraId)
  137. {
  138. // If the entity contains an exclusion tag, do not add it to the camera entities
  139. if (!HasTags(cameraId, m_configuration.m_exclusionTags))
  140. {
  141. m_cameraEntities.insert(cameraId);
  142. }
  143. AZ::RPI::ViewPtr view = nullptr;
  144. AZ::RPI::ViewProviderBus::EventResult(view, cameraId, &AZ::RPI::ViewProvider::GetView);
  145. if (view != nullptr)
  146. {
  147. m_allCameraViews.insert(view.get());
  148. }
  149. }
  150. void PostFxLayerComponentController::OnCameraRemoved(const AZ::EntityId& cameraId)
  151. {
  152. m_cameraEntities.erase(cameraId);
  153. }
  154. void PostFxLayerComponentController::RebuildCameraEntitiesList()
  155. {
  156. // Reconnect buses to regenerate the entities list
  157. m_taggedCameraEntities.clear();
  158. BusConnectToTags();
  159. m_cameraEntities.clear();
  160. Camera::CameraNotificationBus::Handler::BusDisconnect();
  161. Camera::CameraNotificationBus::Handler::BusConnect();
  162. }
  163. const AZStd::unordered_set<AZ::EntityId>& PostFxLayerComponentController::GetCameraEntityList() const
  164. {
  165. if (m_configuration.m_cameraTags.empty())
  166. {
  167. return m_cameraEntities;
  168. }
  169. else
  170. {
  171. return m_taggedCameraEntities;
  172. }
  173. }
  174. bool PostFxLayerComponentController::IsEditorView(const AZ::RPI::ViewPtr view)
  175. {
  176. return m_allCameraViews.find(view.get()) == m_allCameraViews.end() ? true : false;
  177. }
  178. bool PostFxLayerComponentController::HasTags(const AZ::EntityId& entityId, const AZStd::vector<AZStd::string>& tags) const
  179. {
  180. bool hasTag = false;
  181. for (auto tag : tags)
  182. {
  183. LmbrCentral::TagComponentRequestBus::EventResult(
  184. hasTag,
  185. entityId,
  186. &LmbrCentral::TagComponentRequests::HasTag,
  187. LmbrCentral::Tag(tag)
  188. );
  189. LmbrCentral::EditorTagComponentRequestBus::EventResult(
  190. hasTag,
  191. entityId,
  192. &LmbrCentral::EditorTagComponentRequests::HasTag,
  193. tag.c_str()
  194. );
  195. if (hasTag)
  196. {
  197. return true;
  198. }
  199. }
  200. return false;
  201. }
  202. void PostFxLayerComponentController::BusConnectToTags()
  203. {
  204. LmbrCentral::TagGlobalNotificationBus::MultiHandler::BusDisconnect();
  205. for (auto tag : m_configuration.m_cameraTags)
  206. {
  207. LmbrCentral::TagGlobalNotificationBus::MultiHandler::BusConnect(LmbrCentral::Tag(tag));
  208. }
  209. }
  210. void PostFxLayerComponentController::Activate(EntityId entityId)
  211. {
  212. m_entityId = entityId;
  213. m_featureProcessorInterface = RPI::Scene::GetFeatureProcessorForEntity<PostProcessFeatureProcessorInterface>(m_entityId);
  214. if (m_featureProcessorInterface)
  215. {
  216. m_postProcessInterface = m_featureProcessorInterface->GetOrCreateSettingsInterface(m_entityId);
  217. m_configuration.CopySettingsTo(m_postProcessInterface);
  218. }
  219. BusConnectToTags();
  220. Camera::CameraNotificationBus::Handler::BusConnect();
  221. PostFxLayerRequestBus::Handler::BusConnect(m_entityId);
  222. AZ::TickBus::Handler::BusConnect();
  223. }
  224. void PostFxLayerComponentController::Deactivate()
  225. {
  226. AZ::TickBus::Handler::BusDisconnect();
  227. PostFxLayerRequestBus::Handler::BusDisconnect(m_entityId);
  228. Camera::CameraNotificationBus::Handler::BusDisconnect();
  229. LmbrCentral::TagGlobalNotificationBus::MultiHandler::BusDisconnect();
  230. if (m_featureProcessorInterface)
  231. {
  232. m_featureProcessorInterface->RemoveSettingsInterface(m_entityId);
  233. }
  234. m_postProcessInterface = nullptr;
  235. m_featureProcessorInterface = nullptr;
  236. m_entityId.SetInvalid();
  237. }
  238. void PostFxLayerComponentController::SetConfiguration(const PostFxLayerComponentConfig& config)
  239. {
  240. m_configuration = config;
  241. }
  242. const PostFxLayerComponentConfig& PostFxLayerComponentController::GetConfiguration() const
  243. {
  244. return m_configuration;
  245. }
  246. void PostFxLayerComponentController::OnConfigChanged()
  247. {
  248. if (m_postProcessInterface)
  249. {
  250. m_configuration.CopySettingsTo(m_postProcessInterface);
  251. m_postProcessInterface->OnConfigChanged();
  252. }
  253. }
  254. // Auto-gen getter/setter function definitions...
  255. // The setter functions will set the values on the Atom settings class, then get the value back
  256. // from the settings class to set the local configuration. This is in case the settings class
  257. // applies some custom logic that results in the set value being different from the input
  258. #define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \
  259. \
  260. ValueType PostFxLayerComponentController::Get##Name() const \
  261. { \
  262. return m_configuration.MemberName; \
  263. } \
  264. void PostFxLayerComponentController::Set##Name(ValueType val) \
  265. { \
  266. if(m_postProcessInterface) \
  267. { \
  268. m_postProcessInterface->Set##Name(val); \
  269. m_postProcessInterface->OnConfigChanged(); \
  270. m_configuration.MemberName = m_postProcessInterface->Get##Name(); \
  271. } \
  272. else \
  273. { \
  274. m_configuration.MemberName = val; \
  275. } \
  276. } \
  277. #define AZ_GFX_COMMON_OVERRIDE(ValueType, Name, MemberName, OverrideValueType) \
  278. \
  279. OverrideValueType PostFxLayerComponentController::Get##Name##Override() const \
  280. { \
  281. return m_configuration.MemberName##Override; \
  282. } \
  283. void PostFxLayerComponentController::Set##Name##Override(OverrideValueType val) \
  284. { \
  285. m_configuration.MemberName = val; \
  286. if(m_postProcessInterface) \
  287. { \
  288. m_postProcessInterface->Set##Name##Override(val); \
  289. m_postProcessInterface->OnConfigChanged(); \
  290. } \
  291. } \
  292. #include <Atom/Feature/ParamMacros/MapAllCommon.inl>
  293. #include <Atom/Feature/PostProcess/PostProcessParams.inl>
  294. #include <Atom/Feature/ParamMacros/EndParams.inl>
  295. } // namespace Render
  296. } // namespace AZ