#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
}
// 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;
}
--myImmediateNbStructures;
}
- if (aSeqId == myDefaultLayerIndex
+ if (anIts.Index() == myDefaultLayerIndex
&& theStructure->IsRaytracable())
{
++myModifStateOfRaytraceable;
}
// 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;
}
OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
{
- if (aSeqId == myDefaultLayerIndex
+ if (anIts.Index() == myDefaultLayerIndex
&& theStructure->IsRaytracable())
{
++myModifStateOfRaytraceable;
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;
}
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
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);
}