0030635: Visualization - move OpenGl_Layer to Graphic3d_Layer
[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 struct OpenGl_GlobalLayerSettings
141 {
142   GLint DepthFunc;
143   GLboolean DepthMask;
144 };
145
146 //=======================================================================
147 //function : OpenGl_LayerList
148 //purpose  : Constructor
149 //=======================================================================
150
151 OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
152 : myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
153   myDefaultLayerIndex (0),
154   myNbPriorities (theNbPriorities),
155   myNbStructures (0),
156   myImmediateNbStructures (0),
157   myModifStateOfRaytraceable (0)
158 {
159   // insert default priority layers
160   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
161   myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD,  myLayers.Upper());
162
163   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
164   myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
165
166   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
167   myLayerIds.Bind (Graphic3d_ZLayerId_Top,     myLayers.Upper());
168
169   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
170   myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
171
172   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
173   myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD,  myLayers.Upper());
174
175   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
176
177   myTransparentToProcess.Allocate (myLayers.Length());
178 }
179
180 //=======================================================================
181 //function : ~OpenGl_LayerList
182 //purpose  : Destructor
183 //=======================================================================
184
185 OpenGl_LayerList::~OpenGl_LayerList()
186 {
187 }
188
189 //=======================================================================
190 //function : SetFrustumCullingBVHBuilder
191 //purpose  :
192 //=======================================================================
193 void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
194 {
195   myBVHBuilder = theBuilder;
196   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
197   {
198     anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
199   }
200 }
201
202 //=======================================================================
203 //function : AddLayer
204 //purpose  : 
205 //=======================================================================
206
207 void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
208 {
209   if (myLayerIds.IsBound (theLayerId))
210   {
211     return;
212   }
213
214   // add the new layer
215   myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
216   myLayerIds.Bind (theLayerId, myLayers.Length());
217
218   myTransparentToProcess.Allocate (myLayers.Length());
219 }
220
221 //=======================================================================
222 //function : Layer
223 //purpose  : 
224 //=======================================================================
225 OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
226 {
227   return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
228 }
229
230 //=======================================================================
231 //function : Layer
232 //purpose  : 
233 //=======================================================================
234 const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
235 {
236   return *myLayers.Value (myLayerIds.Find (theLayerId));
237 }
238
239 //=======================================================================
240 //function : RemoveLayer
241 //purpose  :
242 //=======================================================================
243
244 void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
245 {
246   if (!myLayerIds.IsBound (theLayerId)
247     || theLayerId <= 0)
248   {
249     return;
250   }
251
252   const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
253   
254   // move all displayed structures to first layer
255   {
256     const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
257     myLayers.ChangeFirst()->Append (aLayerToMove);
258   }
259
260   // remove layer
261   myLayers.Remove (aRemovePos);
262   myLayerIds.UnBind (theLayerId);
263
264   // updated sequence indexes in map
265   for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
266   {
267     Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
268     if (aSeqIdx > aRemovePos)
269       aSeqIdx--;
270   }
271
272   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
273
274   myTransparentToProcess.Allocate (myLayers.Length());
275 }
276
277 //=======================================================================
278 //function : AddStructure
279 //purpose  :
280 //=======================================================================
281
282 void OpenGl_LayerList::AddStructure (const OpenGl_Structure*  theStruct,
283                                      const Graphic3d_ZLayerId theLayerId,
284                                      const Standard_Integer   thePriority,
285                                      Standard_Boolean         isForChangePriority)
286 {
287   // add structure to associated layer,
288   // if layer doesn't exists, display structure in default layer
289   Standard_Integer aSeqPos = myLayers.Lower();
290   myLayerIds.Find (theLayerId, aSeqPos);
291
292   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
293   aLayer.Add (theStruct, thePriority, isForChangePriority);
294   ++myNbStructures;
295   if (aLayer.IsImmediate())
296   {
297     ++myImmediateNbStructures;
298   }
299
300   // Note: In ray-tracing mode we don't modify modification
301   // state here. It is redundant, because the possible changes
302   // will be handled in the loop for structures
303 }
304
305 //=======================================================================
306 //function : RemoveStructure
307 //purpose  :
308 //=======================================================================
309
310 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
311 {
312   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
313
314   Standard_Integer aSeqPos = myLayers.Lower();
315   myLayerIds.Find (aLayerId, aSeqPos);
316
317   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
318   Standard_Integer aPriority = -1;
319
320   // remove structure from associated list
321   // if the structure is not found there,
322   // scan through layers and remove it
323   if (aLayer.Remove (theStructure, aPriority))
324   {
325     --myNbStructures;
326     if (aLayer.IsImmediate())
327     {
328       --myImmediateNbStructures;
329     }
330
331     if (aLayerId == Graphic3d_ZLayerId_Default
332      && theStructure->IsRaytracable())
333     {
334       ++myModifStateOfRaytraceable;
335     }
336
337     return;
338   }
339
340   // scan through layers and remove it
341   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
342   {
343     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
344     if (aSeqPos == anIts.Index())
345     {
346       continue;
347     }
348
349     if (aLayerEx.Remove (theStructure, aPriority))
350     {
351       --myNbStructures;
352       if (aLayerEx.IsImmediate())
353       {
354         --myImmediateNbStructures;
355       }
356
357       if (anIts.Index() == myDefaultLayerIndex
358        && theStructure->IsRaytracable())
359       {
360         ++myModifStateOfRaytraceable;
361       }
362       return;
363     }
364   }
365 }
366
367 //=======================================================================
368 //function : InvalidateBVHData
369 //purpose  :
370 //=======================================================================
371 void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
372 {
373   Standard_Integer aSeqPos = myLayers.Lower();
374   myLayerIds.Find (theLayerId, aSeqPos);
375   OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
376   aLayer.InvalidateBVHData();
377 }
378
379 //=======================================================================
380 //function : ChangeLayer
381 //purpose  :
382 //=======================================================================
383
384 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
385                                     const Graphic3d_ZLayerId theOldLayerId,
386                                     const Graphic3d_ZLayerId theNewLayerId)
387 {
388   Standard_Integer aSeqPos = myLayers.Lower();
389   myLayerIds.Find (theOldLayerId, aSeqPos);
390   OpenGl_Layer&    aLayer    = *myLayers.ChangeValue (aSeqPos);
391   Standard_Integer aPriority = -1;
392
393   // take priority and remove structure from list found by <theOldLayerId>
394   // if the structure is not found there, scan through all other layers
395   if (aLayer.Remove (theStructure, aPriority, Standard_False))
396   {
397     if (theOldLayerId == Graphic3d_ZLayerId_Default
398      && theStructure->IsRaytracable())
399     {
400       ++myModifStateOfRaytraceable;
401     }
402
403     --myNbStructures;
404     if (aLayer.IsImmediate())
405     {
406       --myImmediateNbStructures;
407     }
408
409     // isForChangePriority should be Standard_False below, because we want
410     // the BVH tree in the target layer to be updated with theStructure
411     AddStructure (theStructure, theNewLayerId, aPriority);
412     return;
413   }
414
415   // scan through layers and remove it
416   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
417   {
418     if (aSeqPos == anIts.Index())
419     {
420       continue;
421     }
422   
423     // try to remove structure and get priority value from this layer
424     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
425     if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
426     {
427       if (anIts.Index() == myDefaultLayerIndex
428        && theStructure->IsRaytracable())
429       {
430         ++myModifStateOfRaytraceable;
431       }
432
433       --myNbStructures;
434       if (aLayerEx.IsImmediate())
435       {
436         --myImmediateNbStructures;
437       }
438
439       // isForChangePriority should be Standard_False below, because we want
440       // the BVH tree in the target layer to be updated with theStructure
441       AddStructure (theStructure, theNewLayerId, aPriority);
442       return;
443     }
444   }
445 }
446
447 //=======================================================================
448 //function : ChangePriority
449 //purpose  :
450 //=======================================================================
451 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
452                                        const Graphic3d_ZLayerId theLayerId,
453                                        const Standard_Integer   theNewPriority)
454 {
455   Standard_Integer aSeqPos = myLayers.Lower();
456   myLayerIds.Find (theLayerId, aSeqPos);
457   OpenGl_Layer&    aLayer        = *myLayers.ChangeValue (aSeqPos);
458   Standard_Integer anOldPriority = -1;
459
460   if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
461   {
462     --myNbStructures;
463     if (aLayer.IsImmediate())
464     {
465       --myImmediateNbStructures;
466     }
467
468     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
469     return;
470   }
471
472   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
473   {
474     if (aSeqPos == anIts.Index())
475     {
476       continue;
477     }
478
479     OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
480     if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
481     {
482       --myNbStructures;
483       if (aLayerEx.IsImmediate())
484       {
485         --myImmediateNbStructures;
486       }
487
488       AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
489       return;
490     }
491   }
492 }
493
494 //=======================================================================
495 //function : SetLayerSettings
496 //purpose  :
497 //=======================================================================
498 void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLayerId,
499                                          const Graphic3d_ZLayerSettings& theSettings)
500 {
501   OpenGl_Layer& aLayer = Layer (theLayerId);
502   if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
503   {
504     if (theSettings.IsImmediate())
505     {
506       myImmediateNbStructures += aLayer.NbStructures();
507     }
508     else
509     {
510       myImmediateNbStructures -= aLayer.NbStructures();
511     }
512   }
513   aLayer.SetLayerSettings (theSettings);
514 }
515
516 //=======================================================================
517 //function : UpdateCulling
518 //purpose  :
519 //=======================================================================
520 void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
521                                       const Standard_Boolean theToDrawImmediate)
522 {
523   const Handle(OpenGl_FrameStats)& aStats = theWorkspace->GetGlContext()->FrameStats();
524   OSD_Timer& aTimer = aStats->ActiveDataFrame().ChangeTimer (Graphic3d_FrameStatsTimer_CpuCulling);
525   aTimer.Start();
526
527   const Standard_Integer aViewId = theWorkspace->View()->Identification();
528   const Graphic3d_CullingTool& aSelector = theWorkspace->View()->BVHTreeSelector();
529   for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
530   {
531     OpenGl_Layer& aLayer = *anIts.ChangeValue();
532     if (aLayer.IsImmediate() != theToDrawImmediate)
533     {
534       continue;
535     }
536
537     aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->View()->RenderingParams().FrustumCullingState);
538   }
539
540   aTimer.Stop();
541   aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
542 }
543
544 //=======================================================================
545 //function : renderLayer
546 //purpose  :
547 //=======================================================================
548 void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace,
549                                     const OpenGl_GlobalLayerSettings& theDefaultSettings,
550                                     const Graphic3d_Layer& theLayer) const
551 {
552   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
553
554   const Graphic3d_ZLayerSettings& aLayerSettings = theLayer.LayerSettings();
555   // aLayerSettings.ToClearDepth() is handled outside
556
557   // handle depth test
558   if (aLayerSettings.ToEnableDepthTest())
559   {
560     // assuming depth test is enabled by default
561     glDepthFunc (theDefaultSettings.DepthFunc);
562   }
563   else
564   {
565     glDepthFunc (GL_ALWAYS);
566   }
567
568   // save environment texture
569   Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
570   if (!aLayerSettings.UseEnvironmentTexture())
571   {
572     theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
573   }
574
575   // handle depth offset
576   const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->SetDefaultPolygonOffset (aLayerSettings.PolygonOffset());
577
578   // handle depth write
579   theWorkspace->UseDepthWrite() = aLayerSettings.ToEnableDepthWrite() && theDefaultSettings.DepthMask == GL_TRUE;
580   glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
581
582   const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull();
583   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
584   Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources();
585   const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack;
586   if (hasOwnLights)
587   {
588     aLayerSettings.Lights()->UpdateRevision();
589     aManager->UpdateLightSourceStateTo (aLayerSettings.Lights());
590   }
591
592   const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
593   if (hasLocalCS)
594   {
595     // Apply local camera transformation.
596     // The vertex position is computed by the following formula in GLSL program:
597     //   gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
598     // where:
599     //   occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection
600     //   occWorldViewMatrix  - world-view  matrix defining Camera position and orientation
601     //   occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system
602     //   occVertex           - input vertex position
603     //
604     // Since double precision is quite expensive on modern GPUs, and not available on old hardware,
605     // all these values are passed with single float precision to the shader.
606     // As result, single precision become insufficient for handling objects far from the world origin.
607     //
608     // Several approaches can be used to solve precision issues:
609     //  - [Broute force] migrate to double precision for all matrices and vertex position.
610     //    This is too expensive for most hardware.
611     //  - Store only translation part with double precision and pass it to GLSL program.
612     //    This requires modified GLSL programs for computing transformation
613     //    and extra packing mechanism for hardware not supporting double precision natively.
614     //    This solution is less expensive then previous one.
615     //  - Move translation part of occModelWorldMatrix into occWorldViewMatrix.
616     //    The main idea here is that while moving Camera towards the object,
617     //    Camera translation part and Object translation part will compensate each other
618     //    to fit into single float precision.
619     //    But this operation should be performed with double precision - this is why we are moving
620     //    translation part of occModelWorldMatrix to occWorldViewMatrix.
621     //
622     // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario.
623     // Here we do the trick:
624     //  - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it.
625     //    This Local Origin is included into occWorldViewMatrix during rendering.
626     //  - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer.
627     //    This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer.
628     theWorkspace->View()->SetLocalOrigin (aLayerSettings.Origin());
629
630     NCollection_Mat4<Standard_Real> aWorldView = aWorldCamera->OrientationMatrix();
631     Graphic3d_TransformUtils::Translate (aWorldView, aLayerSettings.Origin().X(), aLayerSettings.Origin().Y(), aLayerSettings.Origin().Z());
632
633     NCollection_Mat4<Standard_ShortReal> aWorldViewF;
634     aWorldViewF.ConvertFrom (aWorldView);
635     aCtx->WorldViewState.SetCurrent (aWorldViewF);
636     aCtx->ShaderManager()->UpdateClippingState();
637     aCtx->ShaderManager()->UpdateLightSourceState();
638   }
639
640   // render priority list
641   const Standard_Integer aViewId = theWorkspace->View()->Identification();
642   for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (theLayer.ArrayOfStructures()); aMapIter.More(); aMapIter.Next())
643   {
644     const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
645     for (OpenGl_Structure::StructIterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
646     {
647       const OpenGl_Structure* aStruct = aStructIter.Value();
648       if (aStruct->IsCulled()
649       || !aStruct->IsVisible (aViewId))
650       {
651         continue;
652       }
653
654       aStruct->Render (theWorkspace);
655     }
656   }
657
658   if (hasOwnLights)
659   {
660     aManager->UpdateLightSourceStateTo (aLightsBack);
661   }
662   if (hasLocalCS)
663   {
664     aCtx->ShaderManager()->RevertClippingState();
665     aCtx->ShaderManager()->UpdateLightSourceState();
666
667     aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF());
668     theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0));
669   }
670
671   // always restore polygon offset between layers rendering
672   theWorkspace->SetDefaultPolygonOffset (anAppliedOffsetParams);
673
674   // restore environment texture
675   if (!aLayerSettings.UseEnvironmentTexture())
676   {
677     theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
678   }
679 }
680
681 //=======================================================================
682 //function : Render
683 //purpose  :
684 //=======================================================================
685 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
686                                const Standard_Boolean          theToDrawImmediate,
687                                const OpenGl_LayerFilter        theLayersToProcess,
688                                OpenGl_FrameBuffer*             theReadDrawFbo,
689                                OpenGl_FrameBuffer*             theOitAccumFbo) const
690 {
691   // Remember global settings for glDepth function and write mask.
692   OpenGl_GlobalLayerSettings aPrevSettings;
693
694   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
695   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aPrevSettings.DepthFunc);
696   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
697   OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
698
699   // Two render filters are used to support transparency draw. Opaque filter accepts
700   // only non-transparent OpenGl elements of a layer and counts number of skipped
701   // transparent ones. If the counter has positive value the layer is added into
702   // transparency post-processing stack. At the end of drawing or once the depth
703   // buffer is to be cleared the layers in the stack should be drawn using
704   // blending and depth mask settings and another transparency filter which accepts
705   // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
706   // was preallocated before going into this method and has enough space to keep
707   // maximum number of references to layers, therefore it will not increase memory
708   // fragmentation during regular rendering.
709   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
710   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
711
712   myTransparentToProcess.Clear();
713
714   OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
715   Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
716   const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
717                                   && aPrevSettings.DepthMask == GL_TRUE;
718   const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
719   for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
720   {
721     bool hasSkippedDepthLayers = false;
722     for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
723     {
724       if (aPassIter == 0)
725       {
726         aCtx->SetColorMask (false);
727         aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
728         aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
729         aDefaultSettings.DepthMask = GL_TRUE;
730       }
731       else if (aPassIter == 1)
732       {
733         if (!hasSkippedDepthLayers)
734         {
735           continue;
736         }
737         aCtx->SetColorMask (true);
738         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
739         aDefaultSettings = aPrevSettings;
740       }
741       else if (aPassIter == 2)
742       {
743         aCtx->SetColorMask (true);
744         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
745         if (toPerformDepthPrepass)
746         {
747           aDefaultSettings.DepthFunc = GL_EQUAL;
748           aDefaultSettings.DepthMask = GL_FALSE;
749         }
750       }
751
752       OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
753       for (; aLayerIter.More(); aLayerIter.Next())
754       {
755         const OpenGl_Layer& aLayer = aLayerIter.Value();
756
757         // make sure to clear depth of previous layers even if layer has no structures
758         if (aLayer.LayerSettings().ToClearDepth())
759         {
760           aClearDepthLayer = aLayerIter.Index();
761         }
762         if (aLayer.IsCulled())
763         {
764           continue;
765         }
766         else if (aClearDepthLayer > aClearDepthLayerPrev)
767         {
768           // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
769           // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
770           // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
771           if (aPassIter == 2)
772           {
773             aLayerIterStart = aLayerIter;
774           }
775           else
776           {
777             aClearDepthLayer = -1;
778           }
779           break;
780         }
781         else if (aPassIter == 0
782              && !aLayer.LayerSettings().ToRenderInDepthPrepass())
783         {
784           hasSkippedDepthLayers = true;
785           continue;
786         }
787         else if (aPassIter == 1
788               && aLayer.LayerSettings().ToRenderInDepthPrepass())
789         {
790           continue;
791         }
792
793         // Render opaque OpenGl elements of a layer and count the number of skipped.
794         // If a layer has skipped (e.g. transparent) elements it should be added into
795         // the transparency post-processing stack.
796         theWorkspace->ResetSkippedCounter();
797
798         renderLayer (theWorkspace, aDefaultSettings, aLayer);
799
800         if (aPassIter != 0
801          && theWorkspace->NbSkippedTransparentElements() > 0)
802         {
803           myTransparentToProcess.Push (&aLayer);
804         }
805       }
806       if (aPassIter == 2
807       && !aLayerIter.More())
808       {
809         aLayerIterStart = aLayerIter;
810       }
811     }
812
813     if (!myTransparentToProcess.IsEmpty())
814     {
815       renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
816     }
817     if (aClearDepthLayer > aClearDepthLayerPrev)
818     {
819       aClearDepthLayerPrev = aClearDepthLayer;
820       glDepthMask (GL_TRUE);
821       glClear (GL_DEPTH_BUFFER_BIT);
822     }
823   }
824
825   aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
826   aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
827
828   theWorkspace->SetRenderFilter (aPrevFilter);
829 }
830
831 //=======================================================================
832 //function : renderTransparent
833 //purpose  : Render transparent objects using blending operator.
834 //=======================================================================
835 void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
836                                           OpenGl_LayerStack::iterator&      theLayerIter,
837                                           const OpenGl_GlobalLayerSettings& theGlobalSettings,
838                                           OpenGl_FrameBuffer*               theReadDrawFbo,
839                                           OpenGl_FrameBuffer*               theOitAccumFbo) const
840 {
841   // Blended order-independent transparency algorithm require several preconditions
842   // to be enabled. It should be requested by user, at least two outputs from
843   // fragment shader should be supported by GPU, so is the given framebuffer
844   // should contain two additional color buffers to handle accumulated color channels,
845   // blended alpha channel and weight factors - these accumulation buffers are required
846   // to implement commuting blend operator (at least OpenGl 2.0 should be available).
847   const bool isEnabledOit = theOitAccumFbo != NULL
848                          && theOitAccumFbo->NbColorBuffers() >= 2
849                          && theOitAccumFbo->ColorTexture (0)->IsValid()
850                          && theOitAccumFbo->ColorTexture (1)->IsValid();
851
852   // Check if current iterator has already reached the end of the stack.
853   // This should happen if no additional layers has been added to
854   // the processing stack after last transparency pass.
855   if (theLayerIter == myTransparentToProcess.Back())
856   {
857     return;
858   }
859
860   const Handle(OpenGl_Context) aCtx            = theWorkspace->GetGlContext();
861   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
862   OpenGl_View* aView = theWorkspace->View();
863   const float aDepthFactor =  aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
864
865   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
866   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
867
868   aCtx->core11fwd->glEnable (GL_BLEND);
869
870   if (isEnabledOit)
871   {
872     aManager->SetOitState (true, aDepthFactor);
873
874     theOitAccumFbo->BindBuffer (aCtx);
875
876     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
877     aCtx->SetDrawBuffers (2, aDrawBuffers);
878     aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
879     aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
880     aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
881   }
882   else
883   {
884     aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
885   }
886
887   // During blended order-independent transparency pass the depth test
888   // should be enabled to discard fragments covered by opaque geometry
889   // and depth writing should be disabled, because transparent fragments
890   // overal each other with non unitary coverage factor.
891   OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
892   aGlobalSettings.DepthMask   = GL_FALSE;
893   aCtx->core11fwd->glDepthMask (GL_FALSE);
894
895   for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
896   {
897     renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
898   }
899
900   // Revert state of rendering.
901   if (isEnabledOit)
902   {
903     aManager->SetOitState (false, aDepthFactor);
904     theOitAccumFbo->UnbindBuffer (aCtx);
905     if (theReadDrawFbo)
906     {
907       theReadDrawFbo->BindBuffer (aCtx);
908     }
909
910     static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
911     aCtx->SetDrawBuffers (1, aDrawBuffers);
912   }
913
914   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
915   if (isEnabledOit)
916   {
917     const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
918     OpenGl_VertexBuffer*   aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
919     if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
920     {
921       aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
922       aCtx->core11fwd->glDepthMask (GL_FALSE);
923
924       // Bind full screen quad buffer and framebuffer resources.
925       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
926
927       const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
928
929       theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
930       theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
931
932       // Draw full screen quad with special shader to compose the buffers.
933       aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
934       aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
935
936       // Unbind OpenGL texture objects and shader program.
937       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
938       theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
939       theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
940       aCtx->BindProgram (NULL);
941
942       if (!aTextureBack.IsNull())
943       {
944         aCtx->BindTextures (aTextureBack);
945       }
946     }
947     else
948     {
949       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
950                          "Initialization of OIT compositing pass has failed.\n"
951                          "  Blended order-independent transparency will not be available.\n");
952       if (aView != NULL)
953       {
954         Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
955         aOITFlag = Standard_True;
956       }
957     }
958   }
959
960   aCtx->core11fwd->glDisable (GL_BLEND);
961   aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
962   aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
963   aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
964 }