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