0029300: Visualization, TKOpenGl - provide depth pre-pass option
authorkgv <kgv@opencascade.com>
Tue, 7 Nov 2017 21:11:57 +0000 (00:11 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 9 Nov 2017 15:08:16 +0000 (18:08 +0300)
OpenGl_LayerList::Render() now handles new option Graphic3d_RenderingParams::ToEnableDepthPrepass
which prepends additional pass to rendering pipeline filling Depth Buffer in advance.

src/Graphic3d/Graphic3d_RenderingParams.hxx
src/Graphic3d/Graphic3d_ZLayerSettings.hxx
src/OpenGl/OpenGl_CappingAlgo.cxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_Text.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/glsl/depthprepass [new file with mode: 0644]

index d5bd03afc2c52e72d98050a21765ba4ce7140494..5e7a362973969e1de6c8e41bc0e829d2e931acb8 100644 (file)
@@ -53,6 +53,7 @@ public:
     OitDepthFactor              (0.0f),
     NbMsaaSamples               (0),
     RenderResolutionScale       (1.0f),
+    ToEnableDepthPrepass        (Standard_False),
     // ray tracing parameters
     IsGlobalIlluminationEnabled (Standard_False),
     RaytracingDepth             (THE_DEFAULT_DEPTH),
@@ -105,6 +106,7 @@ public:
   Standard_Integer                  NbMsaaSamples;               //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default
   Standard_ShortReal                RenderResolutionScale;       //!< rendering resolution scale factor, 1 by default;
                                                                  //!  incompatible with MSAA (e.g. NbMsaaSamples should be set to 0)
+  Standard_Boolean                  ToEnableDepthPrepass;        //!< enables/disables depth pre-pass, False by default
 
   Standard_Boolean                  IsGlobalIlluminationEnabled; //!< enables/disables global illumination effects (path tracing)
   Standard_Integer                  SamplesPerPixel;             //!< number of samples per pixel (SPP)
index 8ca091dec487005cfbdfe181b45dd050c61d6769..826ee0aae71d960561d74fdd368039d5e54a25a8 100644 (file)
@@ -39,7 +39,8 @@ struct Graphic3d_ZLayerSettings
     myUseEnvironmentTexture (Standard_True),
     myToEnableDepthTest (Standard_True),
     myToEnableDepthWrite(Standard_True),
-    myToClearDepth      (Standard_True) {}
+    myToClearDepth      (Standard_True),
+    myToRenderInDepthPrepass (Standard_True) {}
 
   //! Return user-provided name.
   const TCollection_AsciiString& Name() const { return myName; }
@@ -118,6 +119,12 @@ struct Graphic3d_ZLayerSettings
   //! Set if depth values should be cleared before drawing the layer.
   void SetClearDepth (const Standard_Boolean theValue) { myToClearDepth = theValue; }
 
+  //! Return TRUE if layer should be rendered within depth pre-pass; TRUE by default.
+  Standard_Boolean ToRenderInDepthPrepass() const { return myToRenderInDepthPrepass; }
+
+  //! Set if layer should be rendered within depth pre-pass.
+  void SetRenderInDepthPrepass (Standard_Boolean theToRender) { myToRenderInDepthPrepass = theToRender; }
+
   //! Return glPolygonOffset() arguments.
   const Graphic3d_PolygonOffset& PolygonOffset() const { return myPolygonOffset; }
 
@@ -196,6 +203,7 @@ protected:
   Standard_Boolean            myToEnableDepthTest;     //!< option to enable depth test
   Standard_Boolean            myToEnableDepthWrite;    //!< option to enable write depth values
   Standard_Boolean            myToClearDepth;          //!< option to clear depth values before drawing the layer
+  Standard_Boolean            myToRenderInDepthPrepass;//!< option to render layer within depth pre-pass
 
 };
 
index 4b2a3e93523d2a169febcb88540717469a71ac5b..61206dd8b12e4c82c70b1b541c3375489637af36 100755 (executable)
@@ -73,7 +73,7 @@ namespace
       aContext->ShaderManager()->UpdateClippingState();
 
       glClear (GL_STENCIL_BUFFER_BIT);
-      glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+      const bool aColorMaskBack = aContext->SetColorMask (false);
 
       // override aspects, disable culling
       theWorkspace->SetAspectFace (&theWorkspace->NoneCulling());
