0032507: Visualization, TKOpenGl - topmost text disappears with Graphic3d_RTM_DEPTH_P...
[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_DepthPeeling.hxx>
20 #include <OpenGl_FrameBuffer.hxx>
21 #include <OpenGl_LayerList.hxx>
22 #include <OpenGl_ShaderManager.hxx>
23 #include <OpenGl_ShadowMap.hxx>
24 #include <OpenGl_Structure.hxx>
25 #include <OpenGl_VertexBuffer.hxx>
26 #include <OpenGl_View.hxx>
27 #include <OpenGl_Workspace.hxx>
28
29 #include <Graphic3d_GraphicDriver.hxx>
30
31 namespace
32 {
33   //! Auxiliary class extending sequence iterator with index.
34   class OpenGl_IndexedLayerIterator : public NCollection_List<Handle(Graphic3d_Layer)>::Iterator
35   {
36   public:
37     //! Main constructor.
38     OpenGl_IndexedLayerIterator (const NCollection_List<Handle(Graphic3d_Layer)>& theSeq)
39     : NCollection_List<Handle(Graphic3d_Layer)>::Iterator (theSeq),
40       myIndex (1) {}
41
42     //! Return index of current position.
43     Standard_Integer Index() const { return myIndex; }
44
45     //! Move to the next position.
46     void Next()
47     {
48       NCollection_List<Handle(Graphic3d_Layer)>::Iterator::Next();
49       ++myIndex;
50     }
51
52   private:
53     Standard_Integer myIndex;
54   };
55
56   //! Iterator through layers with filter.
57   class OpenGl_FilteredIndexedLayerIterator
58   {
59   public:
60     //! Main constructor.
61     OpenGl_FilteredIndexedLayerIterator (const NCollection_List<Handle(Graphic3d_Layer)>& theSeq,
62                                          Standard_Boolean theToDrawImmediate,
63                                          OpenGl_LayerFilter theLayersToProcess)
64     : myIter (theSeq),
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         const Handle(Graphic3d_Layer)& aLayer = myIter.Value();
94         if (aLayer->IsImmediate() != myToDrawImmediate)
95         {
96           continue;
97         }
98
99         switch (myLayersToProcess)
100         {
101           case OpenGl_LF_All:
102           {
103             return;
104           }
105           case OpenGl_LF_Upper:
106           {
107             if (aLayer->LayerId() != Graphic3d_ZLayerId_BotOSD
108              && (!aLayer->LayerSettings().IsRaytracable()
109                || aLayer->IsImmediate()))
110             {
111               return;
112             }
113             break;
114           }
115           case OpenGl_LF_Bottom:
116           {
117             if (aLayer->LayerId() == Graphic3d_ZLayerId_BotOSD
118             && !aLayer->LayerSettings().IsRaytracable())
119             {
120               return;
121             }
122             break;
123           }
124           case OpenGl_LF_RayTracable:
125           {
126             if (aLayer->LayerSettings().IsRaytracable()
127             && !aLayer->IsImmediate())
128             {
129               return;
130             }
131             break;
132           }
133         }
134       }
135     }
136   private:
137     OpenGl_IndexedLayerIterator myIter;
138     OpenGl_LayerFilter          myLayersToProcess;
139     Standard_Boolean            myToDrawImmediate;
140   };
141
142   static const Standard_Integer THE_DRAW_BUFFERS0[]   = { GL_COLOR_ATTACHMENT0 };
143   static const Standard_Integer THE_DRAW_BUFFERS01[]  = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
144   static const Standard_Integer THE_DRAW_BUFFERS012[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1, GL_COLOR_ATTACHMENT0 + 2 };
145   static const float THE_DEPTH_CLEAR_VALUE = -1e15f;
146 }
147
148 struct OpenGl_GlobalLayerSettings
149 {
150   GLint DepthFunc;
151   GLboolean DepthMask;
152 };
153
154 //=======================================================================
155 //function : OpenGl_LayerList
156 //purpose  : Constructor
157 //=======================================================================
158
159 OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
160 : myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
161   myNbPriorities (theNbPriorities),
162   myNbStructures (0),
163   myImmediateNbStructures (0),
164   myModifStateOfRaytraceable (0)
165 {
166   //
167 }
168
169 //=======================================================================
170 //function : ~OpenGl_LayerList
171 //purpose  : Destructor
172 //=======================================================================
173
174 OpenGl_LayerList::~OpenGl_LayerList()
175 {
176 }
177
178 //=======================================================================
179 //function : SetFrustumCullingBVHBuilder
180 //purpose  :
181 //=======================================================================
182 void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
183 {
184   myBVHBuilder = theBuilder;
185   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
186   {
187     aLayerIter.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
188   }
189 }
190
191 //=======================================================================
192 //function : InsertLayerBefore
193 //purpose  :
194 //=======================================================================
195 void OpenGl_LayerList::InsertLayerBefore (const Graphic3d_ZLayerId theNewLayerId,
196                                           const Graphic3d_ZLayerSettings& theSettings,
197                                           const Graphic3d_ZLayerId theLayerAfter)
198 {
199   if (myLayerIds.IsBound (theNewLayerId))
200   {
201     return;
202   }
203
204   Handle(Graphic3d_Layer) aNewLayer = new Graphic3d_Layer (theNewLayerId, myNbPriorities, myBVHBuilder);
205   aNewLayer->SetLayerSettings (theSettings);
206
207   Handle(Graphic3d_Layer) anOtherLayer;
208   if (theLayerAfter != Graphic3d_ZLayerId_UNKNOWN
209    && myLayerIds.Find (theLayerAfter, anOtherLayer))
210   {
211     for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
212     {
213       if (aLayerIter.Value() == anOtherLayer)
214       {
215         myLayers.InsertBefore (aNewLayer, aLayerIter);
216         break;
217       }
218     }
219   }
220   else
221   {
222     myLayers.Prepend (aNewLayer);
223   }
224
225   myLayerIds.Bind (theNewLayerId, aNewLayer);
226   myTransparentToProcess.Allocate (myLayers.Size());
227 }
228
229 //=======================================================================
230 //function : InsertLayerAfter
231 //purpose  :
232 //=======================================================================
233 void OpenGl_LayerList::InsertLayerAfter (const Graphic3d_ZLayerId theNewLayerId,
234                                          const Graphic3d_ZLayerSettings& theSettings,
235                                          const Graphic3d_ZLayerId theLayerBefore)
236 {
237   if (myLayerIds.IsBound (theNewLayerId))
238   {
239     return;
240   }
241
242   Handle(Graphic3d_Layer) aNewLayer = new Graphic3d_Layer (theNewLayerId, myNbPriorities, myBVHBuilder);
243   aNewLayer->SetLayerSettings (theSettings);
244
245   Handle(Graphic3d_Layer) anOtherLayer;
246   if (theLayerBefore != Graphic3d_ZLayerId_UNKNOWN
247    && myLayerIds.Find (theLayerBefore, anOtherLayer))
248   {
249     for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
250     {
251       if (aLayerIter.Value() == anOtherLayer)
252       {
253         myLayers.InsertAfter (aNewLayer, aLayerIter);
254         break;
255       }
256     }
257   }
258   else
259   {
260     myLayers.Append (aNewLayer);
261   }
262
263   myLayerIds.Bind (theNewLayerId, aNewLayer);
264   myTransparentToProcess.Allocate (myLayers.Size());
265 }
266
267 //=======================================================================
268 //function : RemoveLayer
269 //purpose  :
270 //=======================================================================
271 void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
272 {
273   Handle(Graphic3d_Layer) aLayerToRemove;
274   if (theLayerId <= 0
275   || !myLayerIds.Find (theLayerId, aLayerToRemove))
276   {
277     return;
278   }
279
280   // move all displayed structures to first layer
281   myLayerIds.Find (Graphic3d_ZLayerId_Default)->Append (*aLayerToRemove);
282
283   // remove layer
284   myLayers.Remove (aLayerToRemove);
285   myLayerIds.UnBind (theLayerId);
286
287   myTransparentToProcess.Allocate (myLayers.Size());
288 }
289
290 //=======================================================================
291 //function : AddStructure
292 //purpose  :
293 //=======================================================================
294
295 void OpenGl_LayerList::AddStructure (const OpenGl_Structure*  theStruct,
296                                      const Graphic3d_ZLayerId theLayerId,
297                                      const Standard_Integer   thePriority,
298                                      Standard_Boolean         isForChangePriority)
299 {
300   // add structure to associated layer,
301   // if layer doesn't exists, display structure in default layer
302   const Handle(Graphic3d_Layer)* aLayerPtr = myLayerIds.Seek (theLayerId);
303   const Handle(Graphic3d_Layer)& aLayer = aLayerPtr != NULL ? *aLayerPtr : myLayerIds.Find (Graphic3d_ZLayerId_Default);
304   aLayer->Add (theStruct, thePriority, isForChangePriority);
305   ++myNbStructures;
306   if (aLayer->IsImmediate())
307   {
308     ++myImmediateNbStructures;
309   }
310
311   // Note: In ray-tracing mode we don't modify modification
312   // state here. It is redundant, because the possible changes
313   // will be handled in the loop for structures
314 }
315
316 //=======================================================================
317 //function : RemoveStructure
318 //purpose  :
319 //=======================================================================
320
321 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
322 {
323   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
324   const Handle(Graphic3d_Layer)* aLayerPtr = myLayerIds.Seek (aLayerId);
325   const Handle(Graphic3d_Layer)& aLayer = aLayerPtr != NULL ? *aLayerPtr : myLayerIds.Find (Graphic3d_ZLayerId_Default);
326
327   Standard_Integer aPriority = -1;
328
329   // remove structure from associated list
330   // if the structure is not found there,
331   // scan through layers and remove it
332   if (aLayer->Remove (theStructure, aPriority))
333   {
334     --myNbStructures;
335     if (aLayer->IsImmediate())
336     {
337       --myImmediateNbStructures;
338     }
339
340     if (aLayer->LayerSettings().IsRaytracable()
341      && theStructure->IsRaytracable())
342     {
343       ++myModifStateOfRaytraceable;
344     }
345
346     return;
347   }
348
349   // scan through layers and remove it
350   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
351   {
352     const Handle(Graphic3d_Layer)& aLayerEx = aLayerIter.ChangeValue();
353     if (aLayerEx == aLayer)
354     {
355       continue;
356     }
357
358     if (aLayerEx->Remove (theStructure, aPriority))
359     {
360       --myNbStructures;
361       if (aLayerEx->IsImmediate())
362       {
363         --myImmediateNbStructures;
364       }
365
366       if (aLayerEx->LayerSettings().IsRaytracable()
367        && theStructure->IsRaytracable())
368       {
369         ++myModifStateOfRaytraceable;
370       }
371       return;
372     }
373   }
374 }
375
376 //=======================================================================
377 //function : InvalidateBVHData
378 //purpose  :
379 //=======================================================================
380 void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
381 {
382   const Handle(Graphic3d_Layer)* aLayerPtr = myLayerIds.Seek (theLayerId);
383   const Handle(Graphic3d_Layer)& aLayer = aLayerPtr != NULL ? *aLayerPtr : myLayerIds.Find (Graphic3d_ZLayerId_Default);
384   aLayer->InvalidateBVHData();
385 }
386
387 //=======================================================================
388 //function : ChangeLayer
389 //purpose  :
390 //=======================================================================
391
392 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
393                                     const Graphic3d_ZLayerId theOldLayerId,
394                                     const Graphic3d_ZLayerId theNewLayerId)
395 {
396   const Handle(Graphic3d_Layer)* aLayerPtr = myLayerIds.Seek (theOldLayerId);
397   const Handle(Graphic3d_Layer)& aLayer = aLayerPtr != NULL ? *aLayerPtr : myLayerIds.Find (Graphic3d_ZLayerId_Default);
398
399   Standard_Integer aPriority = -1;
400
401   // take priority and remove structure from list found by <theOldLayerId>
402   // if the structure is not found there, scan through all other layers
403   if (aLayer->Remove (theStructure, aPriority, Standard_False))
404   {
405     if (aLayer->LayerSettings().IsRaytracable()
406     && !aLayer->LayerSettings().IsImmediate()
407     &&  theStructure->IsRaytracable())
408     {
409       ++myModifStateOfRaytraceable;
410     }
411
412     --myNbStructures;
413     if (aLayer->IsImmediate())
414     {
415       --myImmediateNbStructures;
416     }
417
418     // isForChangePriority should be Standard_False below, because we want
419     // the BVH tree in the target layer to be updated with theStructure
420     AddStructure (theStructure, theNewLayerId, aPriority);
421     return;
422   }
423
424   // scan through layers and remove it
425   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
426   {
427     const Handle(OpenGl_Layer)& aLayerEx = aLayerIter.ChangeValue();
428     if (aLayerEx == aLayer)
429     {
430       continue;
431     }
432   
433     // try to remove structure and get priority value from this layer
434     if (aLayerEx->Remove (theStructure, aPriority, Standard_True))
435     {
436       if (aLayerEx->LayerSettings().IsRaytracable()
437       && !aLayerEx->LayerSettings().IsImmediate()
438       &&  theStructure->IsRaytracable())
439       {
440         ++myModifStateOfRaytraceable;
441       }
442
443       --myNbStructures;
444       if (aLayerEx->IsImmediate())
445       {
446         --myImmediateNbStructures;
447       }
448
449       // isForChangePriority should be Standard_False below, because we want
450       // the BVH tree in the target layer to be updated with theStructure
451       AddStructure (theStructure, theNewLayerId, aPriority);
452       return;
453     }
454   }
455 }
456
457 //=======================================================================
458 //function : ChangePriority
459 //purpose  :
460 //=======================================================================
461 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
462                                        const Graphic3d_ZLayerId theLayerId,
463                                        const Standard_Integer   theNewPriority)
464 {
465   const Handle(Graphic3d_Layer)* aLayerPtr = myLayerIds.Seek (theLayerId);
466   const Handle(Graphic3d_Layer)& aLayer = aLayerPtr != NULL ? *aLayerPtr : myLayerIds.Find (Graphic3d_ZLayerId_Default);
467
468   Standard_Integer anOldPriority = -1;
469
470   if (aLayer->Remove (theStructure, anOldPriority, Standard_True))
471   {
472     --myNbStructures;
473     if (aLayer->IsImmediate())
474     {
475       --myImmediateNbStructures;
476     }
477
478     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
479     return;
480   }
481
482   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
483   {
484     const Handle(OpenGl_Layer)& aLayerEx = aLayerIter.ChangeValue();
485     if (aLayerEx == aLayer)
486     {
487       continue;
488     }
489
490     if (aLayerEx->Remove (theStructure, anOldPriority, Standard_True))
491     {
492       --myNbStructures;
493       if (aLayerEx->IsImmediate())
494       {
495         --myImmediateNbStructures;
496       }
497
498       AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
499       return;
500     }
501   }
502 }
503
504 //=======================================================================
505 //function : SetLayerSettings
506 //purpose  :
507 //=======================================================================
508 void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLayerId,
509                                          const Graphic3d_ZLayerSettings& theSettings)
510 {
511   Graphic3d_Layer& aLayer = Layer (theLayerId);
512   if (aLayer.LayerSettings().IsRaytracable() != theSettings.IsRaytracable()
513    && aLayer.NbStructures() != 0)
514   {
515     ++myModifStateOfRaytraceable;
516   }
517   if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
518   {
519     if (theSettings.IsImmediate())
520     {
521       myImmediateNbStructures += aLayer.NbStructures();
522     }
523     else
524     {
525       myImmediateNbStructures -= aLayer.NbStructures();
526     }
527   }
528   aLayer.SetLayerSettings (theSettings);
529 }
530
531 //=======================================================================
532 //function : UpdateCulling
533 //purpose  :
534 //=======================================================================
535 void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
536                                       const Standard_Boolean theToDrawImmediate)
537 {
538   const Handle(OpenGl_FrameStats)& aStats = theWorkspace->GetGlContext()->FrameStats();
539   OSD_Timer& aTimer = aStats->ActiveDataFrame().ChangeTimer (Graphic3d_FrameStatsTimer_CpuCulling);
540   aTimer.Start();
541
542   const Standard_Integer aViewId = theWorkspace->View()->Identification();
543   const Graphic3d_CullingTool& aSelector = theWorkspace->View()->BVHTreeSelector();
544   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
545   {
546     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.ChangeValue();
547     if (aLayer->IsImmediate() != theToDrawImmediate)
548     {
549       continue;
550     }
551
552     aLayer->UpdateCulling (aViewId, aSelector, theWorkspace->View()->RenderingParams().FrustumCullingState);
553   }
554
555   aTimer.Stop();
556   aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
557 }
558
559 //=======================================================================
560 //function : renderLayer
561 //purpose  :
562 //=======================================================================
563 void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace,
564                                     const OpenGl_GlobalLayerSettings& theDefaultSettings,
565                                     const Graphic3d_Layer& theLayer) const
566 {
567   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
568
569   const Graphic3d_ZLayerSettings& aLayerSettings = theLayer.LayerSettings();
570   // aLayerSettings.ToClearDepth() is handled outside
571
572   // handle depth test
573   if (aLayerSettings.ToEnableDepthTest())
574   {
575     // assuming depth test is enabled by default
576     glDepthFunc (theDefaultSettings.DepthFunc);
577   }
578   else
579   {
580     glDepthFunc (GL_ALWAYS);
581   }
582
583   // save environment texture
584   Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
585   if (!aLayerSettings.UseEnvironmentTexture())
586   {
587     theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
588   }
589
590   // handle depth offset
591   const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->SetDefaultPolygonOffset (aLayerSettings.PolygonOffset());
592
593   // handle depth write
594   theWorkspace->UseDepthWrite() = aLayerSettings.ToEnableDepthWrite() && theDefaultSettings.DepthMask == GL_TRUE;
595   glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
596
597   const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull();
598   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
599   Handle(Graphic3d_LightSet)    aLightsBack = aManager->LightSourceState().LightSources();
600   Handle(OpenGl_ShadowMapArray) aShadowMaps = aManager->LightSourceState().ShadowMaps();
601   const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack;
602   if (hasOwnLights)
603   {
604     aLayerSettings.Lights()->UpdateRevision();
605     aManager->UpdateLightSourceStateTo (aLayerSettings.Lights(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
606   }
607
608   const Handle(Graphic3d_Camera)& aWorldCamera = aCtx->Camera();
609   if (hasLocalCS)
610   {
611     // Apply local camera transformation.
612     // The vertex position is computed by the following formula in GLSL program:
613     //   gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
614     // where:
615     //   occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection
616     //   occWorldViewMatrix  - world-view  matrix defining Camera position and orientation
617     //   occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system
618     //   occVertex           - input vertex position
619     //
620     // Since double precision is quite expensive on modern GPUs, and not available on old hardware,
621     // all these values are passed with single float precision to the shader.
622     // As result, single precision become insufficient for handling objects far from the world origin.
623     //
624     // Several approaches can be used to solve precision issues:
625     //  - [Broute force] migrate to double precision for all matrices and vertex position.
626     //    This is too expensive for most hardware.
627     //  - Store only translation part with double precision and pass it to GLSL program.
628     //    This requires modified GLSL programs for computing transformation
629     //    and extra packing mechanism for hardware not supporting double precision natively.
630     //    This solution is less expensive then previous one.
631     //  - Move translation part of occModelWorldMatrix into occWorldViewMatrix.
632     //    The main idea here is that while moving Camera towards the object,
633     //    Camera translation part and Object translation part will compensate each other
634     //    to fit into single float precision.
635     //    But this operation should be performed with double precision - this is why we are moving
636     //    translation part of occModelWorldMatrix to occWorldViewMatrix.
637     //
638     // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario.
639     // Here we do the trick:
640     //  - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it.
641     //    This Local Origin is included into occWorldViewMatrix during rendering.
642     //  - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer.
643     //    This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer.
644     theWorkspace->View()->SetLocalOrigin (aLayerSettings.Origin());
645
646     NCollection_Mat4<Standard_Real> aWorldView = aWorldCamera->OrientationMatrix();
647     Graphic3d_TransformUtils::Translate (aWorldView, aLayerSettings.Origin().X(), aLayerSettings.Origin().Y(), aLayerSettings.Origin().Z());
648
649     if (!aManager->LightSourceState().ShadowMaps().IsNull())
650     {
651       // shift shadowmap matrix
652       for (OpenGl_ShadowMapArray::Iterator aShadowIter (*aManager->LightSourceState().ShadowMaps()); aShadowIter.More(); aShadowIter.Next())
653       {
654         aShadowIter.Value()->UpdateCamera (*theWorkspace->View(), &aLayerSettings.Origin());
655       }
656     }
657
658     NCollection_Mat4<Standard_ShortReal> aWorldViewF;
659     aWorldViewF.ConvertFrom (aWorldView);
660     aCtx->WorldViewState.SetCurrent (aWorldViewF);
661     aCtx->ShaderManager()->UpdateClippingState();
662     aCtx->ShaderManager()->UpdateLightSourceState();
663   }
664
665   // render priority list
666   const Standard_Integer aViewId = theWorkspace->View()->Identification();
667   for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (theLayer.ArrayOfStructures()); aMapIter.More(); aMapIter.Next())
668   {
669     const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
670     for (OpenGl_Structure::StructIterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
671     {
672       const OpenGl_Structure* aStruct = aStructIter.Value();
673       if (aStruct->IsCulled()
674       || !aStruct->IsVisible (aViewId))
675       {
676         continue;
677       }
678
679       aStruct->Render (theWorkspace);
680     }
681   }
682
683   if (hasOwnLights)
684   {
685     aManager->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
686   }
687   if (hasLocalCS)
688   {
689     if (!aManager->LightSourceState().ShadowMaps().IsNull())
690     {
691       // restore shadowmap matrix
692       for (OpenGl_ShadowMapArray::Iterator aShadowIter (*aManager->LightSourceState().ShadowMaps()); aShadowIter.More(); aShadowIter.Next())
693       {
694         aShadowIter.Value()->UpdateCamera (*theWorkspace->View(), &gp::Origin().XYZ());
695       }
696     }
697
698     aCtx->ShaderManager()->RevertClippingState();
699     aCtx->ShaderManager()->UpdateLightSourceState();
700
701     aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF());
702     theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0));
703   }
704
705   // always restore polygon offset between layers rendering
706   theWorkspace->SetDefaultPolygonOffset (anAppliedOffsetParams);
707
708   // restore environment texture
709   if (!aLayerSettings.UseEnvironmentTexture())
710   {
711     theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
712   }
713 }
714
715 //=======================================================================
716 //function : Render
717 //purpose  :
718 //=======================================================================
719 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
720                                const Standard_Boolean          theToDrawImmediate,
721                                const OpenGl_LayerFilter        theLayersToProcess,
722                                OpenGl_FrameBuffer*             theReadDrawFbo,
723                                OpenGl_FrameBuffer*             theOitAccumFbo) const
724 {
725   // Remember global settings for glDepth function and write mask.
726   OpenGl_GlobalLayerSettings aPrevSettings;
727
728   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
729   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aPrevSettings.DepthFunc);
730   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
731   OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
732   const bool isShadowMapPass = theReadDrawFbo != NULL
733                            && !theReadDrawFbo->HasColor();
734
735   // Two render filters are used to support transparency draw. Opaque filter accepts
736   // only non-transparent OpenGl elements of a layer and counts number of skipped
737   // transparent ones. If the counter has positive value the layer is added into
738   // transparency post-processing stack. At the end of drawing or once the depth
739   // buffer is to be cleared the layers in the stack should be drawn using
740   // blending and depth mask settings and another transparency filter which accepts
741   // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
742   // was preallocated before going into this method and has enough space to keep
743   // maximum number of references to layers, therefore it will not increase memory
744   // fragmentation during regular rendering.
745   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
746   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
747
748   myTransparentToProcess.Clear();
749
750   OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
751   Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
752   const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
753                                   && aPrevSettings.DepthMask == GL_TRUE
754                                   && !isShadowMapPass;
755   const Handle(Graphic3d_LightSet)    aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
756   const Handle(OpenGl_ShadowMapArray) aShadowMaps = aCtx->ShaderManager()->LightSourceState().ShadowMaps();
757   for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
758   {
759     bool hasSkippedDepthLayers = false;
760     for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
761     {
762       if (aPassIter == 0)
763       {
764         aCtx->SetColorMask (false);
765         aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
766         aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
767         aDefaultSettings.DepthMask = GL_TRUE;
768       }
769       else if (aPassIter == 1)
770       {
771         if (!hasSkippedDepthLayers)
772         {
773           continue;
774         }
775         aCtx->SetColorMask (true);
776         aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
777         aDefaultSettings = aPrevSettings;
778       }
779       else if (aPassIter == 2)
780       {
781         if (isShadowMapPass)
782         {
783           aCtx->SetColorMask (false);
784           aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
785         }
786         else
787         {
788           aCtx->SetColorMask (true);
789           aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
790         }
791         if (toPerformDepthPrepass)
792         {
793           aDefaultSettings.DepthFunc = GL_EQUAL;
794           aDefaultSettings.DepthMask = GL_FALSE;
795         }
796       }
797
798       OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
799       for (; aLayerIter.More(); aLayerIter.Next())
800       {
801         const OpenGl_Layer& aLayer = aLayerIter.Value();
802
803         // make sure to clear depth of previous layers even if layer has no structures
804         if (aLayer.LayerSettings().ToClearDepth())
805         {
806           aClearDepthLayer = aLayerIter.Index();
807         }
808         if (aLayer.IsCulled())
809         {
810           continue;
811         }
812         else if (aClearDepthLayer > aClearDepthLayerPrev)
813         {
814           // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
815           // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
816           // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
817           if (aPassIter == 2)
818           {
819             aLayerIterStart = aLayerIter;
820           }
821           else
822           {
823             aClearDepthLayer = -1;
824           }
825           break;
826         }
827         else if (aPassIter == 0
828              && !aLayer.LayerSettings().ToRenderInDepthPrepass())
829         {
830           hasSkippedDepthLayers = true;
831           continue;
832         }
833         else if (aPassIter == 1
834               && aLayer.LayerSettings().ToRenderInDepthPrepass())
835         {
836           continue;
837         }
838
839         // Render opaque OpenGl elements of a layer and count the number of skipped.
840         // If a layer has skipped (e.g. transparent) elements it should be added into
841         // the transparency post-processing stack.
842         theWorkspace->ResetSkippedCounter();
843
844         renderLayer (theWorkspace, aDefaultSettings, aLayer);
845
846         if (aPassIter != 0
847          && theWorkspace->NbSkippedTransparentElements() > 0)
848         {
849           myTransparentToProcess.Push (&aLayer);
850         }
851       }
852       if (aPassIter == 2
853       && !aLayerIter.More())
854       {
855         aLayerIterStart = aLayerIter;
856       }
857     }
858
859     if (!myTransparentToProcess.IsEmpty())
860     {
861       renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
862     }
863     if (aClearDepthLayer > aClearDepthLayerPrev)
864     {
865       aClearDepthLayerPrev = aClearDepthLayer;
866       glDepthMask (GL_TRUE);
867       glClear (GL_DEPTH_BUFFER_BIT);
868     }
869   }
870
871   aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
872   aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
873   aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
874
875   theWorkspace->SetRenderFilter (aPrevFilter);
876 }
877
878 //=======================================================================
879 //function : renderTransparent
880 //purpose  : Render transparent objects using blending operator.
881 //=======================================================================
882 void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
883                                           OpenGl_LayerStack::iterator&      theLayerIter,
884                                           const OpenGl_GlobalLayerSettings& theGlobalSettings,
885                                           OpenGl_FrameBuffer*               theReadDrawFbo,
886                                           OpenGl_FrameBuffer*               theOitAccumFbo) const
887 {
888   // Check if current iterator has already reached the end of the stack.
889   // This should happen if no additional layers has been added to
890   // the processing stack after last transparency pass.
891   if (theLayerIter == myTransparentToProcess.Back())
892   {
893     return;
894   }
895
896   const Handle(OpenGl_Context)& aCtx           = theWorkspace->GetGlContext();
897   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
898   const OpenGl_LayerStack::iterator aLayerFrom = theLayerIter;
899   OpenGl_View* aView = theWorkspace->View();
900
901   Graphic3d_RenderTransparentMethod anOitMode = aView != NULL
902                                               ? aView->RenderingParams().TransparencyMethod
903                                               : Graphic3d_RTM_BLEND_UNORDERED;
904
905   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
906   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
907   aCtx->core11fwd->glEnable (GL_BLEND);
908
909   const Handle(OpenGl_FrameBuffer)* aGlDepthPeelFBOs = aView->DepthPeelingFbos()->DepthPeelFbosOit();
910   const Handle(OpenGl_FrameBuffer)* aGlFrontBackColorFBOs = aView->DepthPeelingFbos()->FrontBackColorFbosOit();
911   const Handle(OpenGl_FrameBuffer)& aGlBlendBackFBO = aView->DepthPeelingFbos()->BlendBackFboOit();
912
913   // Blended order-independent transparency algorithm require several preconditions to be enabled.
914   // It should be requested by user, at least two outputs from fragment shader should be supported by GPU,
915   // so is the given framebuffer should contain two additional color buffers to handle accumulated color channels,
916   // blended alpha channel and weight factors - these accumulation buffers are required
917   // to implement commuting blend operator (at least OpenGl 2.0 should be available).
918   if (anOitMode == Graphic3d_RTM_BLEND_OIT)
919   {
920     if (theOitAccumFbo == NULL
921     ||  theOitAccumFbo->NbColorBuffers() < 2
922     || !theOitAccumFbo->ColorTexture (0)->IsValid()
923     || !theOitAccumFbo->ColorTexture (1)->IsValid())
924     {
925       anOitMode = Graphic3d_RTM_BLEND_UNORDERED;
926     }
927   }
928   else if (anOitMode == Graphic3d_RTM_DEPTH_PEELING_OIT)
929   {
930     if (!aGlBlendBackFBO->IsValid())
931     {
932       anOitMode = Graphic3d_RTM_BLEND_UNORDERED;
933     }
934   }
935   const bool isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
936   int aDepthPeelingDrawId = -1;
937
938   switch (anOitMode)
939   {
940     case Graphic3d_RTM_BLEND_UNORDERED:
941     {
942       aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
943       break;
944     }
945     case Graphic3d_RTM_BLEND_OIT:
946     {
947       const float aDepthFactor = aView->RenderingParams().OitDepthFactor;
948       aManager->SetWeighedOitState (aDepthFactor);
949
950       theOitAccumFbo->BindBuffer (aCtx);
951
952       aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
953       aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha
954       aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
955       aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
956       aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
957       break;
958     }
959     case Graphic3d_RTM_DEPTH_PEELING_OIT:
960     {
961       static const float THE_MIN_DEPTH = 0.0f;
962       static const float THE_MAX_DEPTH = 1.0f;
963
964       aView->DepthPeelingFbos()->AttachDepthTexture (aCtx, theReadDrawFbo->DepthStencilTexture());
965
966       // initialize min/max depth buffer
967       aGlBlendBackFBO->BindDrawBuffer (aCtx);
968       aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
969       aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha
970       aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
971       aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
972
973       aGlDepthPeelFBOs[1]->BindDrawBuffer (aCtx);
974       aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
975       aCtx->core20fwd->glClearColor(-THE_MIN_DEPTH, THE_MAX_DEPTH, 0.0f, 0.0f);
976       aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
977
978       aGlFrontBackColorFBOs[0]->BindDrawBuffer (aCtx);
979       aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
980       aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
981       aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
982
983       aGlFrontBackColorFBOs[1]->BindDrawBuffer (aCtx);
984       aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
985       aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
986       aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
987
988       // draw depth for first pass to peel
989       aGlDepthPeelFBOs[0]->BindBuffer (aCtx);
990
991       aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
992       aCtx->core20fwd->glClearColor (THE_DEPTH_CLEAR_VALUE, THE_DEPTH_CLEAR_VALUE, 0.0f, 0.0f);
993       aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
994       aCtx->core20fwd->glBlendEquation (GL_MAX);
995
996       aManager->SetOitState (Graphic3d_RTM_DEPTH_PEELING_OIT);
997
998       aGlDepthPeelFBOs[1]->ColorTexture (0)->Bind (aCtx, aCtx->DepthPeelingDepthTexUnit());
999       aGlDepthPeelFBOs[1]->ColorTexture (1)->Bind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
1000       break;
1001     }
1002   }
1003
1004   // During blended order-independent transparency pass the depth test
1005   // should be enabled to discard fragments covered by opaque geometry
1006   // and depth writing should be disabled, because transparent fragments
1007   // overall each other with non unitary coverage factor.
1008   OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
1009   aGlobalSettings.DepthMask   = GL_FALSE;
1010   aCtx->core11fwd->glDepthMask (GL_FALSE);
1011
1012   for (theLayerIter = aLayerFrom; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
1013   {
1014     renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
1015   }
1016
1017   switch (anOitMode)
1018   {
1019     case Graphic3d_RTM_BLEND_UNORDERED:
1020     {
1021       break;
1022     }
1023     case Graphic3d_RTM_BLEND_OIT:
1024     {
1025       // revert state of rendering
1026       aManager->ResetOitState();
1027       theOitAccumFbo->UnbindBuffer (aCtx);
1028       if (theReadDrawFbo)
1029       {
1030         theReadDrawFbo->BindBuffer (aCtx);
1031       }
1032
1033       aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
1034       aCtx->SetColorMask (true); // update writes into alpha component
1035       break;
1036     }
1037     case Graphic3d_RTM_DEPTH_PEELING_OIT:
1038     {
1039       // Dual Depth Peeling Ping-Pong
1040       const int aNbPasses = aView->RenderingParams().NbOitDepthPeelingLayers;
1041       OpenGl_VertexBuffer* aQuadVerts = aView->initBlitQuad (false);
1042
1043       aGlDepthPeelFBOs[1]->ColorTexture (1)->Unbind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
1044       aGlDepthPeelFBOs[1]->ColorTexture (0)->Unbind (aCtx, aCtx->DepthPeelingDepthTexUnit());
1045
1046       for (int aPass = 0; aPass < aNbPasses; ++aPass)
1047       {
1048         const int aReadId = aPass % 2;
1049         aDepthPeelingDrawId = 1 - aReadId;
1050
1051         aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
1052         aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
1053         aCtx->core20fwd->glClearColor (THE_DEPTH_CLEAR_VALUE, THE_DEPTH_CLEAR_VALUE, 0.0f, 0.0f);
1054         aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
1055
1056         aGlFrontBackColorFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
1057         aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
1058         aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
1059         aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
1060
1061         ///aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
1062         aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindBuffer (aCtx);
1063         aCtx->SetDrawBuffers (3, THE_DRAW_BUFFERS012);
1064         aCtx->core20fwd->glBlendEquation (GL_MAX);
1065
1066         aGlDepthPeelFBOs[aReadId]->ColorTexture (0)->Bind (aCtx, aCtx->DepthPeelingDepthTexUnit());
1067         aGlDepthPeelFBOs[aReadId]->ColorTexture (1)->Bind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
1068
1069         // draw geometry
1070         for (theLayerIter = aLayerFrom; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
1071         {
1072           renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
1073         }
1074
1075         aGlDepthPeelFBOs[aReadId]->ColorTexture (1)->Unbind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
1076         aGlDepthPeelFBOs[aReadId]->ColorTexture (0)->Unbind (aCtx, aCtx->DepthPeelingDepthTexUnit());
1077
1078         // blend back color
1079         aGlBlendBackFBO->BindDrawBuffer (aCtx);
1080         aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
1081         if (aQuadVerts->IsValid()
1082          && aManager->BindOitDepthPeelingBlendProgram (isMSAA))
1083         {
1084           aCtx->core20fwd->glBlendEquation (GL_FUNC_ADD);
1085           aCtx->core20fwd->glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1086           aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1087
1088           aQuadVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1089
1090           const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
1091           aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (2)->Bind (aCtx, Graphic3d_TextureUnit_0);
1092
1093           aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1094
1095           aQuadVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1096           aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (2)->Unbind (aCtx, Graphic3d_TextureUnit_0);
1097           aCtx->BindProgram (NULL);
1098
1099           if (!aTextureBack.IsNull())
1100           {
1101             aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
1102           }
1103
1104           aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
1105         }
1106         else
1107         {
1108           aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1109                              "Initialization of OIT compositing pass has failed.\n"
1110                              "  Depth Peeling order-independent transparency will not be available.\n");
1111           if (aView != NULL)
1112           {
1113             Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
1114             aOITFlag = Standard_True;
1115           }
1116         }
1117       }
1118
1119       aManager->ResetOitState();
1120       aGlBlendBackFBO->UnbindBuffer (aCtx);
1121       if (theReadDrawFbo)
1122       {
1123         theReadDrawFbo->BindBuffer (aCtx);
1124       }
1125       aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
1126       aCtx->SetColorMask (true); // update writes into alpha component
1127       break;
1128     }
1129   }
1130
1131   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
1132   switch (anOitMode)
1133   {
1134     case Graphic3d_RTM_BLEND_UNORDERED:
1135     {
1136       break;
1137     }
1138     case Graphic3d_RTM_BLEND_OIT:
1139     {
1140       // draw full screen quad with special shader to compose the buffers
1141       OpenGl_VertexBuffer* aVerts = aView->initBlitQuad (Standard_False);
1142       if (aVerts->IsValid()
1143        && aManager->BindOitCompositingProgram (isMSAA))
1144       {
1145         aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
1146         aCtx->core11fwd->glDepthMask (GL_FALSE);
1147
1148         aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1149
1150         const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
1151         theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
1152         theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
1153
1154         aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
1155         aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1156
1157         aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1158         theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
1159         theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
1160         aCtx->BindProgram (NULL);
1161
1162         if (!aTextureBack.IsNull())
1163         {
1164           aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
1165         }
1166       }
1167       else
1168       {
1169         aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1170                            "Initialization of OIT compositing pass has failed.\n"
1171                            "  Blended order-independent transparency will not be available.\n");
1172         if (aView != NULL)
1173         {
1174           Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
1175           aOITFlag = Standard_True;
1176         }
1177       }
1178       break;
1179     }
1180     case Graphic3d_RTM_DEPTH_PEELING_OIT:
1181     {
1182       // compose depth peeling results into destination FBO
1183       OpenGl_VertexBuffer* aVerts = aView->initBlitQuad (Standard_False);
1184       if (aVerts->IsValid()
1185        && aManager->BindOitDepthPeelingFlushProgram (isMSAA))
1186       {
1187         aCtx->core20fwd->glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1188         aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1189
1190         aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1191
1192         const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
1193         aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_0);
1194         aGlBlendBackFBO->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_1);
1195
1196         aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1197
1198         aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1199         aGlBlendBackFBO->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_1);
1200         aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_0);
1201         aCtx->BindProgram (NULL);
1202
1203         if (!aTextureBack.IsNull())
1204         {
1205           aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
1206         }
1207
1208         aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
1209       }
1210       else
1211       {
1212         aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1213                            "Initialization of OIT compositing pass has failed.\n"
1214                            "  Depth Peeling order-independent transparency will not be available.\n");
1215         if (aView != NULL)
1216         {
1217           Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
1218           aOITFlag = true;
1219         }
1220       }
1221       aView->DepthPeelingFbos()->DetachDepthTexture (aCtx);
1222
1223       // Bind the framebuffer for reading depth and writing final color
1224       // after DetachDepthTexture() because after the function it's unbinded.
1225       if (theReadDrawFbo)
1226       {
1227         theReadDrawFbo->BindBuffer (aCtx);
1228       }
1229       break;
1230     }
1231   }
1232
1233   aCtx->core11fwd->glDisable (GL_BLEND);
1234   aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
1235   aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
1236   aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
1237 }
1238
1239 // =======================================================================
1240 // function : DumpJson
1241 // purpose  :
1242 // =======================================================================
1243 void OpenGl_LayerList::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1244 {
1245   OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_LayerList)
1246
1247   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayersIt (myLayers); aLayersIt.More(); aLayersIt.Next())
1248   {
1249     const Handle(Graphic3d_Layer)& aLayerId = aLayersIt.Value();
1250     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aLayerId.get())
1251   }
1252
1253   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbPriorities)
1254   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbStructures)
1255   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myImmediateNbStructures)
1256   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myModifStateOfRaytraceable)
1257 }