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.
OpenGl_IndexedLayerIterator(const NCollection_List<Handle (Graphic3d_Layer)> & theSeq)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.
Index() const43 Standard_Integer Index() const { return myIndex; }
44
45 //! Move to the next position.
Next()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.
OpenGl_FilteredIndexedLayerIterator(const NCollection_List<Handle (Graphic3d_Layer)> & theSeq,Standard_Boolean theToDrawImmediate,OpenGl_LayerFilter theLayersToProcess)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.
More() const72 bool More() const { return myIter.More(); }
73
74 //! Return layer at current position.
Value() const75 const OpenGl_Layer& Value() const { return *myIter.Value(); }
76
77 //! Return index of current position.
Index() const78 Standard_Integer Index() const { return myIter.Index(); }
79
80 //! Go to the next item.
Next()81 void Next()
82 {
83 myIter.Next();
84 next();
85 }
86
87 private:
88 //! Look for the nearest item passing filters.
next()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
OpenGl_LayerList(const Standard_Integer theNbPriorities)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
~OpenGl_LayerList()174 OpenGl_LayerList::~OpenGl_LayerList()
175 {
176 }
177
178 //=======================================================================
179 //function : SetFrustumCullingBVHBuilder
180 //purpose :
181 //=======================================================================
SetFrustumCullingBVHBuilder(const Handle (Select3D_BVHBuilder3d)& theBuilder)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 //=======================================================================
InsertLayerBefore(const Graphic3d_ZLayerId theNewLayerId,const Graphic3d_ZLayerSettings & theSettings,const Graphic3d_ZLayerId theLayerAfter)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 //=======================================================================
InsertLayerAfter(const Graphic3d_ZLayerId theNewLayerId,const Graphic3d_ZLayerSettings & theSettings,const Graphic3d_ZLayerId theLayerBefore)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 //=======================================================================
RemoveLayer(const Graphic3d_ZLayerId theLayerId)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
AddStructure(const OpenGl_Structure * theStruct,const Graphic3d_ZLayerId theLayerId,const Standard_Integer thePriority,Standard_Boolean isForChangePriority)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
RemoveStructure(const OpenGl_Structure * theStructure)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 //=======================================================================
InvalidateBVHData(const Graphic3d_ZLayerId theLayerId)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
ChangeLayer(const OpenGl_Structure * theStructure,const Graphic3d_ZLayerId theOldLayerId,const Graphic3d_ZLayerId theNewLayerId)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 //=======================================================================
ChangePriority(const OpenGl_Structure * theStructure,const Graphic3d_ZLayerId theLayerId,const Standard_Integer theNewPriority)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 //=======================================================================
SetLayerSettings(const Graphic3d_ZLayerId theLayerId,const Graphic3d_ZLayerSettings & theSettings)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 //=======================================================================
UpdateCulling(const Handle (OpenGl_Workspace)& theWorkspace,const Standard_Boolean theToDrawImmediate)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 //=======================================================================
renderLayer(const Handle (OpenGl_Workspace)& theWorkspace,const OpenGl_GlobalLayerSettings & theDefaultSettings,const Graphic3d_Layer & theLayer) const563 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 //=======================================================================
Render(const Handle (OpenGl_Workspace)& theWorkspace,const Standard_Boolean theToDrawImmediate,const OpenGl_LayerFilter theLayersToProcess,OpenGl_FrameBuffer * theReadDrawFbo,OpenGl_FrameBuffer * theOitAccumFbo) const719 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 //=======================================================================
renderTransparent(const Handle (OpenGl_Workspace)& theWorkspace,OpenGl_LayerStack::iterator & theLayerIter,const OpenGl_GlobalLayerSettings & theGlobalSettings,OpenGl_FrameBuffer * theReadDrawFbo,OpenGl_FrameBuffer * theOitAccumFbo) const882 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 // =======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const1243 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 }
1258