@@ -116,7 +116,7 @@ namespace
       aContext->ShaderManager()->UpdateClippingState();
 
       // render capping plane using the generated stencil mask
-      glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+      aContext->SetColorMask (aColorMaskBack);
       if (theWorkspace->UseDepthWrite())
       {
         glDepthMask (GL_TRUE);
index 525fbc630510e9dc44b4b14b15a511014c1de07c..6fb217a2182ae9a08bb40b45d36ffae070b94b4f 100644 (file)
@@ -188,6 +188,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myReadBuffer (0),
   myDrawBuffers (1),
   myDefaultVao (0),
+  myColorMask (true),
   myIsGlDebugCtx (Standard_False),
   myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION),
   myResolutionRatio (1.0f),
@@ -3678,3 +3679,17 @@ void OpenGl_Context::DisableFeatures() const
   }
 #endif
 }
+
+// =======================================================================
+// function : SetColorMask
+// purpose  :
+// =======================================================================
+bool OpenGl_Context::SetColorMask (bool theToWriteColor)
+{
+  const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE;
+  glColorMask (toWrite, toWrite, toWrite, toWrite);
+
+  const bool anOldValue = myColorMask;
+  myColorMask = theToWriteColor;
+  return anOldValue;
+}
index 58d150f2730e7a2ac98b7ca592bb21ae663fcd8f..a0e2da762f97f5f54939c1589fbf199367fc6bc5 100644 (file)
@@ -625,6 +625,12 @@ public: //! @name methods to alter or retrieve current state
     SetDrawBuffer (theBuffer);
   }
 
+  //! Return cached flag indicating writing into color buffer is enabled or disabled (glColorMask).
+  bool ColorMask() const { return myColorMask; }
+
+  //! Enable/disable writing into color buffer (wrapper for glColorMask).
+  Standard_EXPORT bool SetColorMask (bool theToWriteColor);
+
   //! Return back face culling state.
   bool ToCullBackFaces() const { return myToCullBackFaces; }
 
@@ -906,6 +912,7 @@ private: //! @name fields tracking current state
   Standard_Integer              myReadBuffer;      //!< current read buffer
   OpenGl_DrawBuffers            myDrawBuffers;     //!< current draw buffers
   unsigned int                  myDefaultVao;      //!< default Vertex Array Object
+  Standard_Boolean              myColorMask;       //!< flag indicating writing into color buffer is enabled or disabled (glColorMask)
   Standard_Boolean              myIsGlDebugCtx;    //!< debug context initialization state
   TCollection_AsciiString       myVendor;          //!< Graphics Driver's vendor
   TColStd_PackedMapOfInteger    myFilters[6];      //!< messages suppressing filter (for sources from GL_DEBUG_SOURCE_API_ARB to GL_DEBUG_SOURCE_OTHER_ARB)
index ccefa2ed9e9900f881fe7ac6f65f4e8547563832..aa361ac2e0ce27bd67d8e77a4440adabdb5ca595 100644 (file)
 
 #include <Graphic3d_GraphicDriver.hxx>
 
