]> OCCT Git - occt.git/commitdiff
0033607: Visualization - Implementation of hardware occlusion queries
authorhossamali <Hossam.Ali@opencascade.com>
Fri, 23 Feb 2024 11:45:34 +0000 (11:45 +0000)
committerhossamali <Hossam.Ali@opencascade.com>
Fri, 8 Mar 2024 10:54:00 +0000 (10:54 +0000)
Hardware occlusion queries provides mechanism to answer whether or not
any pixels would be drawn. as instance it can be used as visibility filter
or acceleration for rendering complex scenes, by skipping occluded objects.

Graphic3d_ViewOcclusionMask : Provide way to access occlusion test results
for every graphical presentation per each defined view of the viewer

Graphic3d_OcclusionQuery : provides generic access to occlusion query
functionality.

OpenGl_OcclusionQuery: provides OpenGL implementation for occlusion query

Graphic3d_RenderingParams:  provides way to enable or disable occlusion query

AIS_InteractiveContext : reset view occlusion mask in new loaded objects

Each view invalidate its occlusion query results if camera has changed.

28 files changed:
src/AIS/AIS_InteractiveContext.cxx
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_CStructure.hxx
src/Graphic3d/Graphic3d_CView.cxx
src/Graphic3d/Graphic3d_CView.hxx
src/Graphic3d/Graphic3d_FrameStatsTimer.hxx
src/Graphic3d/Graphic3d_OcclusionQuery.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_OcclusionQuery.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_RenderingParams.cxx
src/Graphic3d/Graphic3d_RenderingParams.hxx
src/Graphic3d/Graphic3d_ViewOcclusionMask.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_ViewOcclusionMask.hxx [new file with mode: 0644]
src/OpenGl/FILES
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_LayerList.hxx
src/OpenGl/OpenGl_OcclusionQuery.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_OcclusionQuery.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/PrsMgr/PrsMgr_PresentableObject.cxx
src/PrsMgr/PrsMgr_PresentableObject.hxx
src/PrsMgr/PrsMgr_PresentationManager.cxx
src/V3d/V3d_Trihedron.cxx
src/V3d/V3d_Viewer.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/occlusion/boxes [new file with mode: 0644]

