0030374: Visualization, TKOpenGl - activate texture unit Graphic3d_TextureUnit_1...
[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),
1b661a81 151 myModifStateOfRaytraceable (0)
59f45b7c 152{
a1954302 153 // insert default priority layers
f5b72419 154 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
af65fb19 155 myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD, myLayers.Upper());
156
f5b72419 157 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 158 myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
59f45b7c 159
f5b72419 160 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 161 myLayerIds.Bind (Graphic3d_ZLayerId_Top, myLayers.Upper());
59f45b7c 162
f5b72419 163 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 164 myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
59f45b7c 165
f5b72419 166 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 167 myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD, myLayers.Upper());
bd6a8454 168
169 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 170
171 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 172}
173
174//=======================================================================
a1954302 175//function : ~OpenGl_LayerList
176//purpose : Destructor
59f45b7c 177//=======================================================================
178
a1954302 179OpenGl_LayerList::~OpenGl_LayerList()
59f45b7c 180{
59f45b7c 181}
182
f5b72419 183//=======================================================================
184//function : SetFrustumCullingBVHBuilder
185//purpose :
186//=======================================================================
187void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
188{
189 myBVHBuilder = theBuilder;
190 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
191 {
192 anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
193 }
194}
195
59f45b7c 196//=======================================================================
197//function : AddLayer
198//purpose :
199//=======================================================================
200
a1954302 201void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 202{
a1954302 203 if (myLayerIds.IsBound (theLayerId))
204 {
59f45b7c 205 return;
a1954302 206 }
59f45b7c 207
208 // add the new layer
f5b72419 209 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
59f45b7c 210 myLayerIds.Bind (theLayerId, myLayers.Length());
a1073ae2 211
212 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 213}
214
c5751993 215//=======================================================================
216//function : Layer
217//purpose :
218//=======================================================================
a1954302 219OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
c5751993 220{
f5b72419 221 return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
c5751993 222}
223
224//=======================================================================
225//function : Layer
226//purpose :
227//=======================================================================
a1954302 228const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
c5751993 229{
f5b72419 230 return *myLayers.Value (myLayerIds.Find (theLayerId));
c5751993 231}
232
59f45b7c 233//=======================================================================
234//function : RemoveLayer
235//purpose :
236//=======================================================================
237
a1954302 238void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 239{
a1954302 240 if (!myLayerIds.IsBound (theLayerId)
241 || theLayerId <= 0)
242 {
59f45b7c 243 return;
a1954302 244 }
59f45b7c 245
a1954302 246 const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
59f45b7c 247
248 // move all displayed structures to first layer
f5b72419 249 {
250 const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
251 myLayers.ChangeFirst()->Append (aLayerToMove);
252 }
59f45b7c 253
254 // remove layer
255 myLayers.Remove (aRemovePos);
256 myLayerIds.UnBind (theLayerId);
257
258 // updated sequence indexes in map
bd6a8454 259 for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
59f45b7c 260 {
bd6a8454 261 Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
59f45b7c 262 if (aSeqIdx > aRemovePos)
263 aSeqIdx--;
264 }
bd6a8454 265
266 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 267
268 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 269}
270
271//=======================================================================
272//function : AddStructure
273//purpose :
274//=======================================================================
275
a1954302 276void OpenGl_LayerList::AddStructure (const OpenGl_Structure* theStruct,
277 const Graphic3d_ZLayerId theLayerId,
278 const Standard_Integer thePriority,
279 Standard_Boolean isForChangePriority)
59f45b7c 280{
281 // add structure to associated layer,
282 // if layer doesn't exists, display structure in default layer
a1954302 283 Standard_Integer aSeqPos = myLayers.Lower();
284 myLayerIds.Find (theLayerId, aSeqPos);
59f45b7c 285
f5b72419 286 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 287 aLayer.Add (theStruct, thePriority, isForChangePriority);
288 ++myNbStructures;
7c3ef2f7 289 if (aLayer.IsImmediate())
a1954302 290 {
291 ++myImmediateNbStructures;
292 }
e276548b 293
294 // Note: In ray-tracing mode we don't modify modification
295 // state here. It is redundant, because the possible changes
296 // will be handled in the loop for structures
59f45b7c 297}
298
299//=======================================================================
300//function : RemoveStructure
a1954302 301//purpose :
59f45b7c 302//=======================================================================
303
c357e426 304void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
59f45b7c 305{
c357e426 306 const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
a1954302 307
308 Standard_Integer aSeqPos = myLayers.Lower();
309 myLayerIds.Find (aLayerId, aSeqPos);
310
f5b72419 311 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 312 Standard_Integer aPriority = -1;
59f45b7c 313
314 // remove structure from associated list
315 // if the structure is not found there,
316 // scan through layers and remove it
c357e426 317 if (aLayer.Remove (theStructure, aPriority))
59f45b7c 318 {
a1954302 319 --myNbStructures;
7c3ef2f7 320 if (aLayer.IsImmediate())
a1954302 321 {
322 --myImmediateNbStructures;
323 }
e276548b 324
bd6a8454 325 if (aLayerId == Graphic3d_ZLayerId_Default
326 && theStructure->IsRaytracable())
e276548b 327 {
bd6a8454 328 ++myModifStateOfRaytraceable;
e276548b 329 }
e276548b 330
59f45b7c 331 return;
332 }
a1954302 333
59f45b7c 334 // scan through layers and remove it
f88457e6 335 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 336 {
f5b72419 337 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
f88457e6 338 if (aSeqPos == anIts.Index())
59f45b7c 339 {
a1954302 340 continue;
341 }
e276548b 342
c357e426 343 if (aLayerEx.Remove (theStructure, aPriority))
a1954302 344 {
345 --myNbStructures;
7c3ef2f7 346 if (aLayerEx.IsImmediate())
e276548b 347 {
a1954302 348 --myImmediateNbStructures;
e276548b 349 }
e276548b 350
f88457e6 351 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 352 && theStructure->IsRaytracable())
a1954302 353 {
bd6a8454 354 ++myModifStateOfRaytraceable;
a1954302 355 }
59f45b7c 356 return;
357 }
358 }
359}
360
b7cd4ba7 361//=======================================================================
362//function : InvalidateBVHData
363//purpose :
364//=======================================================================
a1954302 365void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
b7cd4ba7 366{
a1954302 367 Standard_Integer aSeqPos = myLayers.Lower();
368 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 369 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 370 aLayer.InvalidateBVHData();
b7cd4ba7 371}
372
59f45b7c 373//=======================================================================
374//function : ChangeLayer
375//purpose :
376//=======================================================================
377
a1954302 378void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure* theStructure,
379 const Graphic3d_ZLayerId theOldLayerId,
380 const Graphic3d_ZLayerId theNewLayerId)
59f45b7c 381{
a1954302 382 Standard_Integer aSeqPos = myLayers.Lower();
383 myLayerIds.Find (theOldLayerId, aSeqPos);
f5b72419 384 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 385 Standard_Integer aPriority = -1;
59f45b7c 386
387 // take priority and remove structure from list found by <theOldLayerId>
388 // if the structure is not found there, scan through all other layers
3fe9ce0e 389 if (aLayer.Remove (theStructure, aPriority, Standard_False))
59f45b7c 390 {
bd6a8454 391 if (theOldLayerId == Graphic3d_ZLayerId_Default
392 && theStructure->IsRaytracable())
393 {
394 ++myModifStateOfRaytraceable;
395 }
396
a1954302 397 --myNbStructures;
7c3ef2f7 398 if (aLayer.IsImmediate())
a1954302 399 {
400 --myImmediateNbStructures;
401 }
402
a0c20252 403 // isForChangePriority should be Standard_False below, because we want
404 // the BVH tree in the target layer to be updated with theStructure
405 AddStructure (theStructure, theNewLayerId, aPriority);
a1954302 406 return;
59f45b7c 407 }
a1954302 408
409 // scan through layers and remove it
f88457e6 410 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 411 {
f88457e6 412 if (aSeqPos == anIts.Index())
59f45b7c 413 {
a1954302 414 continue;
415 }
59f45b7c 416
a1954302 417 // try to remove structure and get priority value from this layer
f5b72419 418 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 419 if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
420 {
f88457e6 421 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 422 && theStructure->IsRaytracable())
423 {
424 ++myModifStateOfRaytraceable;
425 }
426
a1954302 427 --myNbStructures;
7c3ef2f7 428 if (aLayerEx.IsImmediate())
b7cd4ba7 429 {
a1954302 430 --myImmediateNbStructures;
b7cd4ba7 431 }
a1954302 432
433 // isForChangePriority should be Standard_False below, because we want
434 // the BVH tree in the target layer to be updated with theStructure
435 AddStructure (theStructure, theNewLayerId, aPriority);
436 return;
b7cd4ba7 437 }
438 }
439}
440
441//=======================================================================
442//function : ChangePriority
443//purpose :
444//=======================================================================
a1954302 445void OpenGl_LayerList::ChangePriority (const OpenGl_Structure* theStructure,
446 const Graphic3d_ZLayerId theLayerId,
447 const Standard_Integer theNewPriority)
b7cd4ba7 448{
a1954302 449 Standard_Integer aSeqPos = myLayers.Lower();
450 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 451 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 452 Standard_Integer anOldPriority = -1;
b7cd4ba7 453
a1954302 454 if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
b7cd4ba7 455 {
a1954302 456 --myNbStructures;
7c3ef2f7 457 if (aLayer.IsImmediate())
a1954302 458 {
459 --myImmediateNbStructures;
460 }
461
b7cd4ba7 462 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
a1954302 463 return;
b7cd4ba7 464 }
a1954302 465
f88457e6 466 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
b7cd4ba7 467 {
f88457e6 468 if (aSeqPos == anIts.Index())
b7cd4ba7 469 {
a1954302 470 continue;
471 }
b7cd4ba7 472
f5b72419 473 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 474 if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
475 {
476 --myNbStructures;
7c3ef2f7 477 if (aLayerEx.IsImmediate())
59f45b7c 478 {
a1954302 479 --myImmediateNbStructures;
59f45b7c 480 }
a1954302 481
482 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
483 return;
59f45b7c 484 }
485 }
486}
487
488//=======================================================================
a1954302 489//function : SetLayerSettings
490//purpose :
59f45b7c 491//=======================================================================
a1954302 492void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId theLayerId,
493 const Graphic3d_ZLayerSettings& theSettings)
494{
495 OpenGl_Layer& aLayer = Layer (theLayerId);
7c3ef2f7 496 if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
a1954302 497 {
7c3ef2f7 498 if (theSettings.IsImmediate())
a1954302 499 {
500 myImmediateNbStructures += aLayer.NbStructures();
501 }
502 else
503 {
504 myImmediateNbStructures -= aLayer.NbStructures();
505 }
506 }
507 aLayer.SetLayerSettings (theSettings);
508}
59f45b7c 509
2b8832bb 510//=======================================================================
511//function : UpdateCulling
512//purpose :
513//=======================================================================
514void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
515 const Standard_Boolean theToDrawImmediate)
516{
5e30547b 517 const Handle(OpenGl_FrameStats)& aStats = theWorkspace->GetGlContext()->FrameStats();
518 OSD_Timer& aTimer = aStats->ActiveDataFrame().ChangeTimer (Graphic3d_FrameStatsTimer_CpuCulling);
519 aTimer.Start();
520
5dc0517d 521 const Standard_Integer aViewId = theWorkspace->View()->Identification();
2b8832bb 522 const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
523 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
524 {
525 OpenGl_Layer& aLayer = *anIts.ChangeValue();
526 if (aLayer.IsImmediate() != theToDrawImmediate)
527 {
528 continue;
529 }
530
5dc0517d 531 aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->IsCullingEnabled());
2b8832bb 532 }
5e30547b 533
534 aTimer.Stop();
535 aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
2b8832bb 536}
537
a1954302 538//=======================================================================
539//function : Render
540//purpose :
541//=======================================================================
542void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
91c60b57 543 const Standard_Boolean theToDrawImmediate,
a1073ae2 544 const OpenGl_LayerFilter theLayersToProcess,
545 OpenGl_FrameBuffer* theReadDrawFbo,
546 OpenGl_FrameBuffer* theOitAccumFbo) const
59f45b7c 547{
a1073ae2 548 // Remember global settings for glDepth function and write mask.
f88457e6 549 OpenGl_GlobalLayerSettings aPrevSettings;
c5751993 550
a1954302 551 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
f88457e6 552 aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc);
553 aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
554 OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
a1954302 555
a1073ae2 556 // Two render filters are used to support transparency draw. Opaque filter accepts
557 // only non-transparent OpenGl elements of a layer and counts number of skipped
558 // transparent ones. If the counter has positive value the layer is added into
559 // transparency post-processing stack. At the end of drawing or once the depth
560 // buffer is to be cleared the layers in the stack should be drawn using
561 // blending and depth mask settings and another transparency filter which accepts
562 // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
563 // was preallocated before going into this method and has enough space to keep
564 // maximum number of references to layers, therefore it will not increase memory
565 // fragmentation during regular rendering.
1b661a81 566 const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
567 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
a1073ae2 568
569 myTransparentToProcess.Clear();
570
571 OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
f88457e6 572 Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
573 const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
574 && aPrevSettings.DepthMask == GL_TRUE;
992ed6b3 575 const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
f88457e6 576 for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
59f45b7c 577 {
f88457e6 578 bool hasSkippedDepthLayers = false;
579 for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
91c60b57 580 {
f88457e6 581 if (aPassIter == 0)
582 {
583 aCtx->SetColorMask (false);
992ed6b3 584 aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
f88457e6 585 aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
586 aDefaultSettings.DepthMask = GL_TRUE;
587 }
588 else if (aPassIter == 1)
589 {
590 if (!hasSkippedDepthLayers)
591 {
592 continue;
593 }
594 aCtx->SetColorMask (true);
992ed6b3 595 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 596 aDefaultSettings = aPrevSettings;
597 }
598 else if (aPassIter == 2)
599 {
600 aCtx->SetColorMask (true);
992ed6b3 601 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 602 if (toPerformDepthPrepass)
603 {
604 aDefaultSettings.DepthFunc = GL_EQUAL;
605 aDefaultSettings.DepthMask = GL_FALSE;
606 }
607 }
91c60b57 608
f88457e6 609 OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
610 for (; aLayerIter.More(); aLayerIter.Next())
611 {
612 const OpenGl_Layer& aLayer = aLayerIter.Value();
613
614 // make sure to clear depth of previous layers even if layer has no structures
615 if (aLayer.LayerSettings().ToClearDepth())
616 {
617 aClearDepthLayer = aLayerIter.Index();
618 }
2b8832bb 619 if (aLayer.IsCulled())
f88457e6 620 {
621 continue;
622 }
623 else if (aClearDepthLayer > aClearDepthLayerPrev)
624 {
625 // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
626 // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
627 // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
628 if (aPassIter == 2)
629 {
630 aLayerIterStart = aLayerIter;
631 }
632 else
633 {
634 aClearDepthLayer = -1;
635 }
636 break;
637 }
638 else if (aPassIter == 0
639 && !aLayer.LayerSettings().ToRenderInDepthPrepass())
640 {
641 hasSkippedDepthLayers = true;
642 continue;
643 }
644 else if (aPassIter == 1
645 && aLayer.LayerSettings().ToRenderInDepthPrepass())
646 {
647 continue;
648 }
649
650 // Render opaque OpenGl elements of a layer and count the number of skipped.
651 // If a layer has skipped (e.g. transparent) elements it should be added into
652 // the transparency post-processing stack.
1b661a81 653 theWorkspace->ResetSkippedCounter();
f88457e6 654
655 aLayer.Render (theWorkspace, aDefaultSettings);
656
657 if (aPassIter != 0
1b661a81 658 && theWorkspace->NbSkippedTransparentElements() > 0)
f88457e6 659 {
660 myTransparentToProcess.Push (&aLayer);
661 }
662 }
663 if (aPassIter == 2
664 && !aLayerIter.More())
665 {
666 aLayerIterStart = aLayerIter;
667 }
a1954302 668 }
f88457e6 669
670 if (!myTransparentToProcess.IsEmpty())
59f45b7c 671 {
f88457e6 672 renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
59f45b7c 673 }
f88457e6 674 if (aClearDepthLayer > aClearDepthLayerPrev)
a1954302 675 {
f88457e6 676 aClearDepthLayerPrev = aClearDepthLayer;
b3eab8ef 677 glDepthMask (GL_TRUE);
678 glClear (GL_DEPTH_BUFFER_BIT);
a1954302 679 }
b3eab8ef 680 }
681
f88457e6 682 aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
683 aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
a1073ae2 684
685 theWorkspace->SetRenderFilter (aPrevFilter);
686}
687
688//=======================================================================
689//function : renderTransparent
690//purpose : Render transparent objects using blending operator.
691//=======================================================================
692void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theWorkspace,
693 OpenGl_LayerStack::iterator& theLayerIter,
694 const OpenGl_GlobalLayerSettings& theGlobalSettings,
695 OpenGl_FrameBuffer* theReadDrawFbo,
696 OpenGl_FrameBuffer* theOitAccumFbo) const
697{
698 // Blended order-independent transparency algorithm require several preconditions
699 // to be enabled. It should be requested by user, at least two outputs from
700 // fragment shader should be supported by GPU, so is the given framebuffer
701 // should contain two additional color buffers to handle accumulated color channels,
702 // blended alpha channel and weight factors - these accumulation buffers are required
703 // to implement commuting blend operator (at least OpenGl 2.0 should be available).
704 const bool isEnabledOit = theOitAccumFbo != NULL
705 && theOitAccumFbo->NbColorBuffers() >= 2
706 && theOitAccumFbo->ColorTexture (0)->IsValid()
707 && theOitAccumFbo->ColorTexture (1)->IsValid();
708
709 // Check if current iterator has already reached the end of the stack.
710 // This should happen if no additional layers has been added to
711 // the processing stack after last transparency pass.
712 if (theLayerIter == myTransparentToProcess.Back())
713 {
714 return;
715 }
716
717 const Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
718 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
719 OpenGl_View* aView = theWorkspace->View();
720 const float aDepthFactor = aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
721
1b661a81 722 const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
723 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
a1073ae2 724
725 aCtx->core11fwd->glEnable (GL_BLEND);
726
727 if (isEnabledOit)
728 {
729 aManager->SetOitState (true, aDepthFactor);
730
731 theOitAccumFbo->BindBuffer (aCtx);
732
733 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
734 aCtx->SetDrawBuffers (2, aDrawBuffers);
735 aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
736 aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
737 aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
738 }
739 else
740 {
741 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
742 }
743
744 // During blended order-independent transparency pass the depth test
745 // should be enabled to discard fragments covered by opaque geometry
746 // and depth writing should be disabled, because transparent fragments
747 // overal each other with non unitary coverage factor.
748 OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
749 aGlobalSettings.DepthMask = GL_FALSE;
750 aCtx->core11fwd->glDepthMask (GL_FALSE);
751
752 for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
753 {
754 (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
755 }
756
757 // Revert state of rendering.
758 if (isEnabledOit)
759 {
760 aManager->SetOitState (false, aDepthFactor);
761 theOitAccumFbo->UnbindBuffer (aCtx);
762 if (theReadDrawFbo)
763 {
764 theReadDrawFbo->BindBuffer (aCtx);
765 }
766
767 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
768 aCtx->SetDrawBuffers (1, aDrawBuffers);
769 }
770
1b661a81 771 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
a1073ae2 772 if (isEnabledOit)
773 {
774 const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
775 OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
776 if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
777 {
778 aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
779 aCtx->core11fwd->glDepthMask (GL_FALSE);
780
781 // Bind full screen quad buffer and framebuffer resources.
782 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
783
cc8cbabe 784 const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
a1073ae2 785
cc8cbabe 786 theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
787 theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 788
789 // Draw full screen quad with special shader to compose the buffers.
790 aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
791 aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
792
793 // Unbind OpenGL texture objects and shader program.
794 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
cc8cbabe 795 theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
ce1c28b8 796 theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
a1073ae2 797 aCtx->BindProgram (NULL);
798
799 if (!aTextureBack.IsNull())
800 {
cc8cbabe 801 aCtx->BindTextures (aTextureBack);
a1073ae2 802 }
803 }
804 else
805 {
806 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
807 "Initialization of OIT compositing pass has failed.\n"
808 " Blended order-independent transparency will not be available.\n");
809 if (aView != NULL)
810 {
811 Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
812 aOITFlag = Standard_True;
813 }
814 }
815 }
816
817 aCtx->core11fwd->glDisable (GL_BLEND);
818 aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
819 aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
820 aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
821}