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