index 13344563e90509b028edbf6b301ca7d8edb7ee76..044180b01dcdc7559004fc25af6ce3cc47c006bf 100644 (file)
@@ -438,6 +438,7 @@ void AIS_InteractiveContext::Display (const Handle(AIS_InteractiveObject)& theIO
   {
     setObjectStatus (theIObj, PrsMgr_DisplayStatus_Displayed, theDispMode, theSelectionMode);
     theIObj->ViewAffinity()->SetVisible (true); // reset view affinity mask
+    theIObj->ViewOcclusionMask()->SetVisible (true); // reset view occlusion mask
     myMainVwr->StructureManager()->RegisterObject (theIObj, theIObj->ViewAffinity());
     myMainPM->Display(theIObj, theDispMode);
     if (theSelectionMode != -1)
@@ -515,6 +516,7 @@ void AIS_InteractiveContext::Load (const Handle(AIS_InteractiveObject)& theIObj,
     GetDefModes (theIObj, aDispMode, aHiMod, aSelModeDef);
     setObjectStatus (theIObj, PrsMgr_DisplayStatus_Erased, aDispMode, theSelMode != -1 ? theSelMode : aSelModeDef);
     theIObj->ViewAffinity()->SetVisible (true); // reset view affinity mask
+    theIObj->ViewOcclusionMask()->SetVisible (true); // reset view occlusion mask
     myMainVwr->StructureManager()->RegisterObject (theIObj, theIObj->ViewAffinity());
   }
 
index ec1f20b4df2905a952d6b81f232ed5c624cf28f0..f83c2db19f783c88f5cafc752d84727b18f97c5c 100755 (executable)
@@ -208,3 +208,7 @@ Graphic3d_Layer.cxx
 Graphic3d_Layer.hxx
 Graphic3d_ZLayerId.hxx
 Graphic3d_ZLayerSettings.hxx
+Graphic3d_OcclusionQuery.hxx
+Graphic3d_OcclusionQuery.cxx
+Graphic3d_ViewOcclusionMask.hxx
+Graphic3d_ViewOcclusionMask.cxx
index 8138cd165f3afc27c48b76d762decece23dc2f5d..0a4f2344a762aa5d7f5b474b53dbe7d4abb0c1e6 100644 (file)
@@ -22,6 +22,7 @@
 #include <Graphic3d_ViewAffinity.hxx>
 #include <Graphic3d_TransformPers.hxx>
 #include <Graphic3d_ZLayerId.hxx>
+#include <Graphic3d_ViewOcclusionMask.hxx>
 #include <TopLoc_Datum3D.hxx>
 #include <NCollection_IndexedMap.hxx>
 
@@ -164,6 +165,17 @@ public:
   //! The method is called during traverse of BVH tree.
   void MarkAsNotCulled() const { myIsCulled = Standard_False; }
 
+  //! Returns True if the structure occulded in specified view, otherwise
+  //! returns False.
+  Standard_Boolean IsOccluded(const Standard_Integer theViewId) const {
+    return (!OcclusionMask->IsVisible(theViewId));
+  }
+
+  //! Marks structure as Occluded by other strcuture in specified view,!
+  void SetOccluded(const Standard_Integer theViewId) const {
+    OcclusionMask->SetVisible(Standard_False, theViewId);
+  }
+
   //! Returns whether check of object's bounding box clipping is enabled before drawing of object; TRUE by default.
   Standard_Boolean BndBoxClipCheck() const { return myBndBoxClipCheck; }
 
@@ -218,6 +230,7 @@ public:
 public:
 
   Handle(Graphic3d_ViewAffinity) ViewAffinity; //!< view affinity mask
+  Handle(Graphic3d_ViewOcclusionMask) OcclusionMask; //!< view occlusion mask
 
 protected:
 
index 59e0ee75a9f373e8d5ee4a256f20ed4629e3609f..d396e3bf80664a20ecf3a54fe04682648e28ccd5 100644 (file)
@@ -547,6 +547,19 @@ void Graphic3d_CView::DisplayedStructures (Graphic3d_MapOfStructure& theStructur
   }
 }
 
+// =======================================================================
+// function : OccludedStructures
+// purpose  :
+// =======================================================================
+void Graphic3d_CView::OccludedStructures(Graphic3d_MapOfStructure& theStructures) const
+{
+  for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
+  {
+
+    if (aStructIter.Value()->CStructure()->IsOccluded(this->myId))
+      theStructures.Add(aStructIter.Key());
+  }
+}
 // =======================================================================
 // function : MinMaxValues
 // purpose  :
index 5fe56d44677ac8313f6229f37303f7bdd88ff520..53351b7c08c275269285af84988fe23ee53154ee 100644 (file)
@@ -130,6 +130,9 @@ public:
   //! Returns the set of structures displayed in this view.
   Standard_EXPORT void DisplayedStructures (Graphic3d_MapOfStructure& theStructures) const;
 
+  //! Returns number of occluded strcutures in the view
+  Standard_EXPORT void OccludedStructures(Graphic3d_MapOfStructure& theStructures) const;
+
   //! Returns number of displayed structures in the view.
   virtual Standard_Integer NumberOfDisplayedStructures() const { return myStructsDisplayed.Extent(); }
 
index a4aff6fa0af049b4217998b015363fc5ded4ee27..7650c618b6552812f1aef8146a0f099cde3ad2fe 100644 (file)
@@ -22,7 +22,8 @@ enum Graphic3d_FrameStatsTimer
   Graphic3d_FrameStatsTimer_CpuCulling,
   Graphic3d_FrameStatsTimer_CpuPicking,
   Graphic3d_FrameStatsTimer_CpuDynamics,
+  Graphic3d_FrameStatsTimer_OcclusionCulling,
 };
-enum { Graphic3d_FrameStatsTimer_NB = Graphic3d_FrameStatsTimer_CpuDynamics + 1 };
+enum { Graphic3d_FrameStatsTimer_NB = Graphic3d_FrameStatsTimer_OcclusionCulling + 1 };
 
 #endif // _Graphic3d_FrameStatsTimer_HeaderFile
