0029929: Visualization, V3d_View - make method ::FitMinMax() public
[occt.git] / src / OpenGl / OpenGl_LayerList.cxx
CommitLineData
6aca4d39 1// Created on: 2012-02-02
b311480e 2// Created by: Anton POLETAEV
6aca4d39 3// Copyright (c) 2012-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
59f45b7c 15
a1073ae2 16#include <OpenGl_GlCore15.hxx>
5f8b738e 17
f5b72419 18#include <BVH_LinearBuilder.hxx>
a1073ae2 19#include <OpenGl_FrameBuffer.hxx>
59f45b7c 20#include <OpenGl_LayerList.hxx>
a1073ae2 21#include <OpenGl_ShaderManager.hxx>
59f45b7c 22#include <OpenGl_Structure.hxx>
a1073ae2 23#include <OpenGl_VertexBuffer.hxx>
24#include <OpenGl_View.hxx>
550f3b8b 25#include <OpenGl_Workspace.hxx>
59f45b7c 26
c04c30b3 27#include <Graphic3d_GraphicDriver.hxx>
59f45b7c 28
f88457e6 29namespace
30{
31 //! Auxiliary class extending sequence iterator with index.
32 class OpenGl_IndexedLayerIterator : public OpenGl_SequenceOfLayers::Iterator
33 {
34 public:
35 //! Main constructor.
36 OpenGl_IndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq)
37 : OpenGl_SequenceOfLayers::Iterator (theSeq),
38 myIndex (theSeq.Lower()) {}
39
40 //! Return index of current position.
41 Standard_Integer Index() const { return myIndex; }
42
43 //! Move to the next position.
44 void Next()
45 {
46 OpenGl_SequenceOfLayers::Iterator::Next();
47 ++myIndex;
48 }
49
50 private:
51 Standard_Integer myIndex;
52 };
53
54 //! Iterator through layers with filter.
55 class OpenGl_FilteredIndexedLayerIterator
56 {
57 public:
58 //! Main constructor.
59 OpenGl_FilteredIndexedLayerIterator (const OpenGl_SequenceOfLayers& theSeq,
60 Standard_Integer theDefaultLayerIndex,
61 Standard_Boolean theToDrawImmediate,
62 OpenGl_LayerFilter theLayersToProcess)
63 : myIter (theSeq),
64 myDefaultLayerIndex (theDefaultLayerIndex),
65 myLayersToProcess (theLayersToProcess),
66 myToDrawImmediate (theToDrawImmediate)
67 {
68 next();
69 }
70
71 //! Return true if iterator points to the valid value.
72 bool More() const { return myIter.More(); }
73
74 //! Return layer at current position.
75 const OpenGl_Layer& Value() const { return *myIter.Value(); }
76
77 //! Return index of current position.
78 Standard_Integer Index() const { return myIter.Index(); }
79
80 //! Go to the next item.
81 void Next()
82 {
83 myIter.Next();
84 next();
85 }
86
87 private:
88 //! Look for the nearest item passing filters.
89 void next()
90 {
91 for (; myIter.More(); myIter.Next())
92 {
93 if (myIter.Value()->IsImmediate() != myToDrawImmediate)
94 {
95 continue;
96 }
97
98 switch (myLayersToProcess)
99 {
100 case OpenGl_LF_All:
101 {
102 break;
103 }
104 case OpenGl_LF_Upper:
105 {
106 if (myIter.Index() <= myDefaultLayerIndex)
107 {
108 continue;
109 }
110 break;
111 }
112 case OpenGl_LF_Bottom:
113 {
114 if (myIter.Index() >= myDefaultLayerIndex)
115 {
116 continue;
117 }
118 break;
119 }
120 case OpenGl_LF_Default:
121 {
122 if (myIter.Index() != myDefaultLayerIndex)
123 {
124 continue;
125 }
126 break;
127 }
128 }
129 return;
130 }
131 }
132 private:
133 OpenGl_IndexedLayerIterator myIter;
134 Standard_Integer myDefaultLayerIndex;
135 OpenGl_LayerFilter myLayersToProcess;
136 Standard_Boolean myToDrawImmediate;
137 };
138}
139
59f45b7c 140//=======================================================================
141//function : OpenGl_LayerList
142//purpose : Constructor
143//=======================================================================
144
145OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
f5b72419 146: myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
147 myDefaultLayerIndex (0),
bd6a8454 148 myNbPriorities (theNbPriorities),
a1954302 149 myNbStructures (0),
bd6a8454 150 myImmediateNbStructures (0),
a1073ae2 151 myModifStateOfRaytraceable (0),
152 myRenderOpaqueFilter (new OpenGl_OpaqueFilter()),
153 myRenderTranspFilter (new OpenGl_TransparentFilter())
59f45b7c 154{
a1954302 155 // insert default priority layers
f5b72419 156 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
af65fb19 157 myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD, myLayers.Upper());
158
f5b72419 159 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 160 myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
59f45b7c 161
f5b72419 162 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 163 myLayerIds.Bind (Graphic3d_ZLayerId_Top, myLayers.Upper());
59f45b7c 164
f5b72419 165 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 166 myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
59f45b7c 167
f5b72419 168 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 169 myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD, myLayers.Upper());
bd6a8454 170
171 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 172
173 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 174}
175
176//=======================================================================
a1954302 177//function : ~OpenGl_LayerList
178//purpose : Destructor
59f45b7c 179//=======================================================================
180
a1954302 181OpenGl_LayerList::~OpenGl_LayerList()
59f45b7c 182{
59f45b7c 183}
184
f5b72419 185//=======================================================================
186//function : SetFrustumCullingBVHBuilder
187//purpose :
188//=======================================================================
189void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
190{
191 myBVHBuilder = theBuilder;
192 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
193 {
194 anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
195 }
196}
197
59f45b7c 198//=======================================================================
199//function : AddLayer
200//purpose :
201//=======================================================================
202
a1954302 203void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 204{
a1954302 205 if (myLayerIds.IsBound (theLayerId))
206 {
59f45b7c 207 return;
a1954302 208 }
59f45b7c 209
210 // add the new layer
f5b72419 211 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
59f45b7c 212 myLayerIds.Bind (theLayerId, myLayers.Length());
a1073ae2 213
214 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 215}
216
c5751993 217//=======================================================================
218//function : Layer
219//purpose :
220//=======================================================================
a1954302 221OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
c5751993 222{
f5b72419 223 return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
c5751993 224}
225
226//=======================================================================
227//function : Layer
228//purpose :
229//=======================================================================
a1954302 230const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
c5751993 231{
f5b72419 232 return *myLayers.Value (myLayerIds.Find (theLayerId));
c5751993 233}
234
59f45b7c 235//=======================================================================
236//function : RemoveLayer
237//purpose :
238//=======================================================================
239
a1954302 240void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 241{
a1954302 242 if (!myLayerIds.IsBound (theLayerId)
243 || theLayerId <= 0)
244 {
59f45b7c 245 return;
a1954302 246 }
59f45b7c 247
a1954302 248 const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
59f45b7c 249
250 // move all displayed structures to first layer
f5b72419 251 {
252 const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
253 myLayers.ChangeFirst()->Append (aLayerToMove);
254 }
59f45b7c 255
256 // remove layer
257 myLayers.Remove (aRemovePos);
258 myLayerIds.UnBind (theLayerId);
259
260 // updated sequence indexes in map
bd6a8454 261 for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
59f45b7c 262 {
bd6a8454 263 Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
59f45b7c 264 if (aSeqIdx > aRemovePos)
265 aSeqIdx--;
266 }
bd6a8454 267
268 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 269
270 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 271}
272
273//=======================================================================
274//function : AddStructure
275//purpose :
276//=======================================================================
277
a1954302 278void OpenGl_LayerList::AddStructure (const OpenGl_Structure* theStruct,
279 const Graphic3d_ZLayerId theLayerId,
280 const Standard_Integer thePriority,
281 Standard_Boolean isForChangePriority)
59f45b7c 282{
283 // add structure to associated layer,
284 // if layer doesn't exists, display structure in default layer
a1954302 285 Standard_Integer aSeqPos = myLayers.Lower();
286 myLayerIds.Find (theLayerId, aSeqPos);
59f45b7c 287
f5b72419 288 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 289 aLayer.Add (theStruct, thePriority, isForChangePriority);
290 ++myNbStructures;
7c3ef2f7 291 if (aLayer.IsImmediate())
a1954302 292 {
293 ++myImmediateNbStructures;
294 }
e276548b 295
296 // Note: In ray-tracing mode we don't modify modification
297 // state here. It is redundant, because the possible changes
298 // will be handled in the loop for structures
59f45b7c 299}
300
301//=======================================================================
302//function : RemoveStructure
a1954302 303//purpose :
59f45b7c 304//=======================================================================
305
c357e426 306void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
59f45b7c 307{
c357e426 308 const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
a1954302 309
310 Standard_Integer aSeqPos = myLayers.Lower();
311 myLayerIds.Find (aLayerId, aSeqPos);
312
f5b72419 313 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 314 Standard_Integer aPriority = -1;
59f45b7c 315
316 // remove structure from associated list
317 // if the structure is not found there,
318 // scan through layers and remove it
c357e426 319 if (aLayer.Remove (theStructure, aPriority))
59f45b7c 320 {
a1954302 321 --myNbStructures;
7c3ef2f7 322 if (aLayer.IsImmediate())
a1954302 323 {
324 --myImmediateNbStructures;
325 }
e276548b 326
bd6a8454 327 if (aLayerId == Graphic3d_ZLayerId_Default
328 && theStructure->IsRaytracable())
e276548b 329 {
bd6a8454 330 ++myModifStateOfRaytraceable;
e276548b 331 }
e276548b 332
59f45b7c 333 return;
334 }
a1954302 335
59f45b7c 336 // scan through layers and remove it
f88457e6 337 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 338 {
f5b72419 339 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
f88457e6 340 if (aSeqPos == anIts.Index())
59f45b7c 341 {
a1954302 342 continue;
343 }
e276548b 344
c357e426 345 if (aLayerEx.Remove (theStructure, aPriority))
a1954302 346 {
347 --myNbStructures;
7c3ef2f7 348 if (aLayerEx.IsImmediate())
e276548b 349 {
a1954302 350 --myImmediateNbStructures;
e276548b 351 }
e276548b 352
f88457e6 353 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 354 && theStructure->IsRaytracable())
a1954302 355 {
bd6a8454 356 ++myModifStateOfRaytraceable;
a1954302 357 }
59f45b7c 358 return;
359 }
360 }
361}
362
b7cd4ba7 363//=======================================================================
364//function : InvalidateBVHData
365//purpose :
366//=======================================================================
a1954302 367void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
b7cd4ba7 368{
a1954302 369 Standard_Integer aSeqPos = myLayers.Lower();
370 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 371 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 372 aLayer.InvalidateBVHData();
b7cd4ba7 373}
374
59f45b7c 375//=======================================================================
376//function : ChangeLayer
377//purpose :
378//=======================================================================
379
a1954302 380void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure* theStructure,
381 const Graphic3d_ZLayerId theOldLayerId,
382 const Graphic3d_ZLayerId theNewLayerId)
59f45b7c 383{
a1954302 384 Standard_Integer aSeqPos = myLayers.Lower();
385 myLayerIds.Find (theOldLayerId, aSeqPos);
f5b72419 386 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 387 Standard_Integer aPriority = -1;
59f45b7c 388
389 // take priority and remove structure from list found by <theOldLayerId>
390 // if the structure is not found there, scan through all other layers
3fe9ce0e 391 if (aLayer.Remove (theStructure, aPriority, Standard_False))
59f45b7c 392 {
bd6a8454 393 if (theOldLayerId == Graphic3d_ZLayerId_Default
394 && theStructure->IsRaytracable())
395 {
396 ++myModifStateOfRaytraceable;
397 }
398
a1954302 399 --myNbStructures;
7c3ef2f7 400 if (aLayer.IsImmediate())
a1954302 401 {
402 --myImmediateNbStructures;
403 }
404
a0c20252 405 // isForChangePriority should be Standard_False below, because we want
406 // the BVH tree in the target layer to be updated with theStructure
407 AddStructure (theStructure, theNewLayerId, aPriority);
a1954302 408 return;
59f45b7c 409 }
a1954302 410
411 // scan through layers and remove it
f88457e6 412 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 413 {
f88457e6 414 if (aSeqPos == anIts.Index())
59f45b7c 415 {
a1954302 416 continue;
417 }
59f45b7c 418
a1954302 419 // try to remove structure and get priority value from this layer
f5b72419 420 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 421 if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
422 {
f88457e6 423 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 424 && theStructure->IsRaytracable())
425 {
426 ++myModifStateOfRaytraceable;
427 }
428
a1954302 429 --myNbStructures;
7c3ef2f7 430 if (aLayerEx.IsImmediate())
b7cd4ba7 431 {
a1954302 432 --myImmediateNbStructures;
b7cd4ba7 433 }
a1954302 434
435 // isForChangePriority should be Standard_False below, because we want
436 // the BVH tree in the target layer to be updated with theStructure
437 AddStructure (theStructure, theNewLayerId, aPriority);
438 return;
b7cd4ba7 439 }
440 }
441}
442
443//=======================================================================
444//function : ChangePriority
445//purpose :
446//=======================================================================
a1954302 447void OpenGl_LayerList::ChangePriority (const OpenGl_Structure* theStructure,
448 const Graphic3d_ZLayerId theLayerId,
449 const Standard_Integer theNewPriority)
b7cd4ba7 450{
a1954302 451 Standard_Integer aSeqPos = myLayers.Lower();
452 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 453 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 454 Standard_Integer anOldPriority = -1;
b7cd4ba7 455
a1954302 456 if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
b7cd4ba7 457 {
a1954302 458 --myNbStructures;
7c3ef2f7 459 if (aLayer.IsImmediate())
a1954302 460 {
461 --myImmediateNbStructures;
462 }
463
b7cd4ba7 464 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
a1954302 465 return;
b7cd4ba7 466 }
a1954302 467
f88457e6 468 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
b7cd4ba7 469 {
f88457e6 470 if (aSeqPos == anIts.Index())
b7cd4ba7 471 {
a1954302 472 continue;
473 }
b7cd4ba7 474
f5b72419 475 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 476 if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
477 {
478 --myNbStructures;
7c3ef2f7 479 if (aLayerEx.IsImmediate())
59f45b7c 480 {
a1954302 481 --myImmediateNbStructures;
59f45b7c 482 }
a1954302 483
484 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
485 return;
59f45b7c 486 }
487 }
488}
489
490//=======================================================================
a1954302 491//function : SetLayerSettings
492//purpose :
59f45b7c 493//=======================================================================
a1954302 494void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId theLayerId,
495 const Graphic3d_ZLayerSettings& theSettings)
496{
497 OpenGl_Layer& aLayer = Layer (theLayerId);
7c3ef2f7 498 if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
a1954302 499 {
7c3ef2f7 500 if (theSettings.IsImmediate())
a1954302 501 {
502 myImmediateNbStructures += aLayer.NbStructures();
503 }
504 else
505 {
506 myImmediateNbStructures -= aLayer.NbStructures();
507 }
508 }
509 aLayer.SetLayerSettings (theSettings);
510}
59f45b7c 511
2b8832bb 512//=======================================================================
513//function : UpdateCulling
514//purpose :
515//=======================================================================
516void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
517 const Standard_Boolean theToDrawImmediate)
518{
5dc0517d 519 const Standard_Integer aViewId = theWorkspace->View()->Identification();
2b8832bb 520 const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
521 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
522 {
523 OpenGl_Layer& aLayer = *anIts.ChangeValue();
524 if (aLayer.IsImmediate() != theToDrawImmediate)
525 {
526 continue;
527 }
528
5dc0517d 529 aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->IsCullingEnabled());
2b8832bb 530 }
531}
532
a1954302 533//=======================================================================
534//function : Render
535//purpose :
536//=======================================================================
537void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
91c60b57 538 const Standard_Boolean theToDrawImmediate,
a1073ae2 539 const OpenGl_LayerFilter theLayersToProcess,
540 OpenGl_FrameBuffer* theReadDrawFbo,
541 OpenGl_FrameBuffer* theOitAccumFbo) const
59f45b7c 542{
a1073ae2 543 // Remember global settings for glDepth function and write mask.
f88457e6 544 OpenGl_GlobalLayerSettings aPrevSettings;
c5751993 545
a1954302 546 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
f88457e6 547 aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc);
548 aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
549 OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
a1954302 550
a1073ae2 551 // Two render filters are used to support transparency draw. Opaque filter accepts
552 // only non-transparent OpenGl elements of a layer and counts number of skipped
553 // transparent ones. If the counter has positive value the layer is added into
554 // transparency post-processing stack. At the end of drawing or once the depth
555 // buffer is to be cleared the layers in the stack should be drawn using
556 // blending and depth mask settings and another transparency filter which accepts
557 // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
558 // was preallocated before going into this method and has enough space to keep
559 // maximum number of references to layers, therefore it will not increase memory
560 // fragmentation during regular rendering.
561 const Handle(OpenGl_RenderFilter) aPrevFilter = theWorkspace->GetRenderFilter();
562 myRenderOpaqueFilter->SetPreviousFilter (aPrevFilter);
563 myRenderTranspFilter->SetPreviousFilter (aPrevFilter);
564 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
565
566 myTransparentToProcess.Clear();
567
568 OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
f88457e6 569 Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
570 const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
571 && aPrevSettings.DepthMask == GL_TRUE;
992ed6b3 572 const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
f88457e6 573 for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
59f45b7c 574 {
f88457e6 575 bool hasSkippedDepthLayers = false;
576 for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
91c60b57 577 {
f88457e6 578 if (aPassIter == 0)
579 {
580 aCtx->SetColorMask (false);
992ed6b3 581 aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
f88457e6 582 aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
583 aDefaultSettings.DepthMask = GL_TRUE;
584 }
585 else if (aPassIter == 1)
586 {
587 if (!hasSkippedDepthLayers)
588 {
589 continue;
590 }
591 aCtx->SetColorMask (true);
992ed6b3 592 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 593 aDefaultSettings = aPrevSettings;
594 }
595 else if (aPassIter == 2)
596 {
597 aCtx->SetColorMask (true);
992ed6b3 598 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 599 if (toPerformDepthPrepass)
600 {
601 aDefaultSettings.DepthFunc = GL_EQUAL;
602 aDefaultSettings.DepthMask = GL_FALSE;
603 }
604 }
91c60b57 605
f88457e6 606 OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
607 for (; aLayerIter.More(); aLayerIter.Next())
608 {
609 const OpenGl_Layer& aLayer = aLayerIter.Value();
610
611 // make sure to clear depth of previous layers even if layer has no structures
612 if (aLayer.LayerSettings().ToClearDepth())
613 {
614 aClearDepthLayer = aLayerIter.Index();
615 }
2b8832bb 616 if (aLayer.IsCulled())
f88457e6 617 {
618 continue;
619 }
620 else if (aClearDepthLayer > aClearDepthLayerPrev)
621 {
622 // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
623 // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
624 // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
625 if (aPassIter == 2)
626 {
627 aLayerIterStart = aLayerIter;
628 }
629 else
630 {
631 aClearDepthLayer = -1;
632 }
633 break;
634 }
635 else if (aPassIter == 0
636 && !aLayer.LayerSettings().ToRenderInDepthPrepass())
637 {
638 hasSkippedDepthLayers = true;
639 continue;
640 }
641 else if (aPassIter == 1
642 && aLayer.LayerSettings().ToRenderInDepthPrepass())
643 {
644 continue;
645 }
646
647 // Render opaque OpenGl elements of a layer and count the number of skipped.
648 // If a layer has skipped (e.g. transparent) elements it should be added into
649 // the transparency post-processing stack.
650 myRenderOpaqueFilter->SetSkippedCounter (0);
651
652 aLayer.Render (theWorkspace, aDefaultSettings);
653
654 if (aPassIter != 0
655 && myRenderOpaqueFilter->NbSkipped() > 0)
656 {
657 myTransparentToProcess.Push (&aLayer);
658 }
659 }
660 if (aPassIter == 2
661 && !aLayerIter.More())
662 {
663 aLayerIterStart = aLayerIter;
664 }
a1954302 665 }
f88457e6 666
667 if (!myTransparentToProcess.IsEmpty())
59f45b7c 668 {
f88457e6 669 renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
59f45b7c 670 }
f88457e6 671 if (aClearDepthLayer > aClearDepthLayerPrev)
a1954302 672 {
f88457e6 673 aClearDepthLayerPrev = aClearDepthLayer;
b3eab8ef 674 glDepthMask (GL_TRUE);
675 glClear (GL_DEPTH_BUFFER_BIT);
a1954302 676 }
b3eab8ef 677 }
678
f88457e6 679 aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
680 aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
a1073ae2 681
682 theWorkspace->SetRenderFilter (aPrevFilter);
683}
684
685//=======================================================================
686//function : renderTransparent
687//purpose : Render transparent objects using blending operator.
688//=======================================================================
689void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theWorkspace,
690 OpenGl_LayerStack::iterator& theLayerIter,
691 const OpenGl_GlobalLayerSettings& theGlobalSettings,
692 OpenGl_FrameBuffer* theReadDrawFbo,
693 OpenGl_FrameBuffer* theOitAccumFbo) const
694{
695 // Blended order-independent transparency algorithm require several preconditions
696 // to be enabled. It should be requested by user, at least two outputs from
697 // fragment shader should be supported by GPU, so is the given framebuffer
698 // should contain two additional color buffers to handle accumulated color channels,
699 // blended alpha channel and weight factors - these accumulation buffers are required
700 // to implement commuting blend operator (at least OpenGl 2.0 should be available).
701 const bool isEnabledOit = theOitAccumFbo != NULL
702 && theOitAccumFbo->NbColorBuffers() >= 2
703 && theOitAccumFbo->ColorTexture (0)->IsValid()
704 && theOitAccumFbo->ColorTexture (1)->IsValid();
705
706 // Check if current iterator has already reached the end of the stack.
707 // This should happen if no additional layers has been added to
708 // the processing stack after last transparency pass.
709 if (theLayerIter == myTransparentToProcess.Back())
710 {
711 return;
712 }
713
714 const Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
715 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
716 OpenGl_View* aView = theWorkspace->View();
717 const float aDepthFactor = aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
718
719 theWorkspace->SetRenderFilter (myRenderTranspFilter);
720
721 aCtx->core11fwd->glEnable (GL_BLEND);
722
723 if (isEnabledOit)
724 {
725 aManager->SetOitState (true, aDepthFactor);
726
727 theOitAccumFbo->BindBuffer (aCtx);
728
729 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
730 aCtx->SetDrawBuffers (2, aDrawBuffers);
731 aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
732 aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
733 aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
734 }
735 else
736 {
737 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
738 }
739
740 // During blended order-independent transparency pass the depth test
741 // should be enabled to discard fragments covered by opaque geometry
742 // and depth writing should be disabled, because transparent fragments
743 // overal each other with non unitary coverage factor.
744 OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
745 aGlobalSettings.DepthMask = GL_FALSE;
746 aCtx->core11fwd->glDepthMask (GL_FALSE);
747
748 for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
749 {
750 (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
751 }
752
753 // Revert state of rendering.
754 if (isEnabledOit)
755 {
756 aManager->SetOitState (false, aDepthFactor);
757 theOitAccumFbo->UnbindBuffer (aCtx);
758 if (theReadDrawFbo)
759 {
760 theReadDrawFbo->BindBuffer (aCtx);
761 }
762
763 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
764 aCtx->SetDrawBuffers (1, aDrawBuffers);
765 }
766
767 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
768 if (isEnabledOit)
769 {
770 const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
771 OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
772 if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
773 {
774 aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
775 aCtx->core11fwd->glDepthMask (GL_FALSE);
776
777 // Bind full screen quad buffer and framebuffer resources.
778 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
779
cc8cbabe 780 const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
a1073ae2 781
cc8cbabe 782 theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
783 theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 784
785 // Draw full screen quad with special shader to compose the buffers.
786 aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
787 aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
788
789 // Unbind OpenGL texture objects and shader program.
790 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
cc8cbabe 791 theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
792 theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 793 aCtx->BindProgram (NULL);
794
795 if (!aTextureBack.IsNull())
796 {
cc8cbabe 797 aCtx->BindTextures (aTextureBack);
a1073ae2 798 }
799 }
800 else
801 {
802 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
803 "Initialization of OIT compositing pass has failed.\n"
804 " Blended order-independent transparency will not be available.\n");
805 if (aView != NULL)
806 {
807 Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
808 aOITFlag = Standard_True;
809 }
810 }
811 }
812
813 aCtx->core11fwd->glDisable (GL_BLEND);
814 aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
815 aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
816 aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
817}
818
819//=======================================================================
820//class : OpenGl_OpaqueFilter
821//function : ShouldRender
822//purpose : Checks whether the element should be rendered or skipped.
823//=======================================================================
824Standard_Boolean OpenGl_LayerList::OpenGl_OpaqueFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
825 const OpenGl_Element* theGlElement)
826{
827 if (!myFilter.IsNull()
828 && !myFilter->ShouldRender (theWorkspace, theGlElement))
829 {
830 return Standard_False;
831 }
832
64c6d8df 833 if (!theGlElement->IsFillDrawMode())
a1073ae2 834 {
835 return Standard_True;
836 }
837
a1073ae2 838 if (OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 839 theWorkspace->HighlightStyle()))
a1073ae2 840 {
841 ++mySkippedCounter;
842 return Standard_False;
843 }
844
845 return Standard_True;
846}
847
848//=======================================================================
849//class : OpenGl_TransparentFilter
850//function : ShouldRender
851//purpose : Checks whether the element should be rendered or skipped.
852//=======================================================================
853Standard_Boolean OpenGl_LayerList::OpenGl_TransparentFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
854 const OpenGl_Element* theGlElement)
855{
856 if (!myFilter.IsNull()
857 && !myFilter->ShouldRender (theWorkspace, theGlElement))
858 {
859 return Standard_False;
860 }
861
64c6d8df 862 if (!theGlElement->IsFillDrawMode())
a1073ae2 863 {
864 return dynamic_cast<const OpenGl_AspectFace*> (theGlElement) != NULL;
865 }
866
a1073ae2 867 return OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 868 theWorkspace->HighlightStyle());
59f45b7c 869}