0029292: Coding Rules - remove Graphic3d_Vector duplicating gp_XYZ
[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
29//=======================================================================
30//function : OpenGl_LayerList
31//purpose : Constructor
32//=======================================================================
33
34OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
f5b72419 35: myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
36 myDefaultLayerIndex (0),
bd6a8454 37 myNbPriorities (theNbPriorities),
a1954302 38 myNbStructures (0),
bd6a8454 39 myImmediateNbStructures (0),
a1073ae2 40 myModifStateOfRaytraceable (0),
41 myRenderOpaqueFilter (new OpenGl_OpaqueFilter()),
42 myRenderTranspFilter (new OpenGl_TransparentFilter())
59f45b7c 43{
a1954302 44 // insert default priority layers
f5b72419 45 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
af65fb19 46 myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD, myLayers.Upper());
47
f5b72419 48 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 49 myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
59f45b7c 50
f5b72419 51 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 52 myLayerIds.Bind (Graphic3d_ZLayerId_Top, myLayers.Upper());
59f45b7c 53
f5b72419 54 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 55 myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
59f45b7c 56
f5b72419 57 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 58 myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD, myLayers.Upper());
bd6a8454 59
60 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 61
62 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 63}
64
65//=======================================================================
a1954302 66//function : ~OpenGl_LayerList
67//purpose : Destructor
59f45b7c 68//=======================================================================
69
a1954302 70OpenGl_LayerList::~OpenGl_LayerList()
59f45b7c 71{
59f45b7c 72}
73
74//=======================================================================
f5b72419 75//function : SetFrustumCullingBVHBuilder
76//purpose :
77//=======================================================================
78void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
79{
80 myBVHBuilder = theBuilder;
81 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
82 {
83 anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
84 }
85}
86
87//=======================================================================
59f45b7c 88//function : AddLayer
89//purpose :
90//=======================================================================
91
a1954302 92void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 93{
a1954302 94 if (myLayerIds.IsBound (theLayerId))
95 {
59f45b7c 96 return;
a1954302 97 }
59f45b7c 98
99 // add the new layer
f5b72419 100 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
59f45b7c 101 myLayerIds.Bind (theLayerId, myLayers.Length());
a1073ae2 102
103 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 104}
105
106//=======================================================================
c5751993 107//function : Layer
108//purpose :
109//=======================================================================
a1954302 110OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
c5751993 111{
f5b72419 112 return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
c5751993 113}
114
115//=======================================================================
116//function : Layer
117//purpose :
118//=======================================================================
a1954302 119const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
c5751993 120{
f5b72419 121 return *myLayers.Value (myLayerIds.Find (theLayerId));
c5751993 122}
123
124//=======================================================================
59f45b7c 125//function : RemoveLayer
126//purpose :
127//=======================================================================
128
a1954302 129void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 130{
a1954302 131 if (!myLayerIds.IsBound (theLayerId)
132 || theLayerId <= 0)
133 {
59f45b7c 134 return;
a1954302 135 }
59f45b7c 136
a1954302 137 const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
59f45b7c 138
139 // move all displayed structures to first layer
f5b72419 140 {
141 const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
142 myLayers.ChangeFirst()->Append (aLayerToMove);
143 }
59f45b7c 144
145 // remove layer
146 myLayers.Remove (aRemovePos);
147 myLayerIds.UnBind (theLayerId);
148
149 // updated sequence indexes in map
bd6a8454 150 for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
59f45b7c 151 {
bd6a8454 152 Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
59f45b7c 153 if (aSeqIdx > aRemovePos)
154 aSeqIdx--;
155 }
bd6a8454 156
157 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 158
159 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 160}
161
162//=======================================================================
163//function : AddStructure
164//purpose :
165//=======================================================================
166
a1954302 167void OpenGl_LayerList::AddStructure (const OpenGl_Structure* theStruct,
168 const Graphic3d_ZLayerId theLayerId,
169 const Standard_Integer thePriority,
170 Standard_Boolean isForChangePriority)
59f45b7c 171{
172 // add structure to associated layer,
173 // if layer doesn't exists, display structure in default layer
a1954302 174 Standard_Integer aSeqPos = myLayers.Lower();
175 myLayerIds.Find (theLayerId, aSeqPos);
59f45b7c 176
f5b72419 177 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 178 aLayer.Add (theStruct, thePriority, isForChangePriority);
179 ++myNbStructures;
7c3ef2f7 180 if (aLayer.IsImmediate())
a1954302 181 {
182 ++myImmediateNbStructures;
183 }
e276548b 184
185 // Note: In ray-tracing mode we don't modify modification
186 // state here. It is redundant, because the possible changes
187 // will be handled in the loop for structures
59f45b7c 188}
189
190//=======================================================================
191//function : RemoveStructure
a1954302 192//purpose :
59f45b7c 193//=======================================================================
194
c357e426 195void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
59f45b7c 196{
c357e426 197 const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
a1954302 198
199 Standard_Integer aSeqPos = myLayers.Lower();
200 myLayerIds.Find (aLayerId, aSeqPos);
201
f5b72419 202 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 203 Standard_Integer aPriority = -1;
59f45b7c 204
205 // remove structure from associated list
206 // if the structure is not found there,
207 // scan through layers and remove it
c357e426 208 if (aLayer.Remove (theStructure, aPriority))
59f45b7c 209 {
a1954302 210 --myNbStructures;
7c3ef2f7 211 if (aLayer.IsImmediate())
a1954302 212 {
213 --myImmediateNbStructures;
214 }
e276548b 215
bd6a8454 216 if (aLayerId == Graphic3d_ZLayerId_Default
217 && theStructure->IsRaytracable())
e276548b 218 {
bd6a8454 219 ++myModifStateOfRaytraceable;
e276548b 220 }
e276548b 221
59f45b7c 222 return;
223 }
a1954302 224
59f45b7c 225 // scan through layers and remove it
226 Standard_Integer aSeqId = 1;
a1954302 227 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
59f45b7c 228 {
f5b72419 229 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
59f45b7c 230 if (aSeqPos == aSeqId)
59f45b7c 231 {
a1954302 232 continue;
233 }
e276548b 234
c357e426 235 if (aLayerEx.Remove (theStructure, aPriority))
a1954302 236 {
237 --myNbStructures;
7c3ef2f7 238 if (aLayerEx.IsImmediate())
e276548b 239 {
a1954302 240 --myImmediateNbStructures;
e276548b 241 }
e276548b 242
bd6a8454 243 if (aSeqId == myDefaultLayerIndex
244 && theStructure->IsRaytracable())
a1954302 245 {
bd6a8454 246 ++myModifStateOfRaytraceable;
a1954302 247 }
59f45b7c 248 return;
249 }
250 }
251}
252
253//=======================================================================
b7cd4ba7 254//function : InvalidateBVHData
255//purpose :
256//=======================================================================
a1954302 257void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
b7cd4ba7 258{
a1954302 259 Standard_Integer aSeqPos = myLayers.Lower();
260 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 261 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 262 aLayer.InvalidateBVHData();
b7cd4ba7 263}
264
265//=======================================================================
59f45b7c 266//function : ChangeLayer
267//purpose :
268//=======================================================================
269
a1954302 270void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure* theStructure,
271 const Graphic3d_ZLayerId theOldLayerId,
272 const Graphic3d_ZLayerId theNewLayerId)
59f45b7c 273{
a1954302 274 Standard_Integer aSeqPos = myLayers.Lower();
275 myLayerIds.Find (theOldLayerId, aSeqPos);
f5b72419 276 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 277 Standard_Integer aPriority = -1;
59f45b7c 278
279 // take priority and remove structure from list found by <theOldLayerId>
280 // if the structure is not found there, scan through all other layers
3fe9ce0e 281 if (aLayer.Remove (theStructure, aPriority, Standard_False))
59f45b7c 282 {
bd6a8454 283 if (theOldLayerId == Graphic3d_ZLayerId_Default
284 && theStructure->IsRaytracable())
285 {
286 ++myModifStateOfRaytraceable;
287 }
288
a1954302 289 --myNbStructures;
7c3ef2f7 290 if (aLayer.IsImmediate())
a1954302 291 {
292 --myImmediateNbStructures;
293 }
294
a0c20252 295 // isForChangePriority should be Standard_False below, because we want
296 // the BVH tree in the target layer to be updated with theStructure
297 AddStructure (theStructure, theNewLayerId, aPriority);
a1954302 298 return;
59f45b7c 299 }
a1954302 300
301 // scan through layers and remove it
302 Standard_Integer aSeqId = 1;
303 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
59f45b7c 304 {
a1954302 305 if (aSeqPos == aSeqId)
59f45b7c 306 {
a1954302 307 continue;
308 }
59f45b7c 309
a1954302 310 // try to remove structure and get priority value from this layer
f5b72419 311 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 312 if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
313 {
bd6a8454 314 if (aSeqId == myDefaultLayerIndex
315 && theStructure->IsRaytracable())
316 {
317 ++myModifStateOfRaytraceable;
318 }
319
a1954302 320 --myNbStructures;
7c3ef2f7 321 if (aLayerEx.IsImmediate())
b7cd4ba7 322 {
a1954302 323 --myImmediateNbStructures;
b7cd4ba7 324 }
a1954302 325
326 // isForChangePriority should be Standard_False below, because we want
327 // the BVH tree in the target layer to be updated with theStructure
328 AddStructure (theStructure, theNewLayerId, aPriority);
329 return;
b7cd4ba7 330 }
331 }
332}
333
334//=======================================================================
335//function : ChangePriority
336//purpose :
337//=======================================================================
a1954302 338void OpenGl_LayerList::ChangePriority (const OpenGl_Structure* theStructure,
339 const Graphic3d_ZLayerId theLayerId,
340 const Standard_Integer theNewPriority)
b7cd4ba7 341{
a1954302 342 Standard_Integer aSeqPos = myLayers.Lower();
343 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 344 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 345 Standard_Integer anOldPriority = -1;
b7cd4ba7 346
a1954302 347 if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
b7cd4ba7 348 {
a1954302 349 --myNbStructures;
7c3ef2f7 350 if (aLayer.IsImmediate())
a1954302 351 {
352 --myImmediateNbStructures;
353 }
354
b7cd4ba7 355 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
a1954302 356 return;
b7cd4ba7 357 }
a1954302 358
359 Standard_Integer aSeqId = 1;
360 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
b7cd4ba7 361 {
a1954302 362 if (aSeqPos == aSeqId)
b7cd4ba7 363 {
a1954302 364 continue;
365 }
b7cd4ba7 366
f5b72419 367 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 368 if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
369 {
370 --myNbStructures;
7c3ef2f7 371 if (aLayerEx.IsImmediate())
59f45b7c 372 {
a1954302 373 --myImmediateNbStructures;
59f45b7c 374 }
a1954302 375
376 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
377 return;
59f45b7c 378 }
379 }
380}
381
382//=======================================================================
a1954302 383//function : SetLayerSettings
384//purpose :
59f45b7c 385//=======================================================================
a1954302 386void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId theLayerId,
387 const Graphic3d_ZLayerSettings& theSettings)
388{
389 OpenGl_Layer& aLayer = Layer (theLayerId);
7c3ef2f7 390 if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
a1954302 391 {
7c3ef2f7 392 if (theSettings.IsImmediate())
a1954302 393 {
394 myImmediateNbStructures += aLayer.NbStructures();
395 }
396 else
397 {
398 myImmediateNbStructures -= aLayer.NbStructures();
399 }
400 }
401 aLayer.SetLayerSettings (theSettings);
402}
59f45b7c 403
a1954302 404//=======================================================================
405//function : Render
406//purpose :
407//=======================================================================
408void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
91c60b57 409 const Standard_Boolean theToDrawImmediate,
a1073ae2 410 const OpenGl_LayerFilter theLayersToProcess,
411 OpenGl_FrameBuffer* theReadDrawFbo,
412 OpenGl_FrameBuffer* theOitAccumFbo) const
59f45b7c 413{
a1073ae2 414 // Remember global settings for glDepth function and write mask.
550f3b8b 415 OpenGl_GlobalLayerSettings aDefaultSettings;
c5751993 416
a1954302 417 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
418 aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aDefaultSettings.DepthFunc);
419 aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aDefaultSettings.DepthMask);
420
a1073ae2 421 // Two render filters are used to support transparency draw. Opaque filter accepts
422 // only non-transparent OpenGl elements of a layer and counts number of skipped
423 // transparent ones. If the counter has positive value the layer is added into
424 // transparency post-processing stack. At the end of drawing or once the depth
425 // buffer is to be cleared the layers in the stack should be drawn using
426 // blending and depth mask settings and another transparency filter which accepts
427 // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
428 // was preallocated before going into this method and has enough space to keep
429 // maximum number of references to layers, therefore it will not increase memory
430 // fragmentation during regular rendering.
431 const Handle(OpenGl_RenderFilter) aPrevFilter = theWorkspace->GetRenderFilter();
432 myRenderOpaqueFilter->SetPreviousFilter (aPrevFilter);
433 myRenderTranspFilter->SetPreviousFilter (aPrevFilter);
434 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
435
436 myTransparentToProcess.Clear();
437
438 OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
bd6a8454 439 Standard_Integer aSeqId = myLayers.Lower();
b3eab8ef 440 bool toClearDepth = false;
a1073ae2 441 for (OpenGl_SequenceOfLayers::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next(), ++aSeqId)
59f45b7c 442 {
91c60b57 443 if (theLayersToProcess == OpenGl_LF_Bottom)
444 {
bd6a8454 445 if (aSeqId >= myDefaultLayerIndex) continue;
91c60b57 446 }
447 else if (theLayersToProcess == OpenGl_LF_Upper)
448 {
bd6a8454 449 if (aSeqId <= myDefaultLayerIndex) continue;
91c60b57 450 }
451 else if (theLayersToProcess == OpenGl_LF_Default)
452 {
bd6a8454 453 if (aSeqId != myDefaultLayerIndex) continue;
91c60b57 454 }
455
f5b72419 456 const OpenGl_Layer& aLayer = *aLayerIter.Value();
b3eab8ef 457 if (aLayer.IsImmediate() != theToDrawImmediate)
a1954302 458 {
459 continue;
460 }
b3eab8ef 461 else if (aLayer.NbStructures() < 1)
59f45b7c 462 {
a1073ae2 463 // Make sure to clear depth of previous layers even if layer has no structures.
b3eab8ef 464 toClearDepth = toClearDepth || aLayer.LayerSettings().ToClearDepth();
465 continue;
59f45b7c 466 }
b3eab8ef 467
a1073ae2 468 // At this point the depth buffer may be set to clear by
469 // previous configuration of layers or configuration of the
470 // current layer. Additional rendering pass to handle transparent
471 // elements of recently drawn layers require use of current depth
472 // buffer so we put remaining layers for processing as one bunch before
473 // erasing the depth buffer.
b3eab8ef 474 if (toClearDepth
475 || aLayer.LayerSettings().ToClearDepth())
a1954302 476 {
a1073ae2 477 if (!myTransparentToProcess.IsEmpty())
478 {
479 renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
480 }
481
b3eab8ef 482 toClearDepth = false;
483 glDepthMask (GL_TRUE);
484 glClear (GL_DEPTH_BUFFER_BIT);
a1954302 485 }
486
a1073ae2 487 // Render opaque OpenGl elements of a layer and count the number of skipped.
488 // If a layer has skipped (e.g. transparent) elements it should be added into
489 // the transparency post-processing stack.
490 myRenderOpaqueFilter->SetSkippedCounter (0);
491
a1954302 492 aLayer.Render (theWorkspace, aDefaultSettings);
a1073ae2 493
494 if (myRenderOpaqueFilter->NbSkipped() > 0)
495 {
496 myTransparentToProcess.Push (&aLayer);
497 }
498 }
499
500 // Before finishing process the remaining collected layers with transparency.
501 if (!myTransparentToProcess.IsEmpty())
502 {
503 renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
59f45b7c 504 }
550f3b8b 505
b3eab8ef 506 if (toClearDepth)
507 {
508 glDepthMask (GL_TRUE);
509 glClear (GL_DEPTH_BUFFER_BIT);
510 }
511
a1954302 512 aCtx->core11fwd->glDepthMask (aDefaultSettings.DepthMask);
513 aCtx->core11fwd->glDepthFunc (aDefaultSettings.DepthFunc);
a1073ae2 514
515 theWorkspace->SetRenderFilter (aPrevFilter);
516}
517
518//=======================================================================
519//function : renderTransparent
520//purpose : Render transparent objects using blending operator.
521//=======================================================================
522void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theWorkspace,
523 OpenGl_LayerStack::iterator& theLayerIter,
524 const OpenGl_GlobalLayerSettings& theGlobalSettings,
525 OpenGl_FrameBuffer* theReadDrawFbo,
526 OpenGl_FrameBuffer* theOitAccumFbo) const
527{
528 // Blended order-independent transparency algorithm require several preconditions
529 // to be enabled. It should be requested by user, at least two outputs from
530 // fragment shader should be supported by GPU, so is the given framebuffer
531 // should contain two additional color buffers to handle accumulated color channels,
532 // blended alpha channel and weight factors - these accumulation buffers are required
533 // to implement commuting blend operator (at least OpenGl 2.0 should be available).
534 const bool isEnabledOit = theOitAccumFbo != NULL
535 && theOitAccumFbo->NbColorBuffers() >= 2
536 && theOitAccumFbo->ColorTexture (0)->IsValid()
537 && theOitAccumFbo->ColorTexture (1)->IsValid();
538
539 // Check if current iterator has already reached the end of the stack.
540 // This should happen if no additional layers has been added to
541 // the processing stack after last transparency pass.
542 if (theLayerIter == myTransparentToProcess.Back())
543 {
544 return;
545 }
546
547 const Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
548 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
549 OpenGl_View* aView = theWorkspace->View();
550 const float aDepthFactor = aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
551
552 theWorkspace->SetRenderFilter (myRenderTranspFilter);
553
554 aCtx->core11fwd->glEnable (GL_BLEND);
555
556 if (isEnabledOit)
557 {
558 aManager->SetOitState (true, aDepthFactor);
559
560 theOitAccumFbo->BindBuffer (aCtx);
561
562 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
563 aCtx->SetDrawBuffers (2, aDrawBuffers);
564 aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
565 aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
566 aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
567 }
568 else
569 {
570 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
571 }
572
573 // During blended order-independent transparency pass the depth test
574 // should be enabled to discard fragments covered by opaque geometry
575 // and depth writing should be disabled, because transparent fragments
576 // overal each other with non unitary coverage factor.
577 OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
578 aGlobalSettings.DepthMask = GL_FALSE;
579 aCtx->core11fwd->glDepthMask (GL_FALSE);
580
581 for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
582 {
583 (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
584 }
585
586 // Revert state of rendering.
587 if (isEnabledOit)
588 {
589 aManager->SetOitState (false, aDepthFactor);
590 theOitAccumFbo->UnbindBuffer (aCtx);
591 if (theReadDrawFbo)
592 {
593 theReadDrawFbo->BindBuffer (aCtx);
594 }
595
596 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
597 aCtx->SetDrawBuffers (1, aDrawBuffers);
598 }
599
600 theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
601 if (isEnabledOit)
602 {
603 const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
604 OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
605 if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
606 {
607 aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
608 aCtx->core11fwd->glDepthMask (GL_FALSE);
609
610 // Bind full screen quad buffer and framebuffer resources.
611 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
612
cc8cbabe 613 const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
a1073ae2 614
cc8cbabe 615 theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
616 theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 617
618 // Draw full screen quad with special shader to compose the buffers.
619 aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
620 aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
621
622 // Unbind OpenGL texture objects and shader program.
623 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
cc8cbabe 624 theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
625 theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 626 aCtx->BindProgram (NULL);
627
628 if (!aTextureBack.IsNull())
629 {
cc8cbabe 630 aCtx->BindTextures (aTextureBack);
a1073ae2 631 }
632 }
633 else
634 {
635 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
636 "Initialization of OIT compositing pass has failed.\n"
637 " Blended order-independent transparency will not be available.\n");
638 if (aView != NULL)
639 {
640 Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
641 aOITFlag = Standard_True;
642 }
643 }
644 }
645
646 aCtx->core11fwd->glDisable (GL_BLEND);
647 aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
648 aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
649 aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
650}
651
652//=======================================================================
653//class : OpenGl_OpaqueFilter
654//function : ShouldRender
655//purpose : Checks whether the element should be rendered or skipped.
656//=======================================================================
657Standard_Boolean OpenGl_LayerList::OpenGl_OpaqueFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
658 const OpenGl_Element* theGlElement)
659{
660 if (!myFilter.IsNull()
661 && !myFilter->ShouldRender (theWorkspace, theGlElement))
662 {
663 return Standard_False;
664 }
665
666 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
667 if (aPArray == NULL
8e0a2b19 668 || !aPArray->IsFillDrawMode())
a1073ae2 669 {
670 return Standard_True;
671 }
672
a1073ae2 673 if (OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 674 theWorkspace->HighlightStyle()))
a1073ae2 675 {
676 ++mySkippedCounter;
677 return Standard_False;
678 }
679
680 return Standard_True;
681}
682
683//=======================================================================
684//class : OpenGl_TransparentFilter
685//function : ShouldRender
686//purpose : Checks whether the element should be rendered or skipped.
687//=======================================================================
688Standard_Boolean OpenGl_LayerList::OpenGl_TransparentFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
689 const OpenGl_Element* theGlElement)
690{
691 if (!myFilter.IsNull()
692 && !myFilter->ShouldRender (theWorkspace, theGlElement))
693 {
694 return Standard_False;
695 }
696
697 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
698 if (aPArray == NULL
8e0a2b19 699 || !aPArray->IsFillDrawMode())
a1073ae2 700 {
701 return dynamic_cast<const OpenGl_AspectFace*> (theGlElement) != NULL;
702 }
703
a1073ae2 704 return OpenGl_Context::CheckIsTransparent (theWorkspace->AspectFace(),
a71a71de 705 theWorkspace->HighlightStyle());
59f45b7c 706}