diff --git a/src/Graphic3d/Graphic3d_OcclusionQuery.cxx b/src/Graphic3d/Graphic3d_OcclusionQuery.cxx
new file mode 100644 (file)
index 0000000..1df0447
--- /dev/null
@@ -0,0 +1,49 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Graphic3d_OcclusionQuery.hxx>
+
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_OcclusionQuery, Standard_Transient)
+
+// =======================================================================
+// function : GetNumSamplesPassed
+// purpose  :
+// =======================================================================
+unsigned int Graphic3d_OcclusionQuery::GetNumSamplesPassed() const {
+  return samplesPassed;
+}
+
+// =======================================================================
+// function : AnySamplesPassed
+// purpose  :
+// =======================================================================
+bool Graphic3d_OcclusionQuery::AnySamplesPassed() const {
+  return samplesPassed > 0;
+}
+
+// =======================================================================
+// function : DumpJson
+// purpose  :
+// =======================================================================
+void Graphic3d_OcclusionQuery::DumpJson(Standard_OStream &theOStream,
+                                        Standard_Integer) const {
+  OCCT_DUMP_TRANSIENT_CLASS_BEGIN(theOStream)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, queryID)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, samplesPassed)
+}
\ No newline at end of file
diff --git a/src/Graphic3d/Graphic3d_OcclusionQuery.hxx b/src/Graphic3d/Graphic3d_OcclusionQuery.hxx
new file mode 100644 (file)
index 0000000..a0426f0
--- /dev/null
@@ -0,0 +1,59 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_OcclusionQuery_HeaderFile
+#define _Graphic3d_OcclusionQuery_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+//! Base class provides access to occlusion query functionality.
+class Graphic3d_OcclusionQuery : public Standard_Transient {
+public:
+  //! Empty constructor.
+  Graphic3d_OcclusionQuery() : queryID(0), samplesPassed(0) {}
+
+  //! Begins occlusion query. Until the query is ended, samples that pass the
+  //! rendering pipeline are counted.
+  Standard_EXPORT virtual void BeginQuery() const = 0;
+
+  //! Ends occlusion query and caches the result - number of samples that passed
+  //! the rendering pipeline.
+  Standard_EXPORT virtual void EndQuery() = 0;
+
+  //! Gets number of samples that have passed the rendering pipeline.
+  unsigned int GetNumSamplesPassed() const;
+
+  //! Helper method that returns if any samples have passed the rendering
+  //! pipeline.
+  bool AnySamplesPassed() const;
+
+  //! Dumps the content of me into the stream
+  Standard_EXPORT void DumpJson(Standard_OStream &theOStream,
+                                Standard_Integer theDepth = -1) const;
+
+protected:
+  unsigned int queryID; // Query object ID
+  int samplesPassed;    // Number of samples passed in last query
+
+public:
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_OcclusionQuery, Standard_Transient)
+};
+
+DEFINE_STANDARD_HANDLE(Graphic3d_OcclusionQuery, Standard_Transient)
+
+#endif // _Graphic3d_OcclusionQuery_HeaderFile
index 57a941386f423782f2a420a44f9248be1198fb0d..1b2d3789b508b7b8c8b9c2b828bd13776bbd80b9 100644 (file)
@@ -65,6 +65,7 @@ void Graphic3d_RenderingParams::DumpJson (Standard_OStream& theOStream, Standard
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, CameraApertureRadius)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, CameraFocalPlaneDist)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, FrustumCullingState)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, OcculsionQueryState)
   
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, ToneMappingMethod)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Exposure)
index d0ce9217c2fda8d6c11b4f30f1bcf50ccf60b33c..4bc1374bd9ced9f08052e2b27045334c2ecbb940 100644 (file)
@@ -92,6 +92,14 @@ public:
     FrustumCulling_NoUpdate //!< culling is active, but the list of culled entities is not updated
   };
 
+  //! State of occulsion query
+  enum OcculsionQuery
+  {
+    OcculsionQuery_Off,     //!< occulsion query is disabled
+    OcculsionQuery_On,      //!< occulsion query is active
+    OcculsionQuery_NoUpdate //!< occulsion query is active, but the list of occulded entities is not updated
+  };
+
 public:
 
   //! Creates default rendering parameters.
@@ -139,6 +147,7 @@ public:
     CameraApertureRadius        (0.0f),
     CameraFocalPlaneDist        (1.0f),
     FrustumCullingState         (FrustumCulling_On),
+    OcculsionQueryState         (OcculsionQuery_Off),
     ToneMappingMethod           (Graphic3d_ToneMappingMethod_Disabled),
     Exposure                    (0.f),
     WhitePoint                  (1.f),
@@ -249,6 +258,7 @@ public: //! @name Ray-Tracing/Path-Tracing parameters
   Standard_ShortReal                CameraApertureRadius;        //!< aperture radius of perspective camera used for depth-of-field, 0.0 by default (no DOF) (path tracing only)
   Standard_ShortReal                CameraFocalPlaneDist;        //!< focal  distance of perspective camera used for depth-of field, 1.0 by default (path tracing only)
   FrustumCulling                    FrustumCullingState;         //!< state of frustum culling optimization; FrustumCulling_On by default
+  OcculsionQuery                    OcculsionQueryState;         //!< state of occulsion query; OcculsionQuery_OFF by default
 
   Graphic3d_ToneMappingMethod       ToneMappingMethod;           //!< specifies tone mapping method for path tracing, Graphic3d_ToneMappingMethod_Disabled by default
   Standard_ShortReal                Exposure;                    //!< exposure value used for tone mapping (path tracing), 0.0 by default
