Perform AABB test in the viewport space for renderers when not processing a 3D layer 13/263213/14
authorRichard Huang <r.huang@samsung.com>
Fri, 27 Aug 2021 17:26:18 +0000 (18:26 +0100)
committerRichard Huang <r.huang@samsung.com>
Thu, 16 Sep 2021 09:48:23 +0000 (09:48 +0000)
Change-Id: Ib95e9fb1a4c0c4dd7b8ef8260ab9cbe2f4c3c706

dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-item.cpp
dali/internal/render/common/render-item.h
dali/internal/render/common/render-manager.cpp
dali/internal/update/manager/render-instruction-processor.cpp

index 5998670..efcb575 100644 (file)
@@ -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))
       {
index c0e291f..5fb838d 100644 (file)
@@ -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]));
index c601267..d89ab22 100644 (file)
@@ -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.
index 3f240a9..91cb4c5 100644 (file)
@@ -613,7 +613,7 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>&
               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;
index 5488ab7..c4c2655 100644 (file)
@@ -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.