0030374: Visualization, TKOpenGl - activate texture unit Graphic3d_TextureUnit_1...
[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 {
153   // insert default priority layers
154   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
155   myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD,  myLayers.Upper());
156
157   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
158   myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
159
160   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
161   myLayerIds.Bind (Graphic3d_ZLayerId_Top,     myLayers.Upper());
162
163   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
164   myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
165
166   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
167   myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD,  myLayers.Upper());
168
169   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
170
171   myTransparentToProcess.Allocate (myLayers.Length());
172 }
173
174 //=======================================================================
175 //function : ~OpenGl_LayerList
176 //purpose  : Destructor
177 //=======================================================================
178
179 OpenGl_LayerList::~OpenGl_LayerList()
180 {
181 }
182
183 //=======================================================================
184 //function : SetFrustumCullingBVHBuilder
185 //purpose  :
186 //=======================================================================
187 void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
188 {
189   myBVHBuilder = theBuilder;
190   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
191   {
192     anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
193   }
194 }
195
196 //=======================================================================
197 //function : AddLayer
198 //purpose  : 
199 //=======================================================================
200
201 void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
202 {
203   if (myLayerIds.IsBound (theLayerId))
204   {
205     return;
206   }
207
208   // add the new layer
209   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
210   myLayerIds.Bind (theLayerId, myLayers.Length());
211
212   myTransparentToProcess.Allocate (myLayers.Length());
213 }
214
215 //=======================================================================
216 //function : Layer
217 //purpose  : 
218 //=======================================================================
219 OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
220 {
221   return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
222 }
223
224 //=======================================================================
225 //function : Layer
226 //purpose  : 
227 //=======================================================================
228 const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
229 {
230   return *myLayers.Value (myLayerIds.Find (theLayerId));
231 }
232
233 //=======================================================================
234 //function : RemoveLayer
235 //purpose  :
236 //=======================================================================
237
238 void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
239 {
240   if (!myLayerIds.IsBound (theLayerId)
241     || theLayerId <= 0)
242   {
243     return;
244   }
245
246   const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
247   
248   // move all displayed structures to first layer
249   {
250     const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
251     myLayers.ChangeFirst()->Append (aLayerToMove);
252   }
253
254   // remove layer
255   myLayers.Remove (aRemovePos);
256   myLayerIds.UnBind (theLayerId);
257
258   // updated sequence indexes in map
259   for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
260   {
261     Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
262     if (aSeqIdx > aRemovePos)
263       aSeqIdx--;
264   }
265
266   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
267
268   myTransparentToProcess.Allocate (myLayers.Length());
269 }
270
271 //=======================================================================
272 //function : AddStructure
273 //purpose  :
274 //=======================================================================
275
276 void OpenGl_LayerList::AddStructure (const OpenGl_Structure*  theStruct,
277                                      const Graphic3d_ZLayerId theLayerId,
278                                      const Standard_Integer   thePriority,
279                                      Standard_Boolean         isForChangePriority)
280 {
281   // add structure to associated layer,
282   // if layer doesn't exists, display structure in default layer
283   Standard_Integer aSeqPos = myLayers.Lower();
284   myLayerIds.Find (theLayerId, aSeqPos);
285
286   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
287   aLayer.Add (theStruct, thePriority, isForChangePriority);
288   ++myNbStructures;
289   if (aLayer.IsImmediate())
290   {
291     ++myImmediateNbStructures;
292   }
293
294   // Note: In ray-tracing mode we don't modify modification
295   // state here. It is redundant, because the possible changes
296   // will be handled in the loop for structures
297 }
298
299 //=======================================================================
300 //function : RemoveStructure
301 //purpose  :
302 //=======================================================================
303
304 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
305 {
306   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
307
308   Standard_Integer aSeqPos = myLayers.Lower();
309   myLayerIds.Find (aLayerId, aSeqPos);
310
311   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
312   Standard_Integer aPriority = -1;
313
314   // remove structure from associated list
315   // if the structure is not found there,
316   // scan through layers and remove it
317   if (aLayer.Remove (theStructure, aPriority))
318   {
319     --myNbStructures;
320     if (aLayer.IsImmediate())
321     {
322       --myImmediateNbStructures;
323     }
324
325     if (aLayerId == Graphic3d_ZLayerId_Default
326      && theStructure->IsRaytracable())
327     {
328       ++myModifStateOfRaytraceable;
329     }
330
331     return;
332   }
333
334   // scan through layers and remove it
335   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
336   {
337     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
338     if (aSeqPos == anIts.Index())
339     {
340       continue;
341     }
342
343     if (aLayerEx.Remove (theStructure, aPriority))
344     {
345       --myNbStructures;
346       if (aLayerEx.IsImmediate())
347       {
348         --myImmediateNbStructures;
349       }
350
351       if (anIts.Index() == myDefaultLayerIndex
352        && theStructure->IsRaytracable())
353       {
354         ++myModifStateOfRaytraceable;
355       }
356       return;
357     }
358   }
359 }
360
361 //=======================================================================
362 //function : InvalidateBVHData
363 //purpose  :
364 //=======================================================================
365 void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
366 {
367   Standard_Integer aSeqPos = myLayers.Lower();
368   myLayerIds.Find (theLayerId, aSeqPos);
369   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
370   aLayer.InvalidateBVHData();
371 }
372
373 //=======================================================================
374 //function : ChangeLayer
375 //purpose  :
376 //=======================================================================
377
378 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
379                                     const Graphic3d_ZLayerId theOldLayerId,
380                                     const Graphic3d_ZLayerId theNewLayerId)
381 {
382   Standard_Integer aSeqPos = myLayers.Lower();
383   myLayerIds.Find (theOldLayerId, aSeqPos);
384   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
385   Standard_Integer aPriority = -1;
386
387   // take priority and remove structure from list found by <theOldLayerId>
388   // if the structure is not found there, scan through all other layers
389   if (aLayer.Remove (theStructure, aPriority, Standard_False))
390   {
391     if (theOldLayerId == Graphic3d_ZLayerId_Default
392      && theStructure->IsRaytracable())
393     {
394       ++myModifStateOfRaytraceable;
395     }
396
397     --myNbStructures;
398     if (aLayer.IsImmediate())
399     {
400       --myImmediateNbStructures;
401     }
402
403     // isForChangePriority should be Standard_False below, because we want
404     // the BVH tree in the target layer to be updated with theStructure
405     AddStructure (theStructure, theNewLayerId, aPriority);
406     return;
407   }
408
409   // scan through layers and remove it
410   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
411   {
412     if (aSeqPos == anIts.Index())
413     {
414       continue;
415     }
416   
417     // try to remove structure and get priority value from this layer
418     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
419     if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
420     {
421       if (anIts.Index() == myDefaultLayerIndex
422        && theStructure->IsRaytracable())
423       {
424         ++myModifStateOfRaytraceable;
425       }
426
427       --myNbStructures;
428       if (aLayerEx.IsImmediate())
429       {
430         --myImmediateNbStructures;
431       }
432
433       // isForChangePriority should be Standard_False below, because we want
434       // the BVH tree in the target layer to be updated with theStructure
435       AddStructure (theStructure, theNewLayerId, aPriority);
436       return;
437     }
438   }
439 }
440
441 //=======================================================================
442 //function : ChangePriority
443 //purpose  :
444 //=======================================================================
445 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
446                                        const Graphic3d_ZLayerId theLayerId,
447                                        const Standard_Integer   theNewPriority)
448 {
449   Standard_Integer aSeqPos = myLayers.Lower();
450   myLayerIds.Find (theLayerId, aSeqPos);
451   OpenGl_Layer&    aLayer        = *myLayers.ChangeValue (aSeqPos);
452   Standard_Integer anOldPriority = -1;
453
454   if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
455   {
456     --myNbStructures;
457     if (aLayer.IsImmediate())
458     {
459       --myImmediateNbStructures;
460     }
461
462     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
463     return;
464   }
465
466   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
467   {
468     if (aSeqPos == anIts.Index())
469     {
470       continue;
471     }
472
473     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
474     if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
475     {
476       --myNbStructures;
477       if (aLayerEx.IsImmediate())
478       {
479         --myImmediateNbStructures;
480       }
481
482       AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
483       return;
484     }
485   }
486 }
487
488 //=======================================================================
489 //function : SetLayerSettings
490 //purpose  :
491 //=======================================================================
492 void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLayerId,
493                                          const Graphic3d_ZLayerSettings& theSettings)
494 {
495   OpenGl_Layer& aLayer = Layer (theLayerId);
496   if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
497   {
498     if (theSettings.IsImmediate())
499     {
500       myImmediateNbStructures += aLayer.NbStructures();
501     }
502     else
503     {
504       myImmediateNbStructures -= aLayer.NbStructures();
505     }
506   }
507   aLayer.SetLayerSettings (theSettings);
508 }
509
510 //=======================================================================
511 //function : UpdateCulling
512 //purpose  :
513 //=======================================================================
514 void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
515                                       const Standard_Boolean theToDrawImmediate)
516 {
517   const Handle(OpenGl_FrameStats)& aStats = theWorkspace->GetGlContext()->FrameStats();
518   OSD_Timer& aTimer = aStats->ActiveDataFrame().ChangeTimer (Graphic3d_FrameStatsTimer_CpuCulling);
519   aTimer.Start();
520
521   const Standard_Integer aViewId = theWorkspace->View()->Identification();
522   const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
523   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
524   {
525     OpenGl_Layer& aLayer = *anIts.ChangeValue();
526     if (aLayer.IsImmediate() != theToDrawImmediate)
527     {
528       continue;
529     }
530
531     aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->IsCullingEnabled());
532   }
533
534   aTimer.Stop();
535   aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
536 }
537
538 //=======================================================================
539 //function : Render
540 //purpose  :
541 //=======================================================================
542 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
543                                const Standard_Boolean          theToDrawImmediate,
544                                const OpenGl_LayerFilter        theLayersToProcess,
545                                OpenGl_FrameBuffer*             theReadDrawFbo,
546                                OpenGl_FrameBuffer*             theOitAccumFbo) const
547 {
548   // Remember global settings for glDepth function and write mask.
549   OpenGl_GlobalLayerSettings aPrevSettings;
550
551   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
552   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aPrevSettings.DepthFunc);
553   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
554   OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
555
556   // Two render filters are used to support transparency draw. Opaque filter accepts
557   // only non-transparent OpenGl elements of a layer and counts number of skipped
558   // transparent ones. If the counter has positive value the layer is added into
559   // transparency post-processing stack. At the end of drawing or once the depth
560   // buffer is to be cleared the layers in the stack should be drawn using
561   // blending and depth mask settings and another transparency filter which accepts
562   // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
563   // was preallocated before going into this method and has enough space to keep
564   // maximum number of references to layers, therefore it will not increase memory
565   // fragmentation during regular rendering.
566   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
567   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
568
569   myTransparentToProcess.Clear();
570
571   OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
572   Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
573   const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
574                                   && aPrevSettings.DepthMask == GL_TRUE;
575   const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
576   for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
577   {
578     bool hasSkippedDepthLayers = false;
579     for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
580     {
581       if (aPassIter == 0)
582       {
583         aCtx->SetColorMask (false);
584         aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
585         aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
586         aDefaultSettings.DepthMask = GL_TRUE;
587       }
588       else if (aPassIter == 1)
589       {
590         if (!hasSkippedDepthLayers)
591         {
592           continue;
593         }
594         aCtx->SetColorMask (true);
595         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
596         aDefaultSettings = aPrevSettings;
597       }
598       else if (aPassIter == 2)
599       {
600         aCtx->SetColorMask (true);
601         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
602         if (toPerformDepthPrepass)
603         {
604           aDefaultSettings.DepthFunc = GL_EQUAL;
605           aDefaultSettings.DepthMask = GL_FALSE;
606         }
607       }
608
609       OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
610       for (; aLayerIter.More(); aLayerIter.Next())
611       {
612         const OpenGl_Layer& aLayer = aLayerIter.Value();
613
614         // make sure to clear depth of previous layers even if layer has no structures
615         if (aLayer.LayerSettings().ToClearDepth())
616         {
617           aClearDepthLayer = aLayerIter.Index();
618         }
619         if (aLayer.IsCulled())
620         {
621           continue;
622         }
623         else if (aClearDepthLayer > aClearDepthLayerPrev)
624         {
625           // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
626           // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
627           // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
628           if (aPassIter == 2)
629           {
630             aLayerIterStart = aLayerIter;
631           }
632           else
633           {
634             aClearDepthLayer = -1;
635           }
636           break;
637         }
638         else if (aPassIter == 0
639              && !aLayer.LayerSettings().ToRenderInDepthPrepass())
640         {
641           hasSkippedDepthLayers = true;
642           continue;
643         }
644         else if (aPassIter == 1
645               && aLayer.LayerSettings().ToRenderInDepthPrepass())
646         {
647           continue;
648         }
649
650         // Render opaque OpenGl elements of a layer and count the number of skipped.
651         // If a layer has skipped (e.g. transparent) elements it should be added into
652         // the transparency post-processing stack.
653         theWorkspace->ResetSkippedCounter();
654
655         aLayer.Render (theWorkspace, aDefaultSettings);
656
657         if (aPassIter != 0
658          && theWorkspace->NbSkippedTransparentElements() > 0)
659         {
660           myTransparentToProcess.Push (&aLayer);
661         }
662       }
663       if (aPassIter == 2
664       && !aLayerIter.More())
665       {
666         aLayerIterStart = aLayerIter;
667       }
668     }
669
670     if (!myTransparentToProcess.IsEmpty())
671     {
672       renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
673     }
674     if (aClearDepthLayer > aClearDepthLayerPrev)
675     {
676       aClearDepthLayerPrev = aClearDepthLayer;
677       glDepthMask (GL_TRUE);
678       glClear (GL_DEPTH_BUFFER_BIT);
679     }
680   }
681
682   aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
683   aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
684
685   theWorkspace->SetRenderFilter (aPrevFilter);
686 }
687
688 //=======================================================================
689 //function : renderTransparent
690 //purpose  : Render transparent objects using blending operator.
691 //=======================================================================
692 void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
693                                           OpenGl_LayerStack::iterator&      theLayerIter,
694                                           const OpenGl_GlobalLayerSettings& theGlobalSettings,
695                                           OpenGl_FrameBuffer*               theReadDrawFbo,
696                                           OpenGl_FrameBuffer*               theOitAccumFbo) const
697 {
698   // Blended order-independent transparency algorithm require several preconditions
699   // to be enabled. It should be requested by user, at least two outputs from
700   // fragment shader should be supported by GPU, so is the given framebuffer
701   // should contain two additional color buffers to handle accumulated color channels,
702   // blended alpha channel and weight factors - these accumulation buffers are required
703   // to implement commuting blend operator (at least OpenGl 2.0 should be available).
704   const bool isEnabledOit = theOitAccumFbo != NULL
705                          && theOitAccumFbo->NbColorBuffers() >= 2
706                          && theOitAccumFbo->ColorTexture (0)->IsValid()
707                          && theOitAccumFbo->ColorTexture (1)->IsValid();
708
709   // Check if current iterator has already reached the end of the stack.
710   // This should happen if no additional layers has been added to
711   // the processing stack after last transparency pass.
712   if (theLayerIter == myTransparentToProcess.Back())
713   {
714     return;
715   }
716
717   const Handle(OpenGl_Context) aCtx            = theWorkspace->GetGlContext();
718   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
719   OpenGl_View* aView = theWorkspace->View();
720   const float aDepthFactor =  aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
721
722   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
723   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
724
725   aCtx->core11fwd->glEnable (GL_BLEND);
726
727   if (isEnabledOit)
728   {
729     aManager->SetOitState (true, aDepthFactor);
730
731     theOitAccumFbo->BindBuffer (aCtx);
732
733     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
734     aCtx->SetDrawBuffers (2, aDrawBuffers);
735     aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
736     aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
737     aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
738   }
739   else
740   {
741     aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
742   }
743
744   // During blended order-independent transparency pass the depth test
745   // should be enabled to discard fragments covered by opaque geometry
746   // and depth writing should be disabled, because transparent fragments
747   // overal each other with non unitary coverage factor.
748   OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
749   aGlobalSettings.DepthMask   = GL_FALSE;
750   aCtx->core11fwd->glDepthMask (GL_FALSE);
751
752   for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
753   {
754     (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
755   }
756
757   // Revert state of rendering.
758   if (isEnabledOit)
759   {
760     aManager->SetOitState (false, aDepthFactor);
761     theOitAccumFbo->UnbindBuffer (aCtx);
762     if (theReadDrawFbo)
763     {
764       theReadDrawFbo->BindBuffer (aCtx);
765     }
766
767     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
768     aCtx->SetDrawBuffers (1, aDrawBuffers);
769   }
770
771   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
772   if (isEnabledOit)
773   {
774     const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
775     OpenGl_VertexBuffer*   aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
776     if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
777     {
778       aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
779       aCtx->core11fwd->glDepthMask (GL_FALSE);
780
781       // Bind full screen quad buffer and framebuffer resources.
782       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
783
784       const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
785
786       theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
787       theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
788
789       // Draw full screen quad with special shader to compose the buffers.
790       aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
791       aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
792
793       // Unbind OpenGL texture objects and shader program.
794       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
795       theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
796       theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
797       aCtx->BindProgram (NULL);
798
799       if (!aTextureBack.IsNull())
800       {
801         aCtx->BindTextures (aTextureBack);
802       }
803     }
804     else
805     {
806       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
807                          "Initialization of OIT compositing pass has failed.\n"
808                          "  Blended order-independent transparency will not be available.\n");
809       if (aView != NULL)
810       {
811         Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
812         aOITFlag = Standard_True;
813       }
814     }
815   }
816
817   aCtx->core11fwd->glDisable (GL_BLEND);
818   aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
819   aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
820   aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
821 }