diff --git a/src/Graphic3d/Graphic3d_ViewOcclusionMask.cxx b/src/Graphic3d/Graphic3d_ViewOcclusionMask.cxx
new file mode 100644 (file)
index 0000000..b7e88cb
--- /dev/null
@@ -0,0 +1,32 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Graphic3d_ViewOcclusionMask.hxx>
+
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ViewOcclusionMask, Standard_Transient)
+
+// =======================================================================
+// function : DumpJson
+// purpose  :
+// =======================================================================
+void Graphic3d_ViewOcclusionMask::DumpJson(Standard_OStream &theOStream,
+                                       Standard_Integer) const {
+  OCCT_DUMP_TRANSIENT_CLASS_BEGIN(theOStream)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, myMask)
+}
\ No newline at end of file
diff --git a/src/Graphic3d/Graphic3d_ViewOcclusionMask.hxx b/src/Graphic3d/Graphic3d_ViewOcclusionMask.hxx
new file mode 100644 (file)
index 0000000..d71f245
--- /dev/null
@@ -0,0 +1,78 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_ViewOcclusionMask_HeaderFile
+#define _Graphic3d_ViewOcclusionMask_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+//! Structure display state.
+class Graphic3d_ViewOcclusionMask : public Standard_Transient
+{
+public:
+
+  //! Empty constructor.
+  Graphic3d_ViewOcclusionMask()
+  {
+    SetVisible (Standard_True);
+  }
+
+  //! Return visibility flag.
+  bool IsVisible (const Standard_Integer theViewId) const
+  {
+    const unsigned int aBit = 1 << theViewId;
+    return (myMask & aBit) != 0;
+  }
+
+  //! Setup visibility flag for all views.
+  void SetVisible (const Standard_Boolean theIsVisible)
+  {
+    ::memset (&myMask, theIsVisible ? 0xFF : 0x00, sizeof(myMask));
+  }
+
+  //! Setup visibility flag.
+  void SetVisible (const Standard_Integer theViewId,
+                   const bool             theIsVisible)
+  {
+    const unsigned int aBit = 1 << theViewId;
+    if (theIsVisible)
+    {
+      myMask |=  aBit;
+    }
+    else
+    {
+      myMask &= ~aBit;
+    }
+  }
+
+  //! Dumps the content of me into the stream
+  Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
+private:
+
+  unsigned int myMask; //!< affinity mask
+
+public:
+
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_ViewOcclusionMask,Standard_Transient)
+
+};
+
+DEFINE_STANDARD_HANDLE(Graphic3d_ViewOcclusionMask, Standard_Transient)
+
+#endif // _Graphic3d_ViewOcclusionMask_HeaderFile
index 990a8816504b1cb3535133eadcd694ded9897b24..291dfc2a6e2c902f970e038a0ff6878a5f4ab2ea 100755 (executable)
@@ -153,3 +153,5 @@ OpenGl_TextBuilder.hxx
 OpenGl_TextBuilder.cxx
 OpenGl_HaltonSampler.hxx
 OpenGl_ShaderProgramDumpLevel.hxx
+OpenGl_OcclusionQuery.hxx
+OpenGl_OcclusionQuery.cxx
index 52a494d0e2bc200e36a87f0a6218651cc11784f3..54983a99ebcf372f1a98431142158844be7211f6 100644 (file)
@@ -871,6 +871,98 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
   theWorkspace->SetRenderFilter (aPrevFilter);
 }
 
+//=======================================================================
+//function : updateOcclusion
+//purpose  : update Occlsuion state for each struct in each layer 
+//=======================================================================
+void OpenGl_LayerList::UpdateOcclusion( const Handle(OpenGl_Workspace) & theWorkspace,
+                                        const Standard_Boolean theToDrawImmediate,
+                                        const OpenGl_FrameBuffer *theReadDrawFbo,
+                                        const OpenGl_FrameBuffer *theOitAccumFbo)
+{
+  const Handle(OpenGl_Context) &aCtx = theWorkspace->GetGlContext();
+  aCtx->core11fwd->glEnable(GL_DEPTH_TEST);
+  aCtx->core11fwd->glDepthFunc (GL_LESS);
+
+
+  // Remember global settings for glDepth mask and write mask
+  GLboolean aPrevColorMask;
+  GLboolean aPrevDepthMask;
+  aCtx->core11fwd->glGetBooleanv(GL_COLOR_WRITEMASK, &aPrevColorMask);
+  aCtx->core11fwd->glGetBooleanv(GL_DEPTH_WRITEMASK, &aPrevDepthMask);
+
+  // Turn off writing to depth and color buffers 
+  aCtx->core11fwd->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+  aCtx->core11fwd->glDepthMask(GL_FALSE);
+
+  // Start record occlusion test computational cost  
+  const Handle(OpenGl_FrameStats) &aStats = theWorkspace->GetGlContext()->FrameStats();
+  OSD_Timer &aTimer = aStats->ActiveDataFrame().ChangeTimer( Graphic3d_FrameStatsTimer_OcclusionCulling);
+  aTimer.Start();
+
+  // Loop for all layers
+  for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter(myLayers);
+       aLayerIter.More(); aLayerIter.Next()) {
+
+    const Handle(Graphic3d_Layer) &aLayer = aLayerIter.ChangeValue();
+
+    // Exclude frustum culled layer
+    if (aLayer->IsCulled())
+      continue;
+
+    /// TODO Change below to Graphic3d_Query
+    GLuint query_ID;
+    GLint samplesPassed;
+    
+    aCtx->core20->glGenQueries(1, &query_ID);
+
+    // Render priority list
+    const Standard_Integer aViewId = theWorkspace->View()->Identification();
+
+    for (Standard_Integer aPriorityIter = Graphic3d_DisplayPriority_Bottom; aPriorityIter <= Graphic3d_DisplayPriority_Topmost; ++aPriorityIter) 
+    {
+      const Graphic3d_IndexedMapOfStructure &aStructures = aLayer->Structures((Graphic3d_DisplayPriority)aPriorityIter);
+      for (OpenGl_Structure::StructIterator aStructIter(aStructures); aStructIter.More(); aStructIter.Next()) 
+      {
+        const OpenGl_Structure *aStruct = aStructIter.Value();  
+       
+        // Exclude view frustum culled structs
+        if (aStruct->IsCulled() || !aStruct->IsVisible(aViewId))
+          continue;
+        
+        // Begin occlusion query 
+        aCtx->core20->glBeginQuery(GL_SAMPLES_PASSED, query_ID);
+
+        // Dry rendering for conservative approximation of the complex object
+        aStruct->RenderOccluder(theWorkspace);
+
+        // End query and count no of samples 
+        aCtx->core20->glEndQuery(GL_SAMPLES_PASSED);
+        aCtx->core20->glGetQueryObjectiv(query_ID, GL_QUERY_RESULT, &samplesPassed);        
+        
+        if (samplesPassed <= 0)
+          aStruct->SetOccluded(aViewId);
+    
+        std::cout << "layerID: " << aLayer->LayerId()
+                  << " structureID: " << aStruct->Identification()
+                  << " clocation: " << aStruct->BoundingBox().Center().z()
+                  << " queryID: " << query_ID
+                  << " sample passsed : " << samplesPassed << std::endl;
+        samplesPassed=0;
+      }
+    }
+    // Release query resources
+    aCtx->core20->glDeleteQueries(1, &query_ID);
+  }
+
+  // Back to prev settings 
+  aCtx->core11fwd->glDepthMask(aPrevDepthMask);
+  aCtx->core11fwd->glColorMask(aPrevColorMask, aPrevColorMask, aPrevColorMask, aPrevColorMask);
+
+  aTimer.Stop();
+  aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
+}
+
 //=======================================================================
 //function : renderTransparent
 //purpose  : Render transparent objects using blending operator.
