From 1d8c42f83a9803d65c01226636eac4d6f8faf133 Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Fri, 27 Aug 2021 18:26:18 +0100 Subject: [PATCH] Perform AABB test in the viewport space for renderers when not processing a 3D layer Change-Id: Ib95e9fb1a4c0c4dd7b8ef8260ab9cbe2f4c3c706 --- dali/internal/render/common/render-algorithms.cpp | 6 +- dali/internal/render/common/render-item.cpp | 8 +- dali/internal/render/common/render-item.h | 4 +- dali/internal/render/common/render-manager.cpp | 2 +- .../manager/render-instruction-processor.cpp | 111 ++++++++++++++++----- 5 files changed, 98 insertions(+), 33 deletions(-) diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 5998670..efcb575 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -389,7 +389,7 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Graphics::CommandBuffer& commandBuffer, const RenderInstruction& instruction, - int orientation) + int orientation) { // Get the number of child scissors in the stack (do not include layer or root box). size_t childStackDepth = mScissorStack.size() - 1u; @@ -429,7 +429,7 @@ inline void RenderAlgorithms::SetupScissorClipping( // This is a clipping node. We generate the AABB for this node and intersect it with the previous intersection further up the tree. // Get the AABB bounding box for the current render item. - const ClippingBox scissorBox(item.CalculateViewportSpaceAABB(item.mSize, mViewportRectangle.width, mViewportRectangle.height)); + const ClippingBox scissorBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mSize, mViewportRectangle.width, mViewportRectangle.height)); // Get the AABB for the parent item that we must intersect with. const ClippingBox& parentBox(mScissorStack.back()); @@ -625,7 +625,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& bool skip = true; if(!rootClippingRect.IsEmpty()) { - auto rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height); + auto rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height); if(rect.Intersect(rootClippingRect)) { diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp index c0e291f..5fb838d 100644 --- a/dali/internal/render/common/render-item.cpp +++ b/dali/internal/render/common/render-item.cpp @@ -55,7 +55,7 @@ RenderItem::RenderItem() RenderItem::~RenderItem() = default; -ClippingBox RenderItem::CalculateViewportSpaceAABB(const Vector3& size, const int viewportWidth, const int viewportHeight) const +ClippingBox RenderItem::CalculateViewportSpaceAABB(const Matrix& modelViewMatrix, const Vector3& size, const int viewportWidth, const int viewportHeight) { // Calculate extent vector of the AABB: const float halfActorX = size.x * 0.5f; @@ -68,9 +68,9 @@ ClippingBox RenderItem::CalculateViewportSpaceAABB(const Vector3& size, const in // We place the coords into the array in clockwise order, so we know opposite corners are always i + 2 from corner i. // We skip the 4th corner here as we can calculate that from the other 3, bypassing matrix multiplication. // Note: The below transform methods use a fast (2D) matrix multiply (only 4 multiplications are done). - Vector2 corners[4]{Transform2D(mModelViewMatrix, -halfActorX, -halfActorY), - Transform2D(mModelViewMatrix, halfActorX, -halfActorY), - Transform2D(mModelViewMatrix, halfActorX, halfActorY)}; + Vector2 corners[4]{Transform2D(modelViewMatrix, -halfActorX, -halfActorY), + Transform2D(modelViewMatrix, halfActorX, -halfActorY), + Transform2D(modelViewMatrix, halfActorX, halfActorY)}; // As we are dealing with a rectangle, we can do a fast calculation to get the 4th corner from knowing the other 3 (even if rotated). corners[3] = Vector2(corners[0] + (corners[2] - corners[1])); diff --git a/dali/internal/render/common/render-item.h b/dali/internal/render/common/render-item.h index c601267..d89ab22 100644 --- a/dali/internal/render/common/render-item.h +++ b/dali/internal/render/common/render-item.h @@ -60,11 +60,13 @@ struct RenderItem * * Note: We pass in the viewport dimensions rather than allow the caller to modify the raw AABB in order to optimally generate the final result. * + * @param[in] modelViewMatrix The model view matrix + * @param[in] size The size of the render item * @param[in] viewportWidth The width of the viewport to calculate for * @param[in] viewportHeight The height of the viewport to calculate for * @return The AABB coordinates in viewport-space (x, y, width, height) */ - ClippingBox CalculateViewportSpaceAABB(const Vector3& size, const int viewportWidth, const int viewportHeight) const; + static ClippingBox CalculateViewportSpaceAABB(const Matrix& modelViewMatrix, const Vector3& size, const int viewportWidth, const int viewportHeight); /** * Overriden delete operator. diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 3f240a9..91cb4c5 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -613,7 +613,7 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& item.mIsUpdated = false; item.mNode->SetUpdatedTree(false); - rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height); + rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mUpdateSize, viewportRect.width, viewportRect.height); if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty()) { const int left = rect.x; diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp index 5488ab7..c4c2655 100644 --- a/dali/internal/update/manager/render-instruction-processor.cpp +++ b/dali/internal/update/manager/render-instruction-processor.cpp @@ -137,6 +137,33 @@ bool CompareItems3DWithClipping(const RenderInstructionProcessor::SortAttributes } /** + * Set the update size of the node + * @param[in] node The node of the renderer + * @param[in] isLayer3d Whether we are processing a 3D layer or not + * @param[in,out] nodeWorldMatrix The world matrix of the node + * @param[in,out] nodeSize The size of the node + * @param[in,out] nodeUpdateSize The update size of the node + */ +inline void SetNodeUpdateSize(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector3& nodeUpdateSize) +{ + node->GetWorldMatrixAndSize(nodeWorldMatrix, nodeSize); + + if(node->GetUpdateSizeHint() == Vector3::ZERO) + { + // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform + // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be too slow + if(!isLayer3d && nodeWorldMatrix.GetZAxis() == Vector3(0.0f, 0.0f, 1.0f)) + { + nodeUpdateSize = nodeSize; + } + } + else + { + nodeUpdateSize = node->GetUpdateSizeHint(); + } +} + +/** * Add a renderer to the list * @param updateBufferIndex to read the model matrix from * @param renderList to add the item to @@ -144,6 +171,8 @@ bool CompareItems3DWithClipping(const RenderInstructionProcessor::SortAttributes * @param viewMatrix used to calculate modelview matrix for the item * @param camera The camera used to render * @param isLayer3d Whether we are processing a 3D layer or not + * @param viewportSet Whether the viewport is set or not + * @param viewport The viewport * @param cull Whether frustum culling is enabled or not */ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, @@ -152,21 +181,48 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, const Matrix& viewMatrix, SceneGraph::Camera& camera, bool isLayer3d, + bool viewportSet, + const Viewport& viewport, bool cull) { - bool inside(true); - Node* node = renderable.mNode; + bool inside(true); + Node* node = renderable.mNode; + Matrix nodeWorldMatrix(false); + Vector3 nodeSize; + Vector3 nodeUpdateSize; + bool nodeUpdateSizeSet(false); + Matrix nodeModelViewMatrix(false); + bool nodeModelViewMatrixSet(false); if(cull && renderable.mRenderer && !renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY)) { const Vector4& boundingSphere = node->GetBoundingSphere(); inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) && (camera.CheckSphereInFrustum(updateBufferIndex, Vector3(boundingSphere), boundingSphere.w)); + + if(inside && !isLayer3d && viewportSet) + { + SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize); + nodeUpdateSizeSet = true; + + const Vector3& scale = node->GetWorldScale(updateBufferIndex); + const Vector3& halfSize = nodeUpdateSize * scale * 0.5f; + float radius(halfSize.Length()); + + if(radius > Math::MACHINE_EPSILON_1000) + { + Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix); + nodeModelViewMatrixSet = true; + + ClippingBox clippingBox = RenderItem::CalculateViewportSpaceAABB(nodeModelViewMatrix, nodeUpdateSize, viewport.width, viewport.height); + inside = clippingBox.Intersects(viewport); + } + } } if(inside) { - Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *renderable.mNode) : Renderer::OPAQUE; + Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *node) : Renderer::OPAQUE; // We can skip render when node is not clipping and transparent const bool skipRender(opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED); @@ -183,22 +239,22 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, partialRenderingCacheInfo.node = node; partialRenderingCacheInfo.isOpaque = (opacityType == Renderer::OPAQUE); partialRenderingCacheInfo.renderer = renderable.mRenderer; - partialRenderingCacheInfo.color = renderable.mNode->GetColor(updateBufferIndex); - partialRenderingCacheInfo.depthIndex = renderable.mNode->GetDepthIndex(); + partialRenderingCacheInfo.color = node->GetColor(updateBufferIndex); + partialRenderingCacheInfo.depthIndex = node->GetDepthIndex(); if(renderable.mRenderer) { partialRenderingCacheInfo.textureSet = renderable.mRenderer->GetTextureSet(); } - item.mNode = renderable.mNode; + item.mNode = node; item.mIsOpaque = (opacityType == Renderer::OPAQUE); - item.mColor = renderable.mNode->GetColor(updateBufferIndex); + item.mColor = node->GetColor(updateBufferIndex); item.mDepthIndex = 0; if(!isLayer3d) { - item.mDepthIndex = renderable.mNode->GetDepthIndex(); + item.mDepthIndex = node->GetDepthIndex(); } if(DALI_LIKELY(renderable.mRenderer)) @@ -214,27 +270,23 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, item.mIsUpdated |= isLayer3d; - // Save ModelView matrix onto the item. - node->GetWorldMatrixAndSize(item.mModelMatrix, item.mSize); - Matrix::Multiply(item.mModelViewMatrix, item.mModelMatrix, viewMatrix); - - partialRenderingCacheInfo.matrix = item.mModelViewMatrix; - partialRenderingCacheInfo.size = item.mSize; - - if(renderable.mNode->GetUpdateSizeHint() == Vector3::ZERO) + if(!nodeUpdateSizeSet) { - // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform - // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be to slow - if(!isLayer3d && item.mModelMatrix.GetZAxis() == Vector3(0.0f, 0.0f, 1.0f)) - { - item.mUpdateSize = item.mSize; - } + SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize); } - else + + item.mSize = nodeSize; + item.mUpdateSize = nodeUpdateSize; + item.mModelMatrix = nodeWorldMatrix; + + if(!nodeModelViewMatrixSet) { - item.mUpdateSize = renderable.mNode->GetUpdateSizeHint(); + Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix); } + item.mModelViewMatrix = nodeModelViewMatrix; + partialRenderingCacheInfo.matrix = item.mModelViewMatrix; + partialRenderingCacheInfo.size = item.mSize; partialRenderingCacheInfo.updatedSize = item.mUpdateSize; item.mIsUpdated = partialRenderingData.IsUpdated() || item.mIsUpdated; @@ -265,6 +317,8 @@ inline void AddRenderersToRenderList(BufferIndex updateBufferIndex, const Matrix& viewMatrix, SceneGraph::Camera& camera, bool isLayer3d, + bool viewportSet, + const Viewport& viewport, bool cull) { DALI_LOG_INFO(gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n"); @@ -277,6 +331,8 @@ inline void AddRenderersToRenderList(BufferIndex updateBufferIndex, viewMatrix, camera, isLayer3d, + viewportSet, + viewport, cull); } } @@ -446,6 +502,9 @@ void RenderInstructionProcessor::Prepare(BufferIndex updateBuffe const Matrix& viewMatrix = renderTask.GetViewMatrix(updateBufferIndex); SceneGraph::Camera& camera = renderTask.GetCamera(); + Viewport viewport; + bool viewportSet = renderTask.QueryViewport(updateBufferIndex, viewport); + const SortedLayersIter endIter = sortedLayers.end(); for(SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter) { @@ -473,6 +532,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex updateBuffe viewMatrix, camera, isLayer3D, + viewportSet, + viewport, cull); // We only use the clipping version of the sort comparitor if any clipping nodes exist within the RenderList. @@ -495,6 +556,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex updateBuffe viewMatrix, camera, isLayer3D, + viewportSet, + viewport, cull); // Clipping hierarchy is irrelevant when sorting overlay items, so we specify using the non-clipping version of the sort comparitor. -- 2.7.4