0029283: Visualization - allow defining more than 8 light sources
[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
185//=======================================================================
f5b72419 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
198//=======================================================================
59f45b7c 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
217//=======================================================================
c5751993 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
235//=======================================================================
59f45b7c 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
363//=======================================================================
b7cd4ba7 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
375//=======================================================================
59f45b7c 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
a1954302 512//=======================================================================
513//function : Render
514//purpose :
515//=======================================================================
516void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
91c60b57 517 const Standard_Boolean theToDrawImmediate,
a1073ae2 518 const OpenGl_LayerFilter theLayersToProcess,
519 OpenGl_FrameBuffer* theReadDrawFbo,
520 OpenGl_FrameBuffer* theOitAccumFbo) const
59f45b7c 521{
a1073ae2 522 // Remember global settings for glDepth function and write mask.
f88457e6 523 OpenGl_GlobalLayerSettings aPrevSettings;
c5751993 524
a1954302 525 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
f88457e6 526 aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc);
527 aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
528 OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
a1954302 529
a1073ae2 530 // Two render filters are used to support transparency draw. Opaque filter accepts
531 // only non-transparent OpenGl elements of a layer and counts number of skipped
532 // transparent ones. If the counter has positive value the layer is added into
533 // transparency post-processing stack. At the end of drawing or once the depth
534 // buffer is to be cleared the layers in the stack should be drawn using
535 // blending and depth mask settings and another transparency filter which accepts
536 // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
537 // was preallocated before going into this method and has enough space to keep
538 // maximum number of references to layers, therefore it will not increase memory
539 // fragmentation during regular rendering.
540 const Handle(OpenGl_RenderFilter) aPrevFilter = theWorkspace->GetRenderFilter();
541 myRenderOpaqueFilter->SetPreviousFilter (aPrevFilter);
542 myRenderTranspFilter->SetPreviousFilter (aPrevFilter);
543 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
544
545 myTransparentToProcess.Clear();
546
547 OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
f88457e6 548 Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
549 const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
550 && aPrevSettings.DepthMask == GL_TRUE;
551 for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
59f45b7c 552 {
f88457e6 553 bool hasSkippedDepthLayers = false;
554 for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
91c60b57 555 {
f88457e6 556 if (aPassIter == 0)
557 {
558 aCtx->SetColorMask (false);
559 aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
560 aDefaultSettings.DepthMask = GL_TRUE;
561 }
562 else if (aPassIter == 1)
563 {
564 if (!hasSkippedDepthLayers)
565 {
566 continue;
567 }
568 aCtx->SetColorMask (true);
569 aDefaultSettings = aPrevSettings;
570 }
571 else if (aPassIter == 2)
572 {
573 aCtx->SetColorMask (true);
574 if (toPerformDepthPrepass)
575 {
576 aDefaultSettings.DepthFunc = GL_EQUAL;
577 aDefaultSettings.DepthMask = GL_FALSE;
578 }
579 }
91c60b57 580
f88457e6 581 OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
582 for (; aLayerIter.More(); aLayerIter.Next())
583 {
584 const OpenGl_Layer& aLayer = aLayerIter.Value();
585
586 // make sure to clear depth of previous layers even if layer has no structures
587 if (aLayer.LayerSettings().ToClearDepth())
588 {
589 aClearDepthLayer = aLayerIter.Index();
590 }
591 if (aLayer.NbStructures() < 1)
592 {
593 continue;
594 }
595 else if (aClearDepthLayer > aClearDepthLayerPrev)
596 {
597 // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
598 // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
599 // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
600 if (aPassIter == 2)
601 {
602 aLayerIterStart = aLayerIter;
603 }
604 else
605 {
606 aClearDepthLayer = -1;
607 }
608 break;
609 }
610 else if (aPassIter == 0
611 && !aLayer.LayerSettings().ToRenderInDepthPrepass())
612 {
613 hasSkippedDepthLayers = true;
614 continue;
615 }
616 else if (aPassIter == 1
617 && aLayer.LayerSettings().ToRenderInDepthPrepass())
618 {
619 continue;
620 }
621
622 // Render opaque OpenGl elements of a layer and count the number of skipped.
623 // If a layer has skipped (e.g. transparent) elements it should be added into
624 // the transparency post-processing stack.
625 myRenderOpaqueFilter->SetSkippedCounter (0);
626
627 aLayer.Render (theWorkspace, aDefaultSettings);
628
629 if (aPassIter != 0
630 && myRenderOpaqueFilter->NbSkipped() > 0)
631 {
632 myTransparentToProcess.Push (&aLayer);
633 }
634 }
635 if (aPassIter == 2
636 && !aLayerIter.More())
637 {
638 aLayerIterStart = aLayerIter;
639 }
a1954302 640 }
f88457e6 641
642 if (!myTransparentToProcess.IsEmpty())
59f45b7c 643 {
f88457e6 644 renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
59f45b7c 645 }
f88457e6 646 if (aClearDepthLayer > aClearDepthLayerPrev)
a1954302 647 {
f88457e6 648 aClearDepthLayerPrev = aClearDepthLayer;
b3eab8ef 649 glDepthMask (GL_TRUE);
650 glClear (GL_DEPTH_BUFFER_BIT);
a1954302 651 }
b3eab8ef 652 }
653
f88457e6 654 aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
655 aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
a1073ae2 656
657 theWorkspace->SetRenderFilter (aPrevFilter);
658}
659
660//=======================================================================
661//function : renderTransparent
662//purpose : Render transparent objects using blending operator.
663//=======================================================================
664void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theWorkspace,
665 OpenGl_LayerStack::iterator& theLayerIter,
666 const OpenGl_GlobalLayerSettings& theGlobalSettings,
667 OpenGl_FrameBuffer* theReadDrawFbo,
668 OpenGl_FrameBuffer* theOitAccumFbo) const
669{
670 // Blended order-independent transparency algorithm require several preconditions
671 // to be enabled. It should be requested by user, at least two outputs from
672 // fragment shader should be supported by GPU, so is the given framebuffer
673 // should contain two additional color buffers to handle accumulated color channels,
674 // blended alpha channel and weight factors - these accumulation buffers are required
675 // to implement commuting blend operator (at least OpenGl 2.0 should be available).
676 const bool isEnabledOit = theOitAccumFbo != NULL
677 && theOitAccumFbo->NbColorBuffers() >= 2
678 && theOitAccumFbo->ColorTexture (0)->IsValid()
679 && theOitAccumFbo->ColorTexture (1)->IsValid();
680
681 // Check if current iterator has already reached the end of the stack.
682 // This should happen if no additional layers has been added to
683 // the processing stack after last transparency pass.
684 if (theLayerIter == myTransparentToProcess.Back())
685 {
686 return;
687 }
688
689 const Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
690 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
691 OpenGl_View* aView = theWorkspace->View();
692 const float aDepthFactor = aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
693
694 theWorkspace->SetRenderFilter (myRenderTranspFilter);
695
696 aCtx->core11fwd->glEnable (GL_BLEND);
697
698 if (isEnabledOit)
699 {
700 aManager->SetOitState (true, aDepthFactor);
701
702 theOitAccumFbo->BindBuffer (aCtx);
703
704 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
705 aCtx->SetDrawBuffers (2, aDrawBuffers);
706 aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
707 aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
708 aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
709 }
710 else
711 {
712 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
713 }
714
715 // During blended order-independent transparency pass the depth test
716 // should be enabled to discard fragments covered by opaque geometry
717 // and depth writing should be disabled, because transparent fragments
718 // overal each other with non unitary coverage factor.
719 OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
720 aGlobalSettings.DepthMask = GL_FALSE;
721 aCtx->core11fwd->glDepthMask (GL_FALSE);
722
723 for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
724 {
725 (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
726 }
727
728 // Revert state of rendering.
729 if (isEnabledOit)
730 {
731 aManager->SetOitState (false, aDepthFactor);
732 theOitAccumFbo->UnbindBuffer (aCtx);
733 if (theReadDrawFbo)
734 {
735 theReadDrawFbo->BindBuffer (aCtx);
736 }
737
738 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
739 aCtx->SetDrawBuffers (1, aDrawBuffers);
740 }
741
742 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
743 if (isEnabledOit)
744 {
745 const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
746 OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
747 if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
748 {
749 aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
750 aCtx->core11fwd->glDepthMask (GL_FALSE);
751
752 // Bind full screen quad buffer and framebuffer resources.
753 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
754
cc8cbabe 755 const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
a1073ae2 756
cc8cbabe 757 theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
758 theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 759
760 // Draw full screen quad with special shader to compose the buffers.
761 aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
762 aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
763
764 // Unbind OpenGL texture objects and shader program.
765 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
cc8cbabe 766 theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
767 theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 768 aCtx->BindProgram (NULL);
769
770 if (!aTextureBack.IsNull())
771 {
cc8cbabe 772 aCtx->BindTextures (aTextureBack);
a1073ae2 773 }
774 }
775 else
776 {
777 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
778 "Initialization of OIT compositing pass has failed.\n"
779 " Blended order-independent transparency will not be available.\n");
780 if (aView != NULL)
781 {
782 Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
783 aOITFlag = Standard_True;
784 }
785 }
786 }
787
788 aCtx->core11fwd->glDisable (GL_BLEND);
789 aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
790 aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
791 aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
792}
793
794//=======================================================================
795//class : OpenGl_OpaqueFilter
796//function : ShouldRender
797//purpose : Checks whether the element should be rendered or skipped.
798//=======================================================================
799Standard_Boolean OpenGl_LayerList::OpenGl_OpaqueFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
800 const OpenGl_Element* theGlElement)
801{
802 if (!myFilter.IsNull()
803 && !myFilter->ShouldRender (theWorkspace, theGlElement))
804 {
805 return Standard_False;
806 }
807
808 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
809 if (aPArray == NULL
8e0a2b19 810 || !aPArray->IsFillDrawMode())
a1073ae2 811 {
812 return Standard_True;
813 }
814
a1073ae2 815 if (OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 816 theWorkspace->HighlightStyle()))
a1073ae2 817 {
818 ++mySkippedCounter;
819 return Standard_False;
820 }
821
822 return Standard_True;
823}
824
825//=======================================================================
826//class : OpenGl_TransparentFilter
827//function : ShouldRender
828//purpose : Checks whether the element should be rendered or skipped.
829//=======================================================================
830Standard_Boolean OpenGl_LayerList::OpenGl_TransparentFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
831 const OpenGl_Element* theGlElement)
832{
833 if (!myFilter.IsNull()
834 && !myFilter->ShouldRender (theWorkspace, theGlElement))
835 {
836 return Standard_False;
837 }
838
839 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
840 if (aPArray == NULL
8e0a2b19 841 || !aPArray->IsFillDrawMode())
a1073ae2 842 {
843 return dynamic_cast<const OpenGl_AspectFace*> (theGlElement) != NULL;
844 }
845
a1073ae2 846 return OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 847 theWorkspace->HighlightStyle());
59f45b7c 848}