index 442364334dd1c2b9ac5cd2fcc8041473cba1c1e6..00235c48b40e0b984a4c71524a603c3c36f018fd 100644 (file)
@@ -106,6 +106,12 @@ public:
                                OpenGl_FrameBuffer*             theReadDrawFbo,
                                OpenGl_FrameBuffer*             theOitAccumFbo) const;
 
+  //! Update occlusion test
+  Standard_EXPORT void UpdateOcclusion(const Handle(OpenGl_Workspace) & theWorkspace,
+                                       const Standard_Boolean theToDrawImmediate,
+                                       const OpenGl_FrameBuffer *theReadDrawFbo,
+                                       const OpenGl_FrameBuffer *theOitAccumFbo);
+
   //! Returns the set of OpenGL Z-layers.
   const NCollection_List<Handle(Graphic3d_Layer)>& Layers() const { return myLayers; }
 
diff --git a/src/OpenGl/OpenGl_OcclusionQuery.cxx b/src/OpenGl/OpenGl_OcclusionQuery.cxx
new file mode 100644 (file)
index 0000000..325d8e1
--- /dev/null
@@ -0,0 +1,59 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include "OpenGl_OcclusionQuery.hxx"
+
+#include <OpenGl_Context.hxx>
+#include <OpenGl_GlCore15.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_OcclusionQuery, Graphic3d_OcclusionQuery)
+
+// =======================================================================
+// function :
+// purpose  :
+// =======================================================================
+Standard_EXPORT
+OpenGl_OcclusionQuery::OpenGl_OcclusionQuery(const Handle(OpenGl_Context) &
+                                             theCtx)
+    : aCtx(theCtx) {
+  aCtx->core15->glGenQueries(1, &queryID);
+}
+
+// =======================================================================
+// function :
+// purpose  :
+// =======================================================================
+Standard_EXPORT OpenGl_OcclusionQuery::~OpenGl_OcclusionQuery() {
+  aCtx->core15->glDeleteQueries(1, &queryID);
+  queryID = 0;
+}
+
+// =======================================================================
+// function : BeginQuery()
+// purpose  :
+// =======================================================================
+Standard_EXPORT void OpenGl_OcclusionQuery::BeginQuery() const {
+  aCtx->core15->glBeginQuery(GL_SAMPLES_PASSED, queryID);
+}
+
+// =======================================================================
+// function : EndQuery()
+// purpose  :
+// =======================================================================
+Standard_EXPORT void OpenGl_OcclusionQuery::EndQuery() {
+  aCtx->core15->glEndQuery(GL_SAMPLES_PASSED);
+  aCtx->core15->glGetQueryObjectiv(queryID, GL_QUERY_RESULT, &samplesPassed);
+}
diff --git a/src/OpenGl/OpenGl_OcclusionQuery.hxx b/src/OpenGl/OpenGl_OcclusionQuery.hxx
new file mode 100644 (file)
index 0000000..e2cee43
--- /dev/null
@@ -0,0 +1,51 @@
+// Created on: 2024-02-20
+// Created by: Hossam Ali
+// Copyright (c) 2024 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in
+// OCCT distribution for complete text of the license and disclaimer of any
+// warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef OpenGl_View_HeaderFile
+#define OpenGl_View_HeaderFile
+
+#include <Graphic3d_OcclusionQuery.hxx>
+
+class OpenGl_Context;
+
+DEFINE_STANDARD_HANDLE(OpenGl_OcclusionQuery, Graphic3d_OcclusionQuery)
+
+//! Implementation of OpenGl view.
+class OpenGl_OcclusionQuery : public Graphic3d_OcclusionQuery {
+
+public:
+  //! Constructor.
+  Standard_EXPORT OpenGl_OcclusionQuery(const Handle(OpenGl_Context) & theCtx);
+
+  //! Default destructor.
+  Standard_EXPORT virtual ~OpenGl_OcclusionQuery();
+
+  //! Begins occlusion query.
+  Standard_EXPORT virtual void BeginQuery() const Standard_OVERRIDE;
+
+  //! Ends occlusion query and caches the result
+  Standard_EXPORT virtual void EndQuery() Standard_OVERRIDE;
+
+public:
+  DEFINE_STANDARD_ALLOC
+  DEFINE_STANDARD_RTTIEXT(OpenGl_OcclusionQuery,
+                          Graphic3d_OcclusionQuery) // Type definition
+
+private:
+  const Handle(OpenGl_Context) & aCtx;
+};
+
+#endif // _OpenGl_View_Header
index d5c3c5270b2ca11955d8c346a34325eeb7a5b7f8..a89cf7eed62a7d6bf6be278ce27b2454bf127d60 100644 (file)
@@ -626,6 +626,17 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
 }
 
