diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h index ba652a2b94..46fb5cea01 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h @@ -118,6 +118,12 @@ namespace AZ //! Update View's SRG values and compile. This should only be called once per frame before execute command lists. void UpdateSrg(); + using MatrixChangedEvent = AZ::Event; + //! Notifies consumers when the world to view matrix has changed. + void ConnectWorldToViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler); + //! Notifies consumers when the world to clip matrix has changed. + void ConnectWorldToClipMatrixChangedHandler(MatrixChangedEvent::Handler& handler); + private: View() = delete; View(const AZ::Name& name, UsageFlags usage); @@ -182,6 +188,9 @@ namespace AZ // view class doesn't contain subroutines called at the end of each frame bool m_worldToClipMatrixChanged = true; bool m_worldToClipPrevMatrixNeedsUpdate = false; + + MatrixChangedEvent m_oWworldToClipMatrixChange; + MatrixChangedEvent m_onWorldToViewMatrixChange; }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(View::UsageFlags); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h index d3d3155715..4f24a20f35 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h @@ -125,7 +125,9 @@ namespace AZ AzFramework::WindowSize m_viewportSize; SizeChangedEvent m_sizeChangedEvent; MatrixChangedEvent m_viewMatrixChangedEvent; + MatrixChangedEvent::Handler m_onViewMatrixChangedHandler; MatrixChangedEvent m_projectionMatrixChangedEvent; + MatrixChangedEvent::Handler m_onProjectionMatrixChangedHandler; SceneChangedEvent m_sceneChangedEvent; ViewportContextManager* m_manager; RenderPipelinePtr m_currentPipeline; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index 4fe9843534..1d7e10c1ee 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -104,6 +104,9 @@ namespace AZ m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix; m_worldToClipMatrixChanged = true; + m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix); + m_oWworldToClipMatrixChange.Signal(m_worldToClipMatrix); + InvalidateSrg(); } @@ -132,6 +135,9 @@ namespace AZ m_clipToWorldMatrix = m_viewToWorldMatrix * m_clipToViewMatrix; m_worldToClipMatrixChanged = true; + m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix); + m_oWworldToClipMatrixChange.Signal(m_worldToClipMatrix); + InvalidateSrg(); } @@ -166,6 +172,8 @@ namespace AZ m_unprojectionConstants.SetZ(float(-tanHalfFovX)); m_unprojectionConstants.SetW(float(tanHalfFovY)); + m_oWworldToClipMatrixChange.Signal(m_worldToClipMatrix); + InvalidateSrg(); } @@ -225,6 +233,16 @@ namespace AZ passWithDrawListTag->SortDrawList(drawList); } + void View::ConnectWorldToViewMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler) + { + handler.Connect(m_onWorldToViewMatrixChange); + } + + void View::ConnectWorldToClipMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler) + { + handler.Connect(m_oWworldToClipMatrixChange); + } + // [GFX TODO] This function needs unit tests and might need to be reworked RHI::DrawItemSortKey View::GetSortKeyForPosition(const Vector3& positionInWorld) const { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index eb8aaf4440..9482458bd9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -34,8 +34,16 @@ namespace AZ &AzFramework::WindowRequestBus::Events::GetClientAreaSize); AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow); - SetRenderScene(renderScene); - } + m_onProjectionMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) + { + m_projectionMatrixChangedEvent.Signal(matrix); + }); + m_onViewMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) + { + m_projectionMatrixChangedEvent.Signal(matrix); + }); + + SetRenderScene(renderScene); } ViewportContext::~ViewportContext() { @@ -175,7 +183,6 @@ namespace AZ void ViewportContext::SetCameraProjectionMatrix(const AZ::Matrix4x4& matrix) { GetDefaultView()->SetViewToClipMatrix(matrix); - m_projectionMatrixChangedEvent.Signal(matrix); } AZ::Transform ViewportContext::GetCameraTransform() const @@ -192,18 +199,23 @@ namespace AZ { const auto view = GetDefaultView(); view->SetCameraTransform(AZ::Matrix3x4::CreateFromTransform(transform.GetOrthogonalized())); - m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix()); } void ViewportContext::SetDefaultView(ViewPtr view) { if (m_defaultView != view) { + m_onProjectionMatrixChangedHandler.Disconnect(); + m_onViewMatrixChangedHandler.Disconnect(); + m_defaultView = view; UpdatePipelineView(); m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix()); m_projectionMatrixChangedEvent.Signal(view->GetViewToClipMatrix()); + + view->ConnectWorldToViewMatrixChangedHandler(m_onViewMatrixChangedHandler); + view->ConnectWorldToClipMatrixChangedHandler(m_onProjectionMatrixChangedHandler); } }