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