+// =======================================================================
+// function : RenderOccluder 
+// purpose  : 
+// =======================================================================
+void OpenGl_Structure::RenderOccluder(const Handle(OpenGl_Workspace)& theWorkspace) const 
+{
+  const Handle(OpenGl_Context) &aCtx = theWorkspace->GetGlContext();
+  aCtx->ApplyModelViewMatrix();
+  renderBoundingBox(theWorkspace);
+}
+
 // =======================================================================
 // function : Release
 // purpose  :
index b7703237831efe8a7a52aef5cbd76ddbf7deb061..d9f98204910df08405eb90e5024345781e78b1c3 100644 (file)
@@ -96,6 +96,9 @@ public:
   //! Renders the structure.
   Standard_EXPORT virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const;
 
+  //! Render Occluder presenation of this structure 
+  Standard_EXPORT void RenderOccluder(const Handle(OpenGl_Workspace)& theWorkspace) const;
+  
   //! Releases structure resources.
   Standard_EXPORT virtual void Release (const Handle(OpenGl_Context)& theGlCtx);
 
index 790779556779e7b528070c0260fd90a6d41729f5..87d0b920703cd290bc009fed7b69d7448d7cc26d 100644 (file)
@@ -1766,7 +1766,7 @@ void OpenGl_View::Redraw()
     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
                          aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
-
+    
     redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]);
     myBackBufferRestored = Standard_True;
     myIsImmediateDrawn   = Standard_False;
@@ -2129,8 +2129,8 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection,
   aCtx->core11fwd->glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), aCtx->caps->buffersOpaqueAlpha ? 1.0f : 0.0f);
   aCtx->core11fwd->glClear (toClear);
   aCtx->SetColorMask (true); // restore default alpha component write state
-
-  render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False);
+  
+    render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False);
 }
 
 // =======================================================================
@@ -2407,6 +2407,10 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
   {
     myAccumFrames = 0;
     myWorldViewProjState = aWVPState;
+
+    // Invalidiate occlusion query if camera has changed.
+    if (myRenderParams.OcculsionQueryState == Graphic3d_RenderingParams::OcculsionQuery_On)
+      myRenderParams.OcculsionQueryState = Graphic3d_RenderingParams::OcculsionQuery_NoUpdate;
   }
 
   myLocalOrigin.SetCoord (0.0, 0.0, 0.0);
@@ -2534,6 +2538,19 @@ void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
   myZLayers.InvalidateBVHData (theLayerId);
 }
 
+//=======================================================================
+//function : updateOcclusionState
+//purpose  :
+//=======================================================================
+void OpenGl_View::updateOcclusion(OpenGl_FrameBuffer*          theReadDrawFbo,
+                                  OpenGl_FrameBuffer*          theOitAccumFbo,
+                                  const Standard_Boolean       theToDrawImmediate)
+{
+  myZLayers.UpdateOcclusion(myWorkspace, theToDrawImmediate,theReadDrawFbo, theOitAccumFbo);
+  // re-validate occlusion results  
+  myRenderParams.OcculsionQueryState = Graphic3d_RenderingParams::OcculsionQuery_On;
+}
 //=======================================================================
 //function : renderStructs
 //purpose  :
@@ -2547,13 +2564,17 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
   {
     return;
   }
-
+    
   myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
   if (myZLayers.NbStructures() <= 0)
   {
     return;
   }
 