+namespace
+{
+  //! Auxiliary class extending sequence iterator with index.
+  class OpenGl_IndexedLayerIterator : public OpenGl_SequenceOfLayers::Iterator
+  {
+  public:
+    //! Main constructor.
+    OpenGl_IndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq)
+    : OpenGl_SequenceOfLayers::Iterator (theSeq),
+      myIndex (theSeq.Lower()) {}
+
+    //! Return index of current position.
+    Standard_Integer Index() const { return myIndex; }
+
+    //! Move to the next position.
+    void Next()
+    {
+      OpenGl_SequenceOfLayers::Iterator::Next();
+      ++myIndex;
+    }
+
+  private:
+    Standard_Integer myIndex;
+  };
+
+  //! Iterator through layers with filter.
+  class OpenGl_FilteredIndexedLayerIterator
+  {
+  public:
+    //! Main constructor.
+    OpenGl_FilteredIndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq,
+                                         Standard_Integer theDefaultLayerIndex,
+                                         Standard_Boolean theToDrawImmediate,
+                                         OpenGl_LayerFilter theLayersToProcess)
+    : myIter (theSeq),
+      myDefaultLayerIndex (theDefaultLayerIndex),
+      myLayersToProcess (theLayersToProcess),
+      myToDrawImmediate (theToDrawImmediate)
+    {
+      next();
+    }
+
+    //! Return true if iterator points to the valid value.
+    bool More() const { return myIter.More(); }
+
+    //! Return layer at current position.
+    const OpenGl_Layer& Value() const { return *myIter.Value(); }
+
+    //! Return index of current position.
+    Standard_Integer Index() const { return myIter.Index(); }
+
+    //! Go to the next item.
+    void Next()
+    {
+      myIter.Next();
+      next();
+    }
+
+  private:
+    //! Look for the nearest item passing filters.
+    void next()
+    {
+      for (; myIter.More(); myIter.Next())
+      {
+        if (myIter.Value()->IsImmediate() != myToDrawImmediate)
+        {
+          continue;
+        }
+
+        switch (myLayersToProcess)
+        {
+          case OpenGl_LF_All:
+          {
+            break;
+          }
+          case OpenGl_LF_Upper:
+          {
+            if (myIter.Index() <= myDefaultLayerIndex)
+            {
+              continue;
+            }
+            break;
+          }
+          case OpenGl_LF_Bottom:
+          {
+            if (myIter.Index() >= myDefaultLayerIndex)
+            {
+              continue;
+            }
+            break;
+          }
+          case OpenGl_LF_Default:
+          {
+            if (myIter.Index() != myDefaultLayerIndex)
+            {
+              continue;
+            }
+            break;
+          }
+        }
+        return;
+      }
+    }
+  private:
+    OpenGl_IndexedLayerIterator myIter;
+    Standard_Integer            myDefaultLayerIndex;
+    OpenGl_LayerFilter          myLayersToProcess;
+    Standard_Boolean            myToDrawImmediate;
+  };
+}
+
 //=======================================================================
 //function : OpenGl_LayerList
 //purpose  : Constructor
@@ -223,11 +334,10 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
   }
 
   // scan through layers and remove it
-  Standard_Integer aSeqId = 1;
-  for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
+  for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
   {
     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
-    if (aSeqPos == aSeqId)
+    if (aSeqPos == anIts.Index())
     {
       continue;
     }
@@ -240,7 +350,7 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
         --myImmediateNbStructures;
       }
 
