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