+  // update occlusion here after update culling to ensure the frusrum culling updated
+  if (myRenderParams.OcculsionQueryState == Graphic3d_RenderingParams::OcculsionQuery_NoUpdate)
+    updateOcclusion(theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
+
   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
   Standard_Boolean toRenderGL = theToDrawImmediate ||
     myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
index 17768a06d13b2e91ac03685fbd68db8d339c1dde..c2051252ade01f523b1faaa8b4d4775498ba0504 100644 (file)
@@ -380,6 +380,14 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
   Standard_EXPORT virtual void drawBackground (const Handle(OpenGl_Workspace)& theWorkspace,
                                                Graphic3d_Camera::Projection theProjection);
 
+  //! Update occlusion state for the set of structures presented in the view  
+  //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
+  //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process.
+  //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode.
+  Standard_EXPORT virtual void updateOcclusion(OpenGl_FrameBuffer*    theReadDrawFbo,
+                                              OpenGl_FrameBuffer*    theOitAccumFbo,
+                                              const Standard_Boolean       theToDrawImmediate);
+
   //! Render set of structures presented in the view.
   //! @param theProjection [in] the projection that is used for rendering.
   //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
@@ -389,7 +397,7 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
                                               OpenGl_FrameBuffer*    theReadDrawFbo,
                                               OpenGl_FrameBuffer*    theOitAccumFbo,
                                               const Standard_Boolean theToDrawImmediate);
-
+  
   //! Renders trihedron.
   void renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace);
 
index b723891b86eb805c4a092ef281cb6d1abba38d5d..8d540a8bbb8a84766442be81bb7ada0ebbab0d66 100644 (file)
@@ -46,6 +46,7 @@ const gp_Trsf& PrsMgr_PresentableObject::getIdentityTrsf()
 PrsMgr_PresentableObject::PrsMgr_PresentableObject (const PrsMgr_TypeOfPresentation3d theType)
 : myParent (NULL),
   myViewAffinity (new Graphic3d_ViewAffinity()),
+  myViewOcclusionMask(new Graphic3d_ViewOcclusionMask()),
   myDrawer (new Prs3d_Drawer()),
   myTypeOfPresentation3d (theType),
   myDisplayStatus (PrsMgr_DisplayStatus_None),
index bf739ef2b903523bdfefe8016ff843e0a3648257..0ad92e01a234d352a5c6bf3ce0b26c796935dde2 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <Aspect_TypeOfFacingModel.hxx>
 #include <gp_GTrsf.hxx>
+#include <Graphic3d_ViewOcclusionMask.hxx>
 #include <Graphic3d_ClipPlane.hxx>
 #include <Prs3d_Drawer.hxx>
 #include <PrsMgr_ListOfPresentableObjects.hxx>
@@ -72,6 +73,9 @@ public:
 
   //! Return view affinity mask.
   const Handle(Graphic3d_ViewAffinity)& ViewAffinity() const { return myViewAffinity; }
+  
+  //! Return view occlusion mask.
+  const Handle(Graphic3d_ViewOcclusionMask)& ViewOcclusionMask() const { return myViewOcclusionMask; }
 
   //! Returns true if the Interactive Object has display mode setting overriding global setting (within Interactive Context).
   Standard_Boolean HasDisplayMode() const { return myDrawer->DisplayMode() != -1; }
@@ -522,6 +526,7 @@ protected:
   PrsMgr_PresentableObject*              myParent;                  //!< pointer to the parent object
   PrsMgr_Presentations                   myPresentations;           //!< list of presentations
   Handle(Graphic3d_ViewAffinity)         myViewAffinity;            //!< view affinity mask
+  Handle(Graphic3d_ViewOcclusionMask)    myViewOcclusionMask;       //!< view occlusion mask
   Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes;              //!< sequence of object-specific clipping planes
   Handle(Prs3d_Drawer)                   myDrawer;                  //!< main presentation attributes
   Handle(Prs3d_Drawer)                   myHilightDrawer;           //!< (optional) custom presentation attributes for highlighting selected object