-      if (aSeqId == myDefaultLayerIndex
+      if (anIts.Index() == myDefaultLayerIndex
        && theStructure->IsRaytracable())
       {
         ++myModifStateOfRaytraceable;
@@ -299,10 +409,9 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
   }
 
   // scan through layers and remove it
-  Standard_Integer aSeqId = 1;
-  for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
+  for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
   {
-    if (aSeqPos == aSeqId)
+    if (aSeqPos == anIts.Index())
     {
       continue;
     }
@@ -311,7 +420,7 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
     if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
     {
-      if (aSeqId == myDefaultLayerIndex
+      if (anIts.Index() == myDefaultLayerIndex
        && theStructure->IsRaytracable())
       {
         ++myModifStateOfRaytraceable;
@@ -356,10 +465,9 @@ void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
     return;
   }
 
-  Standard_Integer aSeqId = 1;
-  for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
+  for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
   {
-    if (aSeqPos == aSeqId)
+    if (aSeqPos == anIts.Index())
     {
       continue;
     }
@@ -412,11 +520,12 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
                                OpenGl_FrameBuffer*             theOitAccumFbo) const
 {
   // Remember global settings for glDepth function and write mask.
-  OpenGl_GlobalLayerSettings aDefaultSettings;
+  OpenGl_GlobalLayerSettings aPrevSettings;
 
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
-  aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDefaultSettings.DepthFunc);
-  aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aDefaultSettings.DepthMask);
+  aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aPrevSettings.DepthFunc);
+  aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
+  OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
 
   // Two render filters are used to support transparency draw. Opaque filter accepts
   // only non-transparent OpenGl elements of a layer and counts number of skipped
@@ -436,81 +545,114 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
   myTransparentToProcess.Clear();
 
   OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
-  Standard_Integer aSeqId = myLayers.Lower();
-  bool toClearDepth = false;
-  for (OpenGl_SequenceOfLayers::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next(), ++aSeqId)
+  Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
+  const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
+                                  && aPrevSettings.DepthMask == GL_TRUE;
+  for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
   {
-    if (theLayersToProcess == OpenGl_LF_Bottom)
-    {
-      if (aSeqId >= myDefaultLayerIndex) continue;
-    }
-    else if (theLayersToProcess == OpenGl_LF_Upper)
+    bool hasSkippedDepthLayers = false;
+    for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
     {
-      if (aSeqId <= myDefaultLayerIndex) continue;
-    }
-    else if (theLayersToProcess == OpenGl_LF_Default)
-    {
-      if (aSeqId != myDefaultLayerIndex) continue;
-    }
+      if (aPassIter == 0)
+      {
+        aCtx->SetColorMask (false);
+        aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
+        aDefaultSettings.DepthMask = GL_TRUE;
+      }
+      else if (aPassIter == 1)
+      {
+        if (!hasSkippedDepthLayers)
+        {
+          continue;
+        }
+        aCtx->SetColorMask (true);
+        aDefaultSettings = aPrevSettings;
+      }
+      else if (aPassIter == 2)
+      {
+        aCtx->SetColorMask (true);
+        if (toPerformDepthPrepass)
+        {
+          aDefaultSettings.DepthFunc = GL_EQUAL;
+          aDefaultSettings.DepthMask = GL_FALSE;
+        }
+      }
 
-    const OpenGl_Layer& aLayer = *aLayerIter.Value();
-    if (aLayer.IsImmediate() != theToDrawImmediate)
-    {
-      continue;
+      OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
+      for (; aLayerIter.More(); aLayerIter.Next())
+      {
+        const OpenGl_Layer& aLayer = aLayerIter.Value();
+
+        // make sure to clear depth of previous layers even if layer has no structures
+        if (aLayer.LayerSettings().ToClearDepth())
+        {
+          aClearDepthLayer = aLayerIter.Index();
+        }
+        if (aLayer.NbStructures() < 1)
+        {
+          continue;
+        }
+        else if (aClearDepthLayer > aClearDepthLayerPrev)
+        {
+          // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
+          // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
+          // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
+          if (aPassIter == 2)
+          {
+            aLayerIterStart = aLayerIter;
+          }
+          else
+          {
+            aClearDepthLayer = -1;
+          }
+          break;
+        }
+        else if (aPassIter == 0
+             && !aLayer.LayerSettings().ToRenderInDepthPrepass())
+        {
+          hasSkippedDepthLayers = true;
+          continue;
+        }
+        else if (aPassIter == 1
+              && aLayer.LayerSettings().ToRenderInDepthPrepass())
+        {
+          continue;
+        }
+
+        // Render opaque OpenGl elements of a layer and count the number of skipped.
+        // If a layer has skipped (e.g. transparent) elements it should be added into
+        // the transparency post-processing stack.
+        myRenderOpaqueFilter->SetSkippedCounter (0);
+
+        aLayer.Render (theWorkspace, aDefaultSettings);
+
+        if (aPassIter != 0
+         && myRenderOpaqueFilter->NbSkipped() > 0)
+        {
+          myTransparentToProcess.Push (&aLayer);
+        }
+      }
+      if (aPassIter == 2
+      && !aLayerIter.More())
+      {
+        aLayerIterStart = aLayerIter;
+      }
     }
-    else if (aLayer.NbStructures() < 1)
+
+    if (!myTransparentToProcess.IsEmpty())
     {
-      // Make sure to clear depth of previous layers even if layer has no structures.
-      toClearDepth = toClearDepth || aLayer.LayerSettings().ToClearDepth();
-      continue;
+      renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
     }
-
-    // At this point the depth buffer may be set to clear by
-    // previous configuration of layers or configuration of the
-    // current layer. Additional rendering pass to handle transparent
-    // elements of recently drawn layers require use of current depth
-    // buffer so we put remaining layers for processing as one bunch before
-    // erasing the depth buffer.
-    if (toClearDepth
-     || aLayer.LayerSettings().ToClearDepth())
+    if (aClearDepthLayer > aClearDepthLayerPrev)
     {
-      if (!myTransparentToProcess.IsEmpty())
-      {
-        renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
-      }
-
-      toClearDepth = false;
+      aClearDepthLayerPrev = aClearDepthLayer;
       glDepthMask (GL_TRUE);
       glClear (GL_DEPTH_BUFFER_BIT);
     }
-
-    // Render opaque OpenGl elements of a layer and count the number of skipped.
-    // If a layer has skipped (e.g. transparent) elements it should be added into
-    // the transparency post-processing stack.
-    myRenderOpaqueFilter->SetSkippedCounter (0);
-
-    aLayer.Render (theWorkspace, aDefaultSettings);
-
-    if (myRenderOpaqueFilter->NbSkipped() > 0)
-    {
-      myTransparentToProcess.Push (&aLayer);
-    }
-  }
-
-  // Before finishing process the remaining collected layers with transparency.
-  if (!myTransparentToProcess.IsEmpty())
-  {
-    renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
-  }
-
-  if (toClearDepth)
-  {
-    glDepthMask (GL_TRUE);
-    glClear (GL_DEPTH_BUFFER_BIT);
   }
 
-  aCtx->core11fwd->glDepthMask (aDefaultSettings.DepthMask);
-  aCtx->core11fwd->glDepthFunc (aDefaultSettings.DepthFunc);
+  aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
+  aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
 
   theWorkspace->SetRenderFilter (aPrevFilter);
 }
index c2ca7b9e839635684bafe2e0bc7f736fa8c9787e..84030e15bfbc1f4e033e5ce1baa2e099956f0ca4 100644 (file)
@@ -736,7 +736,8 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
                                         && myVboAttribs->HasColorAttribute();
   const Standard_Boolean isLightOn = !anAspectFace->IsNoLighting()
                                   && !myVboAttribs.IsNull()
-                                  &&  myVboAttribs->HasNormalAttribute();
+                                  &&  myVboAttribs->HasNormalAttribute()
+                                  &&  aCtx->ColorMask();
 
   // Temporarily disable environment mapping
   Handle(OpenGl_TextureSet) aTextureBack;
index fd9757f44dbd83496efb3d57be703e948c58ae6f..5bfd924b9bdae7f3af5dbbb83ec7d55ecd8e99e3 100644 (file)
@@ -958,7 +958,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
       glDisable (GL_ALPHA_TEST);
     }
   #endif
