0029365: Visualization, TKOpenGl - do not include hidden structures to Rendered withi...
[occt.git] / src / OpenGl / OpenGl_LayerList.cxx
1 // Created on: 2012-02-02
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_GlCore15.hxx>
17
18 #include <BVH_LinearBuilder.hxx>
19 #include <OpenGl_FrameBuffer.hxx>
20 #include <OpenGl_LayerList.hxx>
21 #include <OpenGl_ShaderManager.hxx>
22 #include <OpenGl_Structure.hxx>
23 #include <OpenGl_VertexBuffer.hxx>
24 #include <OpenGl_View.hxx>
25 #include <OpenGl_Workspace.hxx>
26
27 #include <Graphic3d_GraphicDriver.hxx>
28
29 namespace
30 {
31   //! Auxiliary class extending sequence iterator with index.
32   class OpenGl_IndexedLayerIterator : public OpenGl_SequenceOfLayers::Iterator
33   {
34   public:
35     //! Main constructor.
36     OpenGl_IndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq)
37     : OpenGl_SequenceOfLayers::Iterator (theSeq),
38       myIndex (theSeq.Lower()) {}
39
40     //! Return index of current position.
41     Standard_Integer Index() const { return myIndex; }
42
43     //! Move to the next position.
44     void Next()
45     {
46       OpenGl_SequenceOfLayers::Iterator::Next();
47       ++myIndex;
48     }
49
50   private:
51     Standard_Integer myIndex;
52   };
53
54   //! Iterator through layers with filter.
55   class OpenGl_FilteredIndexedLayerIterator
56   {
57   public:
58     //! Main constructor.
59     OpenGl_FilteredIndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq,
60                                          Standard_Integer theDefaultLayerIndex,
61                                          Standard_Boolean theToDrawImmediate,
62                                          OpenGl_LayerFilter theLayersToProcess)
63     : myIter (theSeq),
64       myDefaultLayerIndex (theDefaultLayerIndex),
65       myLayersToProcess (theLayersToProcess),
66       myToDrawImmediate (theToDrawImmediate)
67     {
68       next();
69     }
70
71     //! Return true if iterator points to the valid value.
72     bool More() const { return myIter.More(); }
73
74     //! Return layer at current position.
75     const OpenGl_Layer& Value() const { return *myIter.Value(); }
76
77     //! Return index of current position.
78     Standard_Integer Index() const { return myIter.Index(); }
79
80     //! Go to the next item.
81     void Next()
82     {
83       myIter.Next();
84       next();
85     }
86
87   private:
88     //! Look for the nearest item passing filters.
89     void next()
90     {
91       for (; myIter.More(); myIter.Next())
92       {
93         if (myIter.Value()->IsImmediate() != myToDrawImmediate)
94         {
95           continue;
96         }
97
98         switch (myLayersToProcess)
99         {
100           case OpenGl_LF_All:
101           {
102             break;
103           }
104           case OpenGl_LF_Upper:
105           {
106             if (myIter.Index() <= myDefaultLayerIndex)
107             {
108               continue;
109             }
110             break;
111           }
112           case OpenGl_LF_Bottom:
113           {
114             if (myIter.Index() >= myDefaultLayerIndex)
115             {
116               continue;
117             }
118             break;
119           }
120           case OpenGl_LF_Default:
121           {
122             if (myIter.Index() != myDefaultLayerIndex)
123             {
124               continue;
125             }
126             break;
127           }
128         }
129         return;
130       }
131     }
132   private:
133     OpenGl_IndexedLayerIterator myIter;
134     Standard_Integer            myDefaultLayerIndex;
135     OpenGl_LayerFilter          myLayersToProcess;
136     Standard_Boolean            myToDrawImmediate;
137   };
138 }
139
140 //=======================================================================
141 //function : OpenGl_LayerList
142 //purpose  : Constructor
143 //=======================================================================
144
145 OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
146 : myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
147   myDefaultLayerIndex (0),
148   myNbPriorities (theNbPriorities),
149   myNbStructures (0),
150   myImmediateNbStructures (0),
151   myModifStateOfRaytraceable (0),
152   myRenderOpaqueFilter (new OpenGl_OpaqueFilter()),
153   myRenderTranspFilter (new OpenGl_TransparentFilter())
154 {
155   // insert default priority layers
156   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
157   myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD,  myLayers.Upper());
158
159   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
160   myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
161
162   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
163   myLayerIds.Bind (Graphic3d_ZLayerId_Top,     myLayers.Upper());
164
165   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
166   myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
167
168   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
169   myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD,  myLayers.Upper());
170
171   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
172
173   myTransparentToProcess.Allocate (myLayers.Length());
174 }
175
176 //=======================================================================
177 //function : ~OpenGl_LayerList
178 //purpose  : Destructor
179 //=======================================================================
180
181 OpenGl_LayerList::~OpenGl_LayerList()
182 {
183 }
184
185 //=======================================================================
186 //function : SetFrustumCullingBVHBuilder
187 //purpose  :
188 //=======================================================================
189 void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
190 {
191   myBVHBuilder = theBuilder;
192   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
193   {
194     anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
195   }
196 }
197
198 //=======================================================================
199 //function : AddLayer
200 //purpose  : 
201 //=======================================================================
202
203 void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
204 {
205   if (myLayerIds.IsBound (theLayerId))
206   {
207     return;
208   }
209
210   // add the new layer
211   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
212   myLayerIds.Bind (theLayerId, myLayers.Length());
213
214   myTransparentToProcess.Allocate (myLayers.Length());
215 }
216
217 //=======================================================================
218 //function : Layer
219 //purpose  : 
220 //=======================================================================
221 OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
222 {
223   return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
224 }
225
226 //=======================================================================
227 //function : Layer
228 //purpose  : 
229 //=======================================================================
230 const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
231 {
232   return *myLayers.Value (myLayerIds.Find (theLayerId));
233 }
234
235 //=======================================================================
236 //function : RemoveLayer
237 //purpose  :
238 //=======================================================================
239
240 void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
241 {
242   if (!myLayerIds.IsBound (theLayerId)
243     || theLayerId <= 0)
244   {
245     return;
246   }
247
248   const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
249   
250   // move all displayed structures to first layer
251   {
252     const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
253     myLayers.ChangeFirst()->Append (aLayerToMove);
254   }
255
256   // remove layer
257   myLayers.Remove (aRemovePos);
258   myLayerIds.UnBind (theLayerId);
259
260   // updated sequence indexes in map
261   for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
262   {
263     Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
264     if (aSeqIdx > aRemovePos)
265       aSeqIdx--;
266   }
267
268   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
269
270   myTransparentToProcess.Allocate (myLayers.Length());
271 }
272
273 //=======================================================================
274 //function : AddStructure
275 //purpose  :
276 //=======================================================================
277
278 void OpenGl_LayerList::AddStructure (const OpenGl_Structure*  theStruct,
279                                      const Graphic3d_ZLayerId theLayerId,
280                                      const Standard_Integer   thePriority,
281                                      Standard_Boolean         isForChangePriority)
282 {
283   // add structure to associated layer,
284   // if layer doesn't exists, display structure in default layer
285   Standard_Integer aSeqPos = myLayers.Lower();
286   myLayerIds.Find (theLayerId, aSeqPos);
287
288   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
289   aLayer.Add (theStruct, thePriority, isForChangePriority);
290   ++myNbStructures;
291   if (aLayer.IsImmediate())
292   {
293     ++myImmediateNbStructures;
294   }
295
296   // Note: In ray-tracing mode we don't modify modification
297   // state here. It is redundant, because the possible changes
298   // will be handled in the loop for structures
299 }
300
301 //=======================================================================
302 //function : RemoveStructure
303 //purpose  :
304 //=======================================================================
305
306 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
307 {
308   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
309
310   Standard_Integer aSeqPos = myLayers.Lower();
311   myLayerIds.Find (aLayerId, aSeqPos);
312
313   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
314   Standard_Integer aPriority = -1;
315
316   // remove structure from associated list
317   // if the structure is not found there,
318   // scan through layers and remove it
319   if (aLayer.Remove (theStructure, aPriority))
320   {
321     --myNbStructures;
322     if (aLayer.IsImmediate())
323     {
324       --myImmediateNbStructures;
325     }
326
327     if (aLayerId == Graphic3d_ZLayerId_Default
328      && theStructure->IsRaytracable())
329     {
330       ++myModifStateOfRaytraceable;
331     }
332
333     return;
334   }
335
336   // scan through layers and remove it
337   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
338   {
339     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
340     if (aSeqPos == anIts.Index())
341     {
342       continue;
343     }
344
345     if (aLayerEx.Remove (theStructure, aPriority))
346     {
347       --myNbStructures;
348       if (aLayerEx.IsImmediate())
349       {
350         --myImmediateNbStructures;
351       }
352
353       if (anIts.Index() == myDefaultLayerIndex
354        && theStructure->IsRaytracable())
355       {
356         ++myModifStateOfRaytraceable;
357       }
358       return;
359     }
360   }
361 }
362
363 //=======================================================================
364 //function : InvalidateBVHData
365 //purpose  :
366 //=======================================================================
367 void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
368 {
369   Standard_Integer aSeqPos = myLayers.Lower();
370   myLayerIds.Find (theLayerId, aSeqPos);
371   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
372   aLayer.InvalidateBVHData();
373 }
374
375 //=======================================================================
376 //function : ChangeLayer
377 //purpose  :
378 //=======================================================================
379
380 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
381                                     const Graphic3d_ZLayerId theOldLayerId,
382                                     const Graphic3d_ZLayerId theNewLayerId)
383 {
384   Standard_Integer aSeqPos = myLayers.Lower();
385   myLayerIds.Find (theOldLayerId, aSeqPos);
386   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
387   Standard_Integer aPriority = -1;
388
389   // take priority and remove structure from list found by <theOldLayerId>
390   // if the structure is not found there, scan through all other layers
391   if (aLayer.Remove (theStructure, aPriority, Standard_False))
392   {
393     if (theOldLayerId == Graphic3d_ZLayerId_Default
394      && theStructure->IsRaytracable())
395     {
396       ++myModifStateOfRaytraceable;
397     }
398
399     --myNbStructures;
400     if (aLayer.IsImmediate())
401     {
402       --myImmediateNbStructures;
403     }
404
405     // isForChangePriority should be Standard_False below, because we want
406     // the BVH tree in the target layer to be updated with theStructure
407     AddStructure (theStructure, theNewLayerId, aPriority);
408     return;
409   }
410
411   // scan through layers and remove it
412   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
413   {
414     if (aSeqPos == anIts.Index())
415     {
416       continue;
417     }
418   
419     // try to remove structure and get priority value from this layer
420     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
421     if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
422     {
423       if (anIts.Index() == myDefaultLayerIndex
424        && theStructure->IsRaytracable())
425       {
426         ++myModifStateOfRaytraceable;
427       }
428
429       --myNbStructures;
430       if (aLayerEx.IsImmediate())
431       {
432         --myImmediateNbStructures;
433       }
434
435       // isForChangePriority should be Standard_False below, because we want
436       // the BVH tree in the target layer to be updated with theStructure
437       AddStructure (theStructure, theNewLayerId, aPriority);
438       return;
439     }
440   }
441 }
442
443 //=======================================================================
444 //function : ChangePriority
445 //purpose  :
446 //=======================================================================
447 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
448                                        const Graphic3d_ZLayerId theLayerId,
449                                        const Standard_Integer   theNewPriority)
450 {
451   Standard_Integer aSeqPos = myLayers.Lower();
452   myLayerIds.Find (theLayerId, aSeqPos);
453   OpenGl_Layer&    aLayer        = *myLayers.ChangeValue (aSeqPos);
454   Standard_Integer anOldPriority = -1;
455
456   if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
457   {
458     --myNbStructures;
459     if (aLayer.IsImmediate())
460     {
461       --myImmediateNbStructures;
462     }
463
464     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
465     return;
466   }
467
468   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
469   {
470     if (aSeqPos == anIts.Index())
471     {
472       continue;
473     }
474
475     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
476     if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
477     {
478       --myNbStructures;
479       if (aLayerEx.IsImmediate())
480       {
481         --myImmediateNbStructures;
482       }
483
484       AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
485       return;
486     }
487   }
488 }
489
490 //=======================================================================
491 //function : SetLayerSettings
492 //purpose  :
493 //=======================================================================
494 void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLayerId,
495                                          const Graphic3d_ZLayerSettings& theSettings)
496 {
497   OpenGl_Layer& aLayer = Layer (theLayerId);
498   if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
499   {
500     if (theSettings.IsImmediate())
501     {
502       myImmediateNbStructures += aLayer.NbStructures();
503     }
504     else
505     {
506       myImmediateNbStructures -= aLayer.NbStructures();
507     }
508   }
509   aLayer.SetLayerSettings (theSettings);
510 }
511
512 //=======================================================================
513 //function : UpdateCulling
514 //purpose  :
515 //=======================================================================
516 void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
517                                       const Standard_Boolean theToDrawImmediate)
518 {
519   const Standard_Integer aViewId = theWorkspace->View()->Identification();
520   const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
521   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
522   {
523     OpenGl_Layer& aLayer = *anIts.ChangeValue();
524     if (aLayer.IsImmediate() != theToDrawImmediate)
525     {
526       continue;
527     }
528
529     aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->IsCullingEnabled());
530   }
531 }
532
533 //=======================================================================
534 //function : Render
535 //purpose  :
536 //=======================================================================
537 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
538                                const Standard_Boolean          theToDrawImmediate,
539                                const OpenGl_LayerFilter        theLayersToProcess,
540                                OpenGl_FrameBuffer*             theReadDrawFbo,
541                                OpenGl_FrameBuffer*             theOitAccumFbo) const
542 {
543   // Remember global settings for glDepth function and write mask.
544   OpenGl_GlobalLayerSettings aPrevSettings;
545
546   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
547   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aPrevSettings.DepthFunc);
548   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
549   OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
550
551   // Two render filters are used to support transparency draw. Opaque filter accepts
552   // only non-transparent OpenGl elements of a layer and counts number of skipped
553   // transparent ones. If the counter has positive value the layer is added into
554   // transparency post-processing stack. At the end of drawing or once the depth
555   // buffer is to be cleared the layers in the stack should be drawn using
556   // blending and depth mask settings and another transparency filter which accepts
557   // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
558   // was preallocated before going into this method and has enough space to keep
559   // maximum number of references to layers, therefore it will not increase memory
560   // fragmentation during regular rendering.
561   const Handle(OpenGl_RenderFilter) aPrevFilter = theWorkspace->GetRenderFilter();
562   myRenderOpaqueFilter->SetPreviousFilter (aPrevFilter);
563   myRenderTranspFilter->SetPreviousFilter (aPrevFilter);
564   theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
565
566   myTransparentToProcess.Clear();
567
568   OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
569   Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
570   const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
571                                   && aPrevSettings.DepthMask == GL_TRUE;
572   const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
573   for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
574   {
575     bool hasSkippedDepthLayers = false;
576     for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
577     {
578       if (aPassIter == 0)
579       {
580         aCtx->SetColorMask (false);
581         aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
582         aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
583         aDefaultSettings.DepthMask = GL_TRUE;
584       }
585       else if (aPassIter == 1)
586       {
587         if (!hasSkippedDepthLayers)
588         {
589           continue;
590         }
591         aCtx->SetColorMask (true);
592         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
593         aDefaultSettings = aPrevSettings;
594       }
595       else if (aPassIter == 2)
596       {
597         aCtx->SetColorMask (true);
598         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
599         if (toPerformDepthPrepass)
600         {
601           aDefaultSettings.DepthFunc = GL_EQUAL;
602           aDefaultSettings.DepthMask = GL_FALSE;
603         }
604       }
605
606       OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
607       for (; aLayerIter.More(); aLayerIter.Next())
608       {
609         const OpenGl_Layer& aLayer = aLayerIter.Value();
610
611         // make sure to clear depth of previous layers even if layer has no structures
612         if (aLayer.LayerSettings().ToClearDepth())
613         {
614           aClearDepthLayer = aLayerIter.Index();
615         }
616         if (aLayer.IsCulled())
617         {
618           continue;
619         }
620         else if (aClearDepthLayer > aClearDepthLayerPrev)
621         {
622           // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
623           // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
624           // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
625           if (aPassIter == 2)
626           {
627             aLayerIterStart = aLayerIter;
628           }
629           else
630           {
631             aClearDepthLayer = -1;
632           }
633           break;
634         }
635         else if (aPassIter == 0
636              && !aLayer.LayerSettings().ToRenderInDepthPrepass())
637         {
638           hasSkippedDepthLayers = true;
639           continue;
640         }
641         else if (aPassIter == 1
642               && aLayer.LayerSettings().ToRenderInDepthPrepass())
643         {
644           continue;
645         }
646
647         // Render opaque OpenGl elements of a layer and count the number of skipped.
648         // If a layer has skipped (e.g. transparent) elements it should be added into
649         // the transparency post-processing stack.
650         myRenderOpaqueFilter->SetSkippedCounter (0);
651
652         aLayer.Render (theWorkspace, aDefaultSettings);
653
654         if (aPassIter != 0
655          && myRenderOpaqueFilter->NbSkipped() > 0)
656         {
657           myTransparentToProcess.Push (&aLayer);
658         }
659       }
660       if (aPassIter == 2
661       && !aLayerIter.More())
662       {
663         aLayerIterStart = aLayerIter;
664       }
665     }
666
667     if (!myTransparentToProcess.IsEmpty())
668     {
669       renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
670     }
671     if (aClearDepthLayer > aClearDepthLayerPrev)
672     {
673       aClearDepthLayerPrev = aClearDepthLayer;
674       glDepthMask (GL_TRUE);
675       glClear (GL_DEPTH_BUFFER_BIT);
676     }
677   }
678
679   aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
680   aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
681
682   theWorkspace->SetRenderFilter (aPrevFilter);
683 }
684
685 //=======================================================================
686 //function : renderTransparent
687 //purpose  : Render transparent objects using blending operator.
688 //=======================================================================
689 void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
690                                           OpenGl_LayerStack::iterator&      theLayerIter,
691                                           const OpenGl_GlobalLayerSettings& theGlobalSettings,
692                                           OpenGl_FrameBuffer*               theReadDrawFbo,
693                                           OpenGl_FrameBuffer*               theOitAccumFbo) const
694 {
695   // Blended order-independent transparency algorithm require several preconditions
696   // to be enabled. It should be requested by user, at least two outputs from
697   // fragment shader should be supported by GPU, so is the given framebuffer
698   // should contain two additional color buffers to handle accumulated color channels,
699   // blended alpha channel and weight factors - these accumulation buffers are required
700   // to implement commuting blend operator (at least OpenGl 2.0 should be available).
701   const bool isEnabledOit = theOitAccumFbo != NULL
702                          && theOitAccumFbo->NbColorBuffers() >= 2
703                          && theOitAccumFbo->ColorTexture (0)->IsValid()
704                          && theOitAccumFbo->ColorTexture (1)->IsValid();
705
706   // Check if current iterator has already reached the end of the stack.
707   // This should happen if no additional layers has been added to
708   // the processing stack after last transparency pass.
709   if (theLayerIter == myTransparentToProcess.Back())
710   {
711     return;
712   }
713
714   const Handle(OpenGl_Context) aCtx            = theWorkspace->GetGlContext();
715   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
716   OpenGl_View* aView = theWorkspace->View();
717   const float aDepthFactor =  aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
718
719   theWorkspace->SetRenderFilter (myRenderTranspFilter);
720
721   aCtx->core11fwd->glEnable (GL_BLEND);
722
723   if (isEnabledOit)
724   {
725     aManager->SetOitState (true, aDepthFactor);
726
727     theOitAccumFbo->BindBuffer (aCtx);
728
729     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
730     aCtx->SetDrawBuffers (2, aDrawBuffers);
731     aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
732     aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
733     aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
734   }
735   else
736   {
737     aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
738   }
739
740   // During blended order-independent transparency pass the depth test
741   // should be enabled to discard fragments covered by opaque geometry
742   // and depth writing should be disabled, because transparent fragments
743   // overal each other with non unitary coverage factor.
744   OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
745   aGlobalSettings.DepthMask   = GL_FALSE;
746   aCtx->core11fwd->glDepthMask (GL_FALSE);
747
748   for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
749   {
750     (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
751   }
752
753   // Revert state of rendering.
754   if (isEnabledOit)
755   {
756     aManager->SetOitState (false, aDepthFactor);
757     theOitAccumFbo->UnbindBuffer (aCtx);
758     if (theReadDrawFbo)
759     {
760       theReadDrawFbo->BindBuffer (aCtx);
761     }
762
763     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
764     aCtx->SetDrawBuffers (1, aDrawBuffers);
765   }
766
767   theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
768   if (isEnabledOit)
769   {
770     const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
771     OpenGl_VertexBuffer*   aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
772     if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
773     {
774       aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
775       aCtx->core11fwd->glDepthMask (GL_FALSE);
776
777       // Bind full screen quad buffer and framebuffer resources.
778       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
779
780       const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
781
782       theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
783       theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
784
785       // Draw full screen quad with special shader to compose the buffers.
786       aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
787       aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
788
789       // Unbind OpenGL texture objects and shader program.
790       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
791       theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
792       theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
793       aCtx->BindProgram (NULL);
794
795       if (!aTextureBack.IsNull())
796       {
797         aCtx->BindTextures (aTextureBack);
798       }
799     }
800     else
801     {
802       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
803                          "Initialization of OIT compositing pass has failed.\n"
804                          "  Blended order-independent transparency will not be available.\n");
805       if (aView != NULL)
806       {
807         Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
808         aOITFlag = Standard_True;
809       }
810     }
811   }
812
813   aCtx->core11fwd->glDisable (GL_BLEND);
814   aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
815   aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
816   aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
817 }
818
819 //=======================================================================
820 //class    : OpenGl_OpaqueFilter
821 //function : ShouldRender
822 //purpose  : Checks whether the element should be rendered or skipped.
823 //=======================================================================
824 Standard_Boolean OpenGl_LayerList::OpenGl_OpaqueFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
825                                                                       const OpenGl_Element*           theGlElement)
826 {
827   if (!myFilter.IsNull()
828    && !myFilter->ShouldRender (theWorkspace, theGlElement))
829   {
830     return Standard_False;
831   }
832
833   if (!theGlElement->IsFillDrawMode())
834   {
835     return Standard_True;
836   }
837
838   if (OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
839                                           theWorkspace->HighlightStyle()))
840   {
841     ++mySkippedCounter;
842     return Standard_False;
843   }
844
845   return Standard_True;
846 }
847
848 //=======================================================================
849 //class    : OpenGl_TransparentFilter
850 //function : ShouldRender
851 //purpose  : Checks whether the element should be rendered or skipped.
852 //=======================================================================
853 Standard_Boolean OpenGl_LayerList::OpenGl_TransparentFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
854                                                                            const OpenGl_Element*           theGlElement)
855 {
856   if (!myFilter.IsNull()
857    && !myFilter->ShouldRender (theWorkspace, theGlElement))
858   {
859     return Standard_False;
860   }
861
862   if (!theGlElement->IsFillDrawMode())
863   {
864     return dynamic_cast<const OpenGl_AspectFace*> (theGlElement) != NULL;
865   }
866
867   return OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
868                                              theWorkspace->HighlightStyle());
869 }