index 09f5a5bffee0d6e127b8c7cf10a214bfd96beaea..28fbcc299b316bf9ed98c0f51e1424db1fa7dc35 100644 (file)
@@ -395,6 +395,7 @@ void PrsMgr_PresentationManager::displayImmediate (const Handle(V3d_Viewer)& the
       {
         aShadowPrs->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
         aShadowPrs->CStructure()->ViewAffinity->SetVisible (Standard_False);
+        aShadowPrs->CStructure()->OcclusionMask =new Graphic3d_ViewOcclusionMask();
         aShadowPrs->Display();
       }
 
@@ -522,6 +523,10 @@ Handle(PrsMgr_Presentation) PrsMgr_PresentationManager::Presentation (const Hand
   thePrsObj->Presentations().Append (aPrs);
   thePrsObj->Fill (this, aPrs, theMode);
 
+  // update object occlusion state by passing occlusion state handle to
+  // underlaying graphic strcutures
+  aPrs->CStructure()->OcclusionMask = thePrsObj->ViewOcclusionMask();
+
   // set layer index accordingly to object's presentations
   aPrs->SetUpdateStatus (Standard_False);
   return aPrs;
index 29c04ba8c3f432e22a726890a90e3e2f0f31c025..5c457d3d15ae4be4e8864264e82cc8c8fa82e94d 100644 (file)
@@ -256,6 +256,7 @@ void V3d_Trihedron::Display (const V3d_View& theView)
     myStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
     myStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
     myStructure->CStructure()->ViewAffinity->SetVisible (theView.View()->Identification(), true);
+    myStructure->CStructure()->OcclusionMask = new Graphic3d_ViewOcclusionMask();
     myToCompute = Standard_True;
   }
   if (myToCompute)
index 896d612d0bc70e97a1de46ae61b78a77a27f8bc9..2e9fe9ba8cd224c25a851fa27e6fde0754c5f27e 100644 (file)
@@ -879,6 +879,7 @@ void V3d_Viewer::ShowGridEcho (const Handle(V3d_View)& theView,
   myGridEchoStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
   myGridEchoStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
   myGridEchoStructure->CStructure()->ViewAffinity->SetVisible (theView->View()->Identification(), true);
+  myGridEchoStructure->CStructure()->OcclusionMask = new Graphic3d_ViewOcclusionMask();
   myGridEchoStructure->Display();
 }
 
index d700adce803dae7ba38b9e8d77a0db929e36e944..33a8f8ef0986f89cfa9ae131f9764c1a5b4e1bb2 100644 (file)
@@ -13992,6 +13992,70 @@ static int VChangeMouseGesture (Draw_Interpretor&,
   return 0;
 }
 
+//==============================================================================
+//function : VOccluded
+//purpose  : Returns number of Occluded objects
+//==============================================================================
+static Standard_Integer VNbOccluded(Draw_Interpretor & /*theDi*/,
+                                  Standard_Integer theArgNb,
+                                  const char **theArgVec) {
+  NCollection_List<TCollection_AsciiString> aViewList;
+  if (theArgNb > 1)
+  {
+    TCollection_AsciiString anArg (theArgVec[1]);
+    anArg.UpperCase();
+    if (anArg.IsEqual ("ALL")
+     || anArg.IsEqual ("*"))
+    {
+      for (ViewerTest_ViewerCommandsViewMap::Iterator anIter (ViewerTest_myViews);
+           anIter.More(); anIter.Next())
+      {
+        aViewList.Append (anIter.Key1());
+      }
+      if (aViewList.IsEmpty())
+      {
+        std::cout << "No views available\n";
+        return 0;
+      }
+    }
+    else
+    {
+      ViewerTest_Names aViewName (theArgVec[1]);
+      if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
+      {
+        Message::SendFail() << "Error: the view with name '" << theArgVec[1] << "' does not exist";
+        return 1;
+      }
+      aViewList.Append (aViewName.GetViewName());
+    }
+  }
+  else
+  {
+    // query from the active view
+    if (ViewerTest::CurrentView().IsNull())
+    {
+      Message::SendFail ("Error: no active view");
+      return 1;
+    }
+    aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
+  }
+
+  for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
+       anIter.More(); anIter.Next()) {
+    Handle(V3d_View) aView = ViewerTest_myViews.Find1(anIter.Value());
+    aView->ChangeRenderingParams().OcculsionQueryState = Graphic3d_RenderingParams::OcculsionQuery_NoUpdate;
+    aView->Redraw();
+    
+    Graphic3d_MapOfStructure aOcculdedStructs;
+    aView->View()->OccludedStructures(aOcculdedStructs);
+
+    printf("No Occluded Objects in view id: %d --> %d\n",
+           aView->View()->Identification(), aOcculdedStructs.Extent());
+  }
+
+  return 0;
+}
+
 //=======================================================================
 //function : ViewerTest_ExitProc
 //purpose  :
@@ -15018,4 +15082,9 @@ Changes the gesture for the mouse button.
  -button  the mouse button;
  -gesture the new gesture for the button.
 )" /* [vchangemousegesture] */);
+
+  addCmd("vnboccluded", VNbOccluded, /* [vnboccluded] */ R"(
+vnboccluded  ALL - print nb of occluded objects for all created views
+vnboccluded [view_id] print nb of occluded objects for specified view_id  . 
+)" /* [vnboccluded] */);
 }
diff --git a/tests/v3d/occlusion/boxes b/tests/v3d/occlusion/boxes
new file mode 100644 (file)
index 0000000..8f63023
--- /dev/null
@@ -0,0 +1,29 @@
+puts "=============================================================================================="
+puts "CR33607: Visualization - Test occlusion query on two boxes using two orthographic projections"
+puts "=============================================================================================="
+
+pload MODELING VISUALIZATION
+vclear
+vclose ALL
+
+box b 10 10 10
+box c 12 0 0 10 10 10
+
+# check left side
+vinit name=View1
+vsetdispmode 1
+vdisplay b c
+vright
+vfit
+vzoom 0.5
+
+# check front side
+vinit name=View2
+vsetdispmode 1
+vdisplay b c
+vfront
+vfit
+
+#run occlusion query for each view 
+vnboccluded View1
+vnboccluded View2