0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[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
d325cb7f 140struct OpenGl_GlobalLayerSettings
141{
142 GLint DepthFunc;
143 GLboolean DepthMask;
144};
145
59f45b7c 146//=======================================================================
147//function : OpenGl_LayerList
148//purpose : Constructor
149//=======================================================================
150
151OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
f5b72419 152: myBVHBuilder (new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)),
153 myDefaultLayerIndex (0),
bd6a8454 154 myNbPriorities (theNbPriorities),
a1954302 155 myNbStructures (0),
bd6a8454 156 myImmediateNbStructures (0),
1b661a81 157 myModifStateOfRaytraceable (0)
59f45b7c 158{
a1954302 159 // insert default priority layers
f5b72419 160 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
af65fb19 161 myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD, myLayers.Upper());
162
f5b72419 163 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 164 myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
59f45b7c 165
f5b72419 166 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 167 myLayerIds.Bind (Graphic3d_ZLayerId_Top, myLayers.Upper());
59f45b7c 168
f5b72419 169 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 170 myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
59f45b7c 171
f5b72419 172 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
a1954302 173 myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD, myLayers.Upper());
bd6a8454 174
175 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 176
177 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 178}
179
180//=======================================================================
a1954302 181//function : ~OpenGl_LayerList
182//purpose : Destructor
59f45b7c 183//=======================================================================
184
a1954302 185OpenGl_LayerList::~OpenGl_LayerList()
59f45b7c 186{
59f45b7c 187}
188
189//=======================================================================
f5b72419 190//function : SetFrustumCullingBVHBuilder
191//purpose :
192//=======================================================================
193void OpenGl_LayerList::SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
194{
195 myBVHBuilder = theBuilder;
196 for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next())
197 {
198 anIts.ChangeValue()->SetFrustumCullingBVHBuilder (theBuilder);
199 }
200}
201
202//=======================================================================
59f45b7c 203//function : AddLayer
204//purpose :
205//=======================================================================
206
a1954302 207void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 208{
a1954302 209 if (myLayerIds.IsBound (theLayerId))
210 {
59f45b7c 211 return;
a1954302 212 }
59f45b7c 213
214 // add the new layer
f5b72419 215 myLayers.Append (new OpenGl_Layer (myNbPriorities, myBVHBuilder));
59f45b7c 216 myLayerIds.Bind (theLayerId, myLayers.Length());
a1073ae2 217
218 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 219}
220
221//=======================================================================
c5751993 222//function : Layer
223//purpose :
224//=======================================================================
a1954302 225OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
c5751993 226{
f5b72419 227 return *myLayers.ChangeValue (myLayerIds.Find (theLayerId));
c5751993 228}
229
230//=======================================================================
231//function : Layer
232//purpose :
233//=======================================================================
a1954302 234const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
c5751993 235{
f5b72419 236 return *myLayers.Value (myLayerIds.Find (theLayerId));
c5751993 237}
238
239//=======================================================================
59f45b7c 240//function : RemoveLayer
241//purpose :
242//=======================================================================
243
a1954302 244void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
59f45b7c 245{
a1954302 246 if (!myLayerIds.IsBound (theLayerId)
247 || theLayerId <= 0)
248 {
59f45b7c 249 return;
a1954302 250 }
59f45b7c 251
a1954302 252 const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
59f45b7c 253
254 // move all displayed structures to first layer
f5b72419 255 {
256 const OpenGl_Layer& aLayerToMove = *myLayers.Value (aRemovePos);
257 myLayers.ChangeFirst()->Append (aLayerToMove);
258 }
59f45b7c 259
260 // remove layer
261 myLayers.Remove (aRemovePos);
262 myLayerIds.UnBind (theLayerId);
263
264 // updated sequence indexes in map
bd6a8454 265 for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
59f45b7c 266 {
bd6a8454 267 Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
59f45b7c 268 if (aSeqIdx > aRemovePos)
269 aSeqIdx--;
270 }
bd6a8454 271
272 myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
a1073ae2 273
274 myTransparentToProcess.Allocate (myLayers.Length());
59f45b7c 275}
276
277//=======================================================================
278//function : AddStructure
279//purpose :
280//=======================================================================
281
a1954302 282void OpenGl_LayerList::AddStructure (const OpenGl_Structure* theStruct,
283 const Graphic3d_ZLayerId theLayerId,
284 const Standard_Integer thePriority,
285 Standard_Boolean isForChangePriority)
59f45b7c 286{
287 // add structure to associated layer,
288 // if layer doesn't exists, display structure in default layer
a1954302 289 Standard_Integer aSeqPos = myLayers.Lower();
290 myLayerIds.Find (theLayerId, aSeqPos);
59f45b7c 291
f5b72419 292 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 293 aLayer.Add (theStruct, thePriority, isForChangePriority);
294 ++myNbStructures;
7c3ef2f7 295 if (aLayer.IsImmediate())
a1954302 296 {
297 ++myImmediateNbStructures;
298 }
e276548b 299
300 // Note: In ray-tracing mode we don't modify modification
301 // state here. It is redundant, because the possible changes
302 // will be handled in the loop for structures
59f45b7c 303}
304
305//=======================================================================
306//function : RemoveStructure
a1954302 307//purpose :
59f45b7c 308//=======================================================================
309
c357e426 310void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
59f45b7c 311{
c357e426 312 const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
a1954302 313
314 Standard_Integer aSeqPos = myLayers.Lower();
315 myLayerIds.Find (aLayerId, aSeqPos);
316
f5b72419 317 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 318 Standard_Integer aPriority = -1;
59f45b7c 319
320 // remove structure from associated list
321 // if the structure is not found there,
322 // scan through layers and remove it
c357e426 323 if (aLayer.Remove (theStructure, aPriority))
59f45b7c 324 {
a1954302 325 --myNbStructures;
7c3ef2f7 326 if (aLayer.IsImmediate())
a1954302 327 {
328 --myImmediateNbStructures;
329 }
e276548b 330
bd6a8454 331 if (aLayerId == Graphic3d_ZLayerId_Default
332 && theStructure->IsRaytracable())
e276548b 333 {
bd6a8454 334 ++myModifStateOfRaytraceable;
e276548b 335 }
e276548b 336
59f45b7c 337 return;
338 }
a1954302 339
59f45b7c 340 // scan through layers and remove it
f88457e6 341 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 342 {
f5b72419 343 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
f88457e6 344 if (aSeqPos == anIts.Index())
59f45b7c 345 {
a1954302 346 continue;
347 }
e276548b 348
c357e426 349 if (aLayerEx.Remove (theStructure, aPriority))
a1954302 350 {
351 --myNbStructures;
7c3ef2f7 352 if (aLayerEx.IsImmediate())
e276548b 353 {
a1954302 354 --myImmediateNbStructures;
e276548b 355 }
e276548b 356
f88457e6 357 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 358 && theStructure->IsRaytracable())
a1954302 359 {
bd6a8454 360 ++myModifStateOfRaytraceable;
a1954302 361 }
59f45b7c 362 return;
363 }
364 }
365}
366
367//=======================================================================
b7cd4ba7 368//function : InvalidateBVHData
369//purpose :
370//=======================================================================
a1954302 371void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
b7cd4ba7 372{
a1954302 373 Standard_Integer aSeqPos = myLayers.Lower();
374 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 375 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 376 aLayer.InvalidateBVHData();
b7cd4ba7 377}
378
379//=======================================================================
59f45b7c 380//function : ChangeLayer
381//purpose :
382//=======================================================================
383
a1954302 384void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure* theStructure,
385 const Graphic3d_ZLayerId theOldLayerId,
386 const Graphic3d_ZLayerId theNewLayerId)
59f45b7c 387{
a1954302 388 Standard_Integer aSeqPos = myLayers.Lower();
389 myLayerIds.Find (theOldLayerId, aSeqPos);
f5b72419 390 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 391 Standard_Integer aPriority = -1;
59f45b7c 392
393 // take priority and remove structure from list found by <theOldLayerId>
394 // if the structure is not found there, scan through all other layers
3fe9ce0e 395 if (aLayer.Remove (theStructure, aPriority, Standard_False))
59f45b7c 396 {
bd6a8454 397 if (theOldLayerId == Graphic3d_ZLayerId_Default
398 && theStructure->IsRaytracable())
399 {
400 ++myModifStateOfRaytraceable;
401 }
402
a1954302 403 --myNbStructures;
7c3ef2f7 404 if (aLayer.IsImmediate())
a1954302 405 {
406 --myImmediateNbStructures;
407 }
408
a0c20252 409 // isForChangePriority should be Standard_False below, because we want
410 // the BVH tree in the target layer to be updated with theStructure
411 AddStructure (theStructure, theNewLayerId, aPriority);
a1954302 412 return;
59f45b7c 413 }
a1954302 414
415 // scan through layers and remove it
f88457e6 416 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
59f45b7c 417 {
f88457e6 418 if (aSeqPos == anIts.Index())
59f45b7c 419 {
a1954302 420 continue;
421 }
59f45b7c 422
a1954302 423 // try to remove structure and get priority value from this layer
f5b72419 424 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 425 if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
426 {
f88457e6 427 if (anIts.Index() == myDefaultLayerIndex
bd6a8454 428 && theStructure->IsRaytracable())
429 {
430 ++myModifStateOfRaytraceable;
431 }
432
a1954302 433 --myNbStructures;
7c3ef2f7 434 if (aLayerEx.IsImmediate())
b7cd4ba7 435 {
a1954302 436 --myImmediateNbStructures;
b7cd4ba7 437 }
a1954302 438
439 // isForChangePriority should be Standard_False below, because we want
440 // the BVH tree in the target layer to be updated with theStructure
441 AddStructure (theStructure, theNewLayerId, aPriority);
442 return;
b7cd4ba7 443 }
444 }
445}
446
447//=======================================================================
448//function : ChangePriority
449//purpose :
450//=======================================================================
a1954302 451void OpenGl_LayerList::ChangePriority (const OpenGl_Structure* theStructure,
452 const Graphic3d_ZLayerId theLayerId,
453 const Standard_Integer theNewPriority)
b7cd4ba7 454{
a1954302 455 Standard_Integer aSeqPos = myLayers.Lower();
456 myLayerIds.Find (theLayerId, aSeqPos);
f5b72419 457 OpenGl_Layer& aLayer = *myLayers.ChangeValue (aSeqPos);
a1954302 458 Standard_Integer anOldPriority = -1;
b7cd4ba7 459
a1954302 460 if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
b7cd4ba7 461 {
a1954302 462 --myNbStructures;
7c3ef2f7 463 if (aLayer.IsImmediate())
a1954302 464 {
465 --myImmediateNbStructures;
466 }
467
b7cd4ba7 468 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
a1954302 469 return;
b7cd4ba7 470 }
a1954302 471
f88457e6 472 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
b7cd4ba7 473 {
f88457e6 474 if (aSeqPos == anIts.Index())
b7cd4ba7 475 {
a1954302 476 continue;
477 }
b7cd4ba7 478
f5b72419 479 OpenGl_Layer& aLayerEx = *anIts.ChangeValue();
a1954302 480 if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
481 {
482 --myNbStructures;
7c3ef2f7 483 if (aLayerEx.IsImmediate())
59f45b7c 484 {
a1954302 485 --myImmediateNbStructures;
59f45b7c 486 }
a1954302 487
488 AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
489 return;
59f45b7c 490 }
491 }
492}
493
494//=======================================================================
a1954302 495//function : SetLayerSettings
496//purpose :
59f45b7c 497//=======================================================================
a1954302 498void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId theLayerId,
499 const Graphic3d_ZLayerSettings& theSettings)
500{
501 OpenGl_Layer& aLayer = Layer (theLayerId);
7c3ef2f7 502 if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
a1954302 503 {
7c3ef2f7 504 if (theSettings.IsImmediate())
a1954302 505 {
506 myImmediateNbStructures += aLayer.NbStructures();
507 }
508 else
509 {
510 myImmediateNbStructures -= aLayer.NbStructures();
511 }
512 }
513 aLayer.SetLayerSettings (theSettings);
514}
59f45b7c 515
a1954302 516//=======================================================================
2b8832bb 517//function : UpdateCulling
518//purpose :
519//=======================================================================
520void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
521 const Standard_Boolean theToDrawImmediate)
522{
5e30547b 523 const Handle(OpenGl_FrameStats)& aStats = theWorkspace->GetGlContext()->FrameStats();
524 OSD_Timer& aTimer = aStats->ActiveDataFrame().ChangeTimer (Graphic3d_FrameStatsTimer_CpuCulling);
525 aTimer.Start();
526
5dc0517d 527 const Standard_Integer aViewId = theWorkspace->View()->Identification();
d325cb7f 528 const Graphic3d_CullingTool& aSelector = theWorkspace->View()->BVHTreeSelector();
2b8832bb 529 for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
530 {
531 OpenGl_Layer& aLayer = *anIts.ChangeValue();
532 if (aLayer.IsImmediate() != theToDrawImmediate)
533 {
534 continue;
535 }
536
0e3025bc 537 aLayer.UpdateCulling (aViewId, aSelector, theWorkspace->View()->RenderingParams().FrustumCullingState);
2b8832bb 538 }
5e30547b 539
540 aTimer.Stop();
541 aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU();
2b8832bb 542}
543
544//=======================================================================
d325cb7f 545//function : renderLayer
546//purpose :
547//=======================================================================
548void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace,
549 const OpenGl_GlobalLayerSettings& theDefaultSettings,
550 const Graphic3d_Layer& theLayer) const
551{
552 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
553
554 const Graphic3d_ZLayerSettings& aLayerSettings = theLayer.LayerSettings();
555 // aLayerSettings.ToClearDepth() is handled outside
556
557 // handle depth test
558 if (aLayerSettings.ToEnableDepthTest())
559 {
560 // assuming depth test is enabled by default
561 glDepthFunc (theDefaultSettings.DepthFunc);
562 }
563 else
564 {
565 glDepthFunc (GL_ALWAYS);
566 }
567
568 // save environment texture
569 Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
570 if (!aLayerSettings.UseEnvironmentTexture())
571 {
572 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
573 }
574
575 // handle depth offset
576 const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->SetDefaultPolygonOffset (aLayerSettings.PolygonOffset());
577
578 // handle depth write
579 theWorkspace->UseDepthWrite() = aLayerSettings.ToEnableDepthWrite() && theDefaultSettings.DepthMask == GL_TRUE;
580 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
581
582 const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull();
583 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
584 Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources();
585 const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack;
586 if (hasOwnLights)
587 {
588 aLayerSettings.Lights()->UpdateRevision();
589 aManager->UpdateLightSourceStateTo (aLayerSettings.Lights());
590 }
591
592 const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
593 if (hasLocalCS)
594 {
595 // Apply local camera transformation.
596 // The vertex position is computed by the following formula in GLSL program:
597 // gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
598 // where:
599 // occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection
600 // occWorldViewMatrix - world-view matrix defining Camera position and orientation
601 // occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system
602 // occVertex - input vertex position
603 //
604 // Since double precision is quite expensive on modern GPUs, and not available on old hardware,
605 // all these values are passed with single float precision to the shader.
606 // As result, single precision become insufficient for handling objects far from the world origin.
607 //
608 // Several approaches can be used to solve precision issues:
609 // - [Broute force] migrate to double precision for all matrices and vertex position.
610 // This is too expensive for most hardware.
611 // - Store only translation part with double precision and pass it to GLSL program.
612 // This requires modified GLSL programs for computing transformation
613 // and extra packing mechanism for hardware not supporting double precision natively.
614 // This solution is less expensive then previous one.
615 // - Move translation part of occModelWorldMatrix into occWorldViewMatrix.
616 // The main idea here is that while moving Camera towards the object,
617 // Camera translation part and Object translation part will compensate each other
618 // to fit into single float precision.
619 // But this operation should be performed with double precision - this is why we are moving
620 // translation part of occModelWorldMatrix to occWorldViewMatrix.
621 //
622 // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario.
623 // Here we do the trick:
624 // - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it.
625 // This Local Origin is included into occWorldViewMatrix during rendering.
626 // - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer.
627 // This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer.
628 theWorkspace->View()->SetLocalOrigin (aLayerSettings.Origin());
629
630 NCollection_Mat4<Standard_Real> aWorldView = aWorldCamera->OrientationMatrix();
631 Graphic3d_TransformUtils::Translate (aWorldView, aLayerSettings.Origin().X(), aLayerSettings.Origin().Y(), aLayerSettings.Origin().Z());
632
633 NCollection_Mat4<Standard_ShortReal> aWorldViewF;
634 aWorldViewF.ConvertFrom (aWorldView);
635 aCtx->WorldViewState.SetCurrent (aWorldViewF);
636 aCtx->ShaderManager()->UpdateClippingState();
637 aCtx->ShaderManager()->UpdateLightSourceState();
638 }
639
640 // render priority list
641 const Standard_Integer aViewId = theWorkspace->View()->Identification();
642 for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (theLayer.ArrayOfStructures()); aMapIter.More(); aMapIter.Next())
643 {
644 const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value();
645 for (OpenGl_Structure::StructIterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
646 {
647 const OpenGl_Structure* aStruct = aStructIter.Value();
648 if (aStruct->IsCulled()
649 || !aStruct->IsVisible (aViewId))
650 {
651 continue;
652 }
653
654 aStruct->Render (theWorkspace);
655 }
656 }
657
658 if (hasOwnLights)
659 {
660 aManager->UpdateLightSourceStateTo (aLightsBack);
661 }
662 if (hasLocalCS)
663 {
664 aCtx->ShaderManager()->RevertClippingState();
665 aCtx->ShaderManager()->UpdateLightSourceState();
666
667 aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF());
668 theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0));
669 }
670
671 // always restore polygon offset between layers rendering
672 theWorkspace->SetDefaultPolygonOffset (anAppliedOffsetParams);
673
674 // restore environment texture
675 if (!aLayerSettings.UseEnvironmentTexture())
676 {
677 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
678 }
679}
680
681//=======================================================================
a1954302 682//function : Render
683//purpose :
684//=======================================================================
685void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
91c60b57 686 const Standard_Boolean theToDrawImmediate,
a1073ae2 687 const OpenGl_LayerFilter theLayersToProcess,
688 OpenGl_FrameBuffer* theReadDrawFbo,
689 OpenGl_FrameBuffer* theOitAccumFbo) const
59f45b7c 690{
a1073ae2 691 // Remember global settings for glDepth function and write mask.
f88457e6 692 OpenGl_GlobalLayerSettings aPrevSettings;
c5751993 693
a1954302 694 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
f88457e6 695 aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc);
696 aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
697 OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
a1954302 698
a1073ae2 699 // Two render filters are used to support transparency draw. Opaque filter accepts
700 // only non-transparent OpenGl elements of a layer and counts number of skipped
701 // transparent ones. If the counter has positive value the layer is added into
702 // transparency post-processing stack. At the end of drawing or once the depth
703 // buffer is to be cleared the layers in the stack should be drawn using
704 // blending and depth mask settings and another transparency filter which accepts
705 // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
706 // was preallocated before going into this method and has enough space to keep
707 // maximum number of references to layers, therefore it will not increase memory
708 // fragmentation during regular rendering.
1b661a81 709 const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
710 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
a1073ae2 711
712 myTransparentToProcess.Clear();
713
714 OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
f88457e6 715 Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
716 const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
717 && aPrevSettings.DepthMask == GL_TRUE;
992ed6b3 718 const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
f88457e6 719 for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, myDefaultLayerIndex, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
59f45b7c 720 {
f88457e6 721 bool hasSkippedDepthLayers = false;
722 for (int aPassIter = toPerformDepthPrepass ? 0 : 2; aPassIter < 3; ++aPassIter)
91c60b57 723 {
f88457e6 724 if (aPassIter == 0)
725 {
726 aCtx->SetColorMask (false);
992ed6b3 727 aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
f88457e6 728 aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
729 aDefaultSettings.DepthMask = GL_TRUE;
730 }
731 else if (aPassIter == 1)
732 {
733 if (!hasSkippedDepthLayers)
734 {
735 continue;
736 }
737 aCtx->SetColorMask (true);
992ed6b3 738 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 739 aDefaultSettings = aPrevSettings;
740 }
741 else if (aPassIter == 2)
742 {
743 aCtx->SetColorMask (true);
992ed6b3 744 aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
f88457e6 745 if (toPerformDepthPrepass)
746 {
747 aDefaultSettings.DepthFunc = GL_EQUAL;
748 aDefaultSettings.DepthMask = GL_FALSE;
749 }
750 }
91c60b57 751
f88457e6 752 OpenGl_FilteredIndexedLayerIterator aLayerIter (aLayerIterStart);
753 for (; aLayerIter.More(); aLayerIter.Next())
754 {
755 const OpenGl_Layer& aLayer = aLayerIter.Value();
756
757 // make sure to clear depth of previous layers even if layer has no structures
758 if (aLayer.LayerSettings().ToClearDepth())
759 {
760 aClearDepthLayer = aLayerIter.Index();
761 }
2b8832bb 762 if (aLayer.IsCulled())
f88457e6 763 {
764 continue;
765 }
766 else if (aClearDepthLayer > aClearDepthLayerPrev)
767 {
768 // At this point the depth buffer may be set to clear by previous configuration of layers or configuration of the current layer.
769 // Additional rendering pass to handle transparent elements of recently drawn layers require use of current depth
770 // buffer so we put remaining layers for processing as one bunch before erasing the depth buffer.
771 if (aPassIter == 2)
772 {
773 aLayerIterStart = aLayerIter;
774 }
775 else
776 {
777 aClearDepthLayer = -1;
778 }
779 break;
780 }
781 else if (aPassIter == 0
782 && !aLayer.LayerSettings().ToRenderInDepthPrepass())
783 {
784 hasSkippedDepthLayers = true;
785 continue;
786 }
787 else if (aPassIter == 1
788 && aLayer.LayerSettings().ToRenderInDepthPrepass())
789 {
790 continue;
791 }
792
793 // Render opaque OpenGl elements of a layer and count the number of skipped.
794 // If a layer has skipped (e.g. transparent) elements it should be added into
795 // the transparency post-processing stack.
1b661a81 796 theWorkspace->ResetSkippedCounter();
f88457e6 797
d325cb7f 798 renderLayer (theWorkspace, aDefaultSettings, aLayer);
f88457e6 799
800 if (aPassIter != 0
1b661a81 801 && theWorkspace->NbSkippedTransparentElements() > 0)
f88457e6 802 {
803 myTransparentToProcess.Push (&aLayer);
804 }
805 }
806 if (aPassIter == 2
807 && !aLayerIter.More())
808 {
809 aLayerIterStart = aLayerIter;
810 }
a1954302 811 }
f88457e6 812
813 if (!myTransparentToProcess.IsEmpty())
59f45b7c 814 {
f88457e6 815 renderTransparent (theWorkspace, aStackIter, aPrevSettings, theReadDrawFbo, theOitAccumFbo);
59f45b7c 816 }
f88457e6 817 if (aClearDepthLayer > aClearDepthLayerPrev)
a1954302 818 {
f88457e6 819 aClearDepthLayerPrev = aClearDepthLayer;
b3eab8ef 820 glDepthMask (GL_TRUE);
821 glClear (GL_DEPTH_BUFFER_BIT);
a1954302 822 }
b3eab8ef 823 }
824
f88457e6 825 aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
826 aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);
a1073ae2 827
828 theWorkspace->SetRenderFilter (aPrevFilter);
829}
830
831//=======================================================================
832//function : renderTransparent
833//purpose : Render transparent objects using blending operator.
834//=======================================================================
835void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theWorkspace,
836 OpenGl_LayerStack::iterator& theLayerIter,
837 const OpenGl_GlobalLayerSettings& theGlobalSettings,
838 OpenGl_FrameBuffer* theReadDrawFbo,
839 OpenGl_FrameBuffer* theOitAccumFbo) const
840{
841 // Blended order-independent transparency algorithm require several preconditions
842 // to be enabled. It should be requested by user, at least two outputs from
843 // fragment shader should be supported by GPU, so is the given framebuffer
844 // should contain two additional color buffers to handle accumulated color channels,
845 // blended alpha channel and weight factors - these accumulation buffers are required
846 // to implement commuting blend operator (at least OpenGl 2.0 should be available).
847 const bool isEnabledOit = theOitAccumFbo != NULL
848 && theOitAccumFbo->NbColorBuffers() >= 2
849 && theOitAccumFbo->ColorTexture (0)->IsValid()
850 && theOitAccumFbo->ColorTexture (1)->IsValid();
851
852 // Check if current iterator has already reached the end of the stack.
853 // This should happen if no additional layers has been added to
854 // the processing stack after last transparency pass.
855 if (theLayerIter == myTransparentToProcess.Back())
856 {
857 return;
858 }
859
860 const Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
861 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
862 OpenGl_View* aView = theWorkspace->View();
863 const float aDepthFactor = aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
864
1b661a81 865 const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
866 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
a1073ae2 867
868 aCtx->core11fwd->glEnable (GL_BLEND);
869
870 if (isEnabledOit)
871 {
872 aManager->SetOitState (true, aDepthFactor);
873
874 theOitAccumFbo->BindBuffer (aCtx);
875
876 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
877 aCtx->SetDrawBuffers (2, aDrawBuffers);
878 aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
879 aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
880 aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
881 }
882 else
883 {
884 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
885 }
886
887 // During blended order-independent transparency pass the depth test
888 // should be enabled to discard fragments covered by opaque geometry
889 // and depth writing should be disabled, because transparent fragments
890 // overal each other with non unitary coverage factor.
891 OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
892 aGlobalSettings.DepthMask = GL_FALSE;
893 aCtx->core11fwd->glDepthMask (GL_FALSE);
894
895 for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
896 {
d325cb7f 897 renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
a1073ae2 898 }
899
900 // Revert state of rendering.
901 if (isEnabledOit)
902 {
903 aManager->SetOitState (false, aDepthFactor);
904 theOitAccumFbo->UnbindBuffer (aCtx);
905 if (theReadDrawFbo)
906 {
907 theReadDrawFbo->BindBuffer (aCtx);
908 }
909
910 static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
911 aCtx->SetDrawBuffers (1, aDrawBuffers);
912 }
913
1b661a81 914 theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
a1073ae2 915 if (isEnabledOit)
916 {
917 const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
918 OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
919 if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
920 {
921 aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
922 aCtx->core11fwd->glDepthMask (GL_FALSE);
923
924 // Bind full screen quad buffer and framebuffer resources.
925 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
926
cc8cbabe 927 const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
a1073ae2 928
cc8cbabe 929 theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
930 theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
a1073ae2 931
932 // Draw full screen quad with special shader to compose the buffers.
933 aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
934 aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
935
936 // Unbind OpenGL texture objects and shader program.
937 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
cc8cbabe 938 theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
ce1c28b8 939 theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
a1073ae2 940 aCtx->BindProgram (NULL);
941
942 if (!aTextureBack.IsNull())
943 {
cc8cbabe 944 aCtx->BindTextures (aTextureBack);
a1073ae2 945 }
946 }
947 else
948 {
949 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
950 "Initialization of OIT compositing pass has failed.\n"
951 " Blended order-independent transparency will not be available.\n");
952 if (aView != NULL)
953 {
954 Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
955 aOITFlag = Standard_True;
956 }
957 }
958 }
959
960 aCtx->core11fwd->glDisable (GL_BLEND);
961 aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
962 aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
963 aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
964}