-    glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+    const bool aColorMaskBack = theCtx->SetColorMask (false);
 
     glClear (GL_STENCIL_BUFFER_BIT);
     glEnable (GL_STENCIL_TEST);
@@ -969,7 +969,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
 
     glStencilFunc (GL_ALWAYS, 0, 0xFF);
 
-    glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    theCtx->SetColorMask (aColorMaskBack);
   }
 
   // reset OpenGL state
index fcc5c5cce143904bb5e8cabe1ab7af7399644fb4..a8f65a72a57a4fd2efafb00de7662a74a82e393d 100644 (file)
@@ -9843,6 +9843,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       case V3d_GOURAUD: theDI << "gouraud"; break;
       case V3d_PHONG:   theDI << "phong";   break;
     }
+    theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
     theDI << "\n";
     return 0;
   }
@@ -9974,6 +9975,20 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         return 1;
       }
     }
+    else if (aFlag == "-depthprepass")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
+        continue;
+      }
+      aParams.ToEnableDepthPrepass = Standard_True;
+      if (anArgIter + 1 < theArgNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
+      {
+        ++anArgIter;
+      }
+    }
     else if (aFlag == "-rendscale"
           || aFlag == "-renderscale"
           || aFlag == "-renderresolutionscale")
@@ -11946,6 +11961,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n      '-raster'                   Disables GPU ray-tracing"
     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
+    "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
     "\n      '-rendScale    value        Rendering resolution scale factor"
     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
diff --git a/tests/v3d/glsl/depthprepass b/tests/v3d/glsl/depthprepass
new file mode 100644 (file)
index 0000000..be106f0
--- /dev/null
@@ -0,0 +1,27 @@
+puts "========"
+puts "0029300: Visualization, TKOpenGl - provide depth pre-pass option"
+puts "========"
+
+vclear
+vclose ALL
+vinit View1
+
+# display objects
+psphere s 1
+box b 1 2 3
+vaxo
+vdisplay -dispMode 1 s b
+vaspects b -setColor RED -setTransparency 0.5
+vfit
+vzbufftrihedron
+vmoveto 150 250
+vcaps -ffp 0
+vrenderparams -shadingModel phong
+
+vrenderparams -depthPrePass off
+vdump $::imagedir/${::casename}_1.png
+
+vrenderparams -depthPrePass on
+vdump $::imagedir/${::casename}_2.png
+
+if { [diffimage $::imagedir/${::casename}_1.png $::imagedir/${::casename}_2.png 0 0 0 $::imagedir/${::casename}_diff.png] != 0 } { puts "Error: images differ" }