c357e426 |
1 | // Created on: 2011-09-20 |
2 | // Created by: Sergey ZERCHANINOV |
3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
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 |
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. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <stdio.h> |
17 | #include <stdlib.h> |
18 | |
19 | #include <OpenGl_GlCore11.hxx> |
c357e426 |
20 | |
21 | #include <Graphic3d_GraphicDriver.hxx> |
851dacdb |
22 | #include <Graphic3d_StructureManager.hxx> |
c357e426 |
23 | #include <Graphic3d_TextureParams.hxx> |
24 | #include <Graphic3d_Texture2Dmanual.hxx> |
25 | #include <Graphic3d_TransformUtils.hxx> |
26 | #include <Image_AlienPixMap.hxx> |
27 | |
28 | #include <NCollection_Mat4.hxx> |
29 | |
30 | #include <OpenGl_AspectLine.hxx> |
31 | #include <OpenGl_Context.hxx> |
32 | #include <OpenGl_Matrix.hxx> |
33 | #include <OpenGl_Workspace.hxx> |
34 | #include <OpenGl_View.hxx> |
c357e426 |
35 | #include <OpenGl_GraduatedTrihedron.hxx> |
36 | #include <OpenGl_PrimitiveArray.hxx> |
c357e426 |
37 | #include <OpenGl_ShaderManager.hxx> |
38 | #include <OpenGl_ShaderProgram.hxx> |
39 | #include <OpenGl_Structure.hxx> |
40 | #include <OpenGl_ArbFBO.hxx> |
41 | |
a0b49de4 |
42 | namespace |
43 | { |
44 | //! Format Frame Buffer format for logging messages. |
45 | static TCollection_AsciiString printFboFormat (const Handle(OpenGl_FrameBuffer)& theFbo) |
46 | { |
47 | return TCollection_AsciiString() + theFbo->GetInitVPSizeX() + "x" + theFbo->GetInitVPSizeY() + "@" + theFbo->NbSamples(); |
48 | } |
49 | |
50 | //! Return TRUE if Frame Buffer initialized has failed with the same parameters. |
51 | static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck, |
52 | Standard_Integer theSizeX, |
53 | Standard_Integer theSizeY, |
54 | Standard_Integer theNbSamples) |
55 | { |
56 | return !theFboToCheck->IsValid() |
57 | && theFboToCheck->GetInitVPSizeX() == theSizeX |
58 | && theFboToCheck->GetInitVPSizeY() == theSizeY |
59 | && theFboToCheck->NbSamples() == theNbSamples; |
60 | } |
61 | |
62 | //! Return TRUE if Frame Buffer initialized has failed with the same parameters. |
63 | static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck, |
64 | const Handle(OpenGl_FrameBuffer)& theFboRef) |
65 | { |
66 | return checkWasFailedFbo (theFboToCheck, theFboRef->GetVPSizeX(), theFboRef->GetVPSizeY(), theFboRef->NbSamples()); |
67 | } |
68 | } |
69 | |
c357e426 |
70 | //======================================================================= |
a521d90d |
71 | //function : drawBackground |
c357e426 |
72 | //purpose : |
73 | //======================================================================= |
a521d90d |
74 | void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) |
c357e426 |
75 | { |
76 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
77 | |
8613985b |
78 | if (!myBgTextureArray->IsDefined() // no texture |
79 | && !myBgGradientArray->IsDefined()) // no gradient |
c357e426 |
80 | { |
81 | return; |
82 | } |
83 | |
84 | const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False); |
85 | if (wasUsedZBuffer) |
86 | { |
87 | aCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
88 | } |
89 | |
c357e426 |
90 | // Drawing background gradient if: |
91 | // - gradient fill type is not Aspect_GFM_NONE and |
92 | // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode |
93 | if (myBgGradientArray->IsDefined() |
b6472664 |
94 | && (!myTextureParams->Aspect()->ToMapTexture() |
c357e426 |
95 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED |
96 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE)) |
97 | { |
98 | #if !defined(GL_ES_VERSION_2_0) |
99 | GLint aShadingModelOld = GL_SMOOTH; |
dd1ae9df |
100 | if (aCtx->core11 != NULL |
101 | && aCtx->caps->ffpEnable) |
c357e426 |
102 | { |
103 | aCtx->core11fwd->glDisable (GL_LIGHTING); |
104 | aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld); |
105 | aCtx->core11->glShadeModel (GL_SMOOTH); |
106 | } |
107 | #endif |
108 | |
c357e426 |
109 | myBgGradientArray->Render (theWorkspace); |
110 | |
111 | #if !defined(GL_ES_VERSION_2_0) |
dd1ae9df |
112 | if (aCtx->core11 != NULL |
113 | && aCtx->caps->ffpEnable) |
c357e426 |
114 | { |
115 | aCtx->core11->glShadeModel (aShadingModelOld); |
116 | } |
117 | #endif |
118 | } |
119 | |
120 | // Drawing background image if it is defined |
121 | // (texture is defined and fill type is not Aspect_FM_NONE) |
122 | if (myBgTextureArray->IsDefined() |
b6472664 |
123 | && myTextureParams->Aspect()->ToMapTexture()) |
c357e426 |
124 | { |
125 | aCtx->core11fwd->glDisable (GL_BLEND); |
126 | |
127 | const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams); |
c357e426 |
128 | myBgTextureArray->Render (theWorkspace); |
c357e426 |
129 | theWorkspace->SetAspectFace (anOldAspectFace); |
130 | } |
131 | |
c357e426 |
132 | if (wasUsedZBuffer) |
133 | { |
134 | theWorkspace->SetUseZBuffer (Standard_True); |
135 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); |
136 | } |
137 | } |
138 | |
139 | //======================================================================= |
140 | //function : Redraw |
141 | //purpose : |
142 | //======================================================================= |
143 | void OpenGl_View::Redraw() |
144 | { |
7ccf8676 |
145 | const Standard_Boolean wasDisabledMSAA = myToDisableMSAA; |
146 | const Standard_Boolean hadFboBlit = myHasFboBlit; |
c357e426 |
147 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
148 | && !myCaps->vboDisable |
149 | && !myCaps->keepArrayData) |
150 | { |
851dacdb |
151 | // caps are shared across all views, thus we need to invalidate all of them |
152 | // if (myWasRedrawnGL) { myStructureManager->SetDeviceLost(); } |
153 | myDriver->setDeviceLost(); |
c357e426 |
154 | myCaps->keepArrayData = Standard_True; |
155 | } |
156 | |
157 | if (!myWorkspace->Activate()) |
158 | { |
159 | return; |
160 | } |
161 | |
162 | myWindow->SetSwapInterval(); |
163 | |
164 | ++myFrameCounter; |
7c3ef2f7 |
165 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
166 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
167 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
c357e426 |
168 | |
169 | // release pending GL resources |
170 | aCtx->ReleaseDelayed(); |
171 | |
172 | // fetch OpenGl context state |
173 | aCtx->FetchState(); |
174 | |
b128c892 |
175 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->(); |
c357e426 |
176 | bool toSwap = aCtx->IsRender() |
177 | && !aCtx->caps->buffersNoSwap |
178 | && aFrameBuffer == NULL; |
179 | |
180 | Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width(); |
181 | Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height(); |
56689b27 |
182 | Standard_Integer aRendSizeX = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeX + 0.5f); |
183 | Standard_Integer aRendSizeY = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeY + 0.5f); |
c357e426 |
184 | |
3c4b62a4 |
185 | // determine multisampling parameters |
56689b27 |
186 | Standard_Integer aNbSamples = !myToDisableMSAA && aSizeX == aRendSizeX |
7ccf8676 |
187 | ? Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0) |
188 | : 0; |
3c4b62a4 |
189 | if (aNbSamples != 0) |
190 | { |
191 | aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); |
192 | } |
193 | |
a1073ae2 |
194 | bool toUseOit = myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT |
195 | && checkOitCompatibility (aCtx, aNbSamples > 0); |
196 | |
197 | const bool toInitImmediateFbo = myTransientDrawToFront |
198 | && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures())); |
199 | |
c357e426 |
200 | if ( aFrameBuffer == NULL |
201 | && !aCtx->DefaultFrameBuffer().IsNull() |
202 | && aCtx->DefaultFrameBuffer()->IsValid()) |
203 | { |
204 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
205 | } |
206 | |
207 | if (myHasFboBlit |
3c4b62a4 |
208 | && (myTransientDrawToFront |
209 | || aProjectType == Graphic3d_Camera::Projection_Stereo |
56689b27 |
210 | || aNbSamples != 0 |
a1073ae2 |
211 | || toUseOit |
56689b27 |
212 | || aSizeX != aRendSizeX)) |
c357e426 |
213 | { |
56689b27 |
214 | if (myMainSceneFbos[0]->GetVPSizeX() != aRendSizeX |
215 | || myMainSceneFbos[0]->GetVPSizeY() != aRendSizeY |
3c4b62a4 |
216 | || myMainSceneFbos[0]->NbSamples() != aNbSamples) |
c357e426 |
217 | { |
521b0d7f |
218 | if (!myTransientDrawToFront) |
219 | { |
220 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
221 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
222 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
223 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
224 | } |
225 | |
c357e426 |
226 | // prepare FBOs containing main scene |
227 | // for further blitting and rendering immediate presentations on top |
228 | if (aCtx->core20fwd != NULL) |
229 | { |
a0b49de4 |
230 | const bool wasFailedMain0 = checkWasFailedFbo (myMainSceneFbos[0], aRendSizeX, aRendSizeY, aNbSamples); |
231 | if (!myMainSceneFbos[0]->Init (aCtx, aRendSizeX, aRendSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples) |
232 | && !wasFailedMain0) |
233 | { |
234 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO " |
235 | + printFboFormat (myMainSceneFbos[0]) + " initialization has failed"; |
236 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
237 | } |
c357e426 |
238 | } |
a1073ae2 |
239 | } |
240 | if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid())) |
241 | { |
a0b49de4 |
242 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); |
243 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) |
244 | && !wasFailedImm0) |
245 | { |
246 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO " |
247 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; |
248 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
249 | } |
c357e426 |
250 | } |
251 | } |
252 | else |
253 | { |
254 | myMainSceneFbos [0]->Release (aCtx.operator->()); |
255 | myMainSceneFbos [1]->Release (aCtx.operator->()); |
256 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
257 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
258 | myMainSceneFbos [0]->ChangeViewport (0, 0); |
259 | myMainSceneFbos [1]->ChangeViewport (0, 0); |
260 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
261 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
262 | } |
263 | |
264 | if (aProjectType == Graphic3d_Camera::Projection_Stereo |
265 | && myMainSceneFbos[0]->IsValid()) |
266 | { |
a0b49de4 |
267 | const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]); |
268 | if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) |
269 | && !wasFailedMain1) |
270 | { |
271 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) " |
272 | + printFboFormat (myMainSceneFbos[1]) + " initialization has failed"; |
273 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
274 | } |
c357e426 |
275 | if (!myMainSceneFbos[1]->IsValid()) |
276 | { |
277 | // no enough memory? |
278 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
279 | } |
280 | else if (!myTransientDrawToFront) |
281 | { |
282 | // |
283 | } |
284 | else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer) |
285 | { |
a0b49de4 |
286 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); |
287 | const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]); |
288 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) |
289 | && !wasFailedImm0) |
290 | { |
291 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " |
292 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; |
293 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
294 | } |
295 | if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) |
296 | && !wasFailedImm1) |
297 | { |
298 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " |
299 | + printFboFormat (myImmediateSceneFbos[1]) + " initialization has failed"; |
300 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
301 | } |
c357e426 |
302 | if (!myImmediateSceneFbos[0]->IsValid() |
303 | || !myImmediateSceneFbos[1]->IsValid()) |
304 | { |
305 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
306 | } |
307 | } |
308 | } |
309 | |
a1073ae2 |
310 | // create color and coverage accumulation buffers required for OIT algorithm |
311 | if (toUseOit) |
312 | { |
313 | Standard_Integer anFboIt = 0; |
314 | for (; anFboIt < 2; ++anFboIt) |
315 | { |
316 | Handle(OpenGl_FrameBuffer)& aMainSceneFbo = myMainSceneFbos [anFboIt]; |
317 | Handle(OpenGl_FrameBuffer)& aMainSceneFboOit = myMainSceneFbosOit [anFboIt]; |
318 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFbo = myImmediateSceneFbos [anFboIt]; |
319 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFboOit = myImmediateSceneFbosOit[anFboIt]; |
320 | if (aMainSceneFbo->IsValid() |
321 | && (aMainSceneFboOit->GetVPSizeX() != aRendSizeX |
322 | || aMainSceneFboOit->GetVPSizeY() != aRendSizeY |
323 | || aMainSceneFboOit->NbSamples() != aNbSamples)) |
324 | { |
325 | Standard_Integer aColorConfig = 0; |
326 | for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED) |
327 | { |
328 | if (myFboOitColorConfig.IsEmpty()) |
329 | { |
330 | if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig)) |
331 | { |
332 | break; |
333 | } |
334 | } |
335 | if (aMainSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, aMainSceneFbo->DepthStencilTexture(), aNbSamples)) |
336 | { |
337 | break; |
338 | } |
339 | myFboOitColorConfig.Clear(); |
340 | } |
341 | if (!aMainSceneFboOit->IsValid()) |
342 | { |
343 | break; |
344 | } |
345 | } |
346 | else if (!aMainSceneFbo->IsValid()) |
347 | { |
348 | aMainSceneFboOit->Release (aCtx.operator->()); |
349 | aMainSceneFboOit->ChangeViewport (0, 0); |
350 | } |
351 | |
352 | if (anImmediateSceneFbo->IsValid() |
353 | && (anImmediateSceneFboOit->GetVPSizeX() != aRendSizeX |
354 | || anImmediateSceneFboOit->GetVPSizeY() != aRendSizeY |
355 | || anImmediateSceneFboOit->NbSamples() != aNbSamples)) |
356 | { |
357 | if (!anImmediateSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, |
358 | anImmediateSceneFbo->DepthStencilTexture(), aNbSamples)) |
359 | { |
360 | break; |
361 | } |
362 | } |
363 | else if (!anImmediateSceneFbo->IsValid()) |
364 | { |
365 | anImmediateSceneFboOit->Release (aCtx.operator->()); |
366 | anImmediateSceneFboOit->ChangeViewport (0, 0); |
367 | } |
368 | } |
369 | if (anFboIt == 0) // only the first OIT framebuffer is mandatory |
370 | { |
371 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
372 | "Initialization of float texture framebuffer for use with\n" |
373 | " blended order-independent transparency rendering algorithm has failed.\n" |
374 | " Blended order-independent transparency will not be available.\n"); |
375 | if (aNbSamples > 0) |
376 | { |
377 | myToDisableOITMSAA = Standard_True; |
378 | } |
379 | else |
380 | { |
381 | myToDisableOIT = Standard_True; |
382 | } |
383 | toUseOit = false; |
384 | } |
385 | } |
386 | if (!toUseOit && myMainSceneFbosOit[0]->IsValid()) |
387 | { |
388 | myMainSceneFbosOit [0]->Release (aCtx.operator->()); |
389 | myMainSceneFbosOit [1]->Release (aCtx.operator->()); |
390 | myImmediateSceneFbosOit[0]->Release (aCtx.operator->()); |
391 | myImmediateSceneFbosOit[1]->Release (aCtx.operator->()); |
392 | myMainSceneFbosOit [0]->ChangeViewport (0, 0); |
393 | myMainSceneFbosOit [1]->ChangeViewport (0, 0); |
394 | myImmediateSceneFbosOit[0]->ChangeViewport (0, 0); |
395 | myImmediateSceneFbosOit[1]->ChangeViewport (0, 0); |
396 | } |
397 | |
c357e426 |
398 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
399 | { |
400 | OpenGl_FrameBuffer* aMainFbos[2] = |
401 | { |
402 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
403 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
404 | }; |
a1073ae2 |
405 | OpenGl_FrameBuffer* aMainFbosOit[2] = |
406 | { |
407 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL, |
408 | myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() : |
409 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL |
410 | }; |
411 | |
c357e426 |
412 | OpenGl_FrameBuffer* anImmFbos[2] = |
413 | { |
414 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
415 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
416 | }; |
a1073ae2 |
417 | OpenGl_FrameBuffer* anImmFbosOit[2] = |
418 | { |
419 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, |
420 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : |
421 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL |
422 | }; |
c357e426 |
423 | |
424 | if (!myTransientDrawToFront) |
425 | { |
a1073ae2 |
426 | anImmFbos [0] = aMainFbos [0]; |
427 | anImmFbos [1] = aMainFbos [1]; |
428 | anImmFbosOit[0] = aMainFbosOit[0]; |
429 | anImmFbosOit[1] = aMainFbosOit[1]; |
c357e426 |
430 | } |
431 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
432 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
433 | { |
a1073ae2 |
434 | anImmFbos [0] = NULL; |
435 | anImmFbos [1] = NULL; |
436 | anImmFbosOit[0] = NULL; |
437 | anImmFbosOit[1] = NULL; |
c357e426 |
438 | } |
439 | |
440 | #if !defined(GL_ES_VERSION_2_0) |
441 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
442 | #endif |
56689b27 |
443 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
444 | aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
445 | |
a1073ae2 |
446 | redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]); |
c357e426 |
447 | myBackBufferRestored = Standard_True; |
448 | myIsImmediateDrawn = Standard_False; |
449 | #if !defined(GL_ES_VERSION_2_0) |
450 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
451 | #endif |
56689b27 |
452 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
453 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
454 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0])) |
c357e426 |
455 | { |
456 | toSwap = false; |
457 | } |
458 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) |
459 | { |
460 | aCtx->SwapBuffers(); |
461 | } |
462 | |
463 | #if !defined(GL_ES_VERSION_2_0) |
464 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
465 | #endif |
56689b27 |
466 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
467 | aMainFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
468 | |
a1073ae2 |
469 | redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]); |
c357e426 |
470 | myBackBufferRestored = Standard_True; |
471 | myIsImmediateDrawn = Standard_False; |
56689b27 |
472 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
473 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
474 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1])) |
c357e426 |
475 | { |
476 | toSwap = false; |
477 | } |
478 | |
479 | if (anImmFbos[0] != NULL) |
480 | { |
56689b27 |
481 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), 1.0f); |
3c4b62a4 |
482 | drawStereoPair (aFrameBuffer); |
c357e426 |
483 | } |
484 | } |
485 | else |
486 | { |
a1073ae2 |
487 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer; |
488 | OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL; |
489 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
490 | OpenGl_FrameBuffer* anImmFboOit = NULL; |
491 | if (!myTransientDrawToFront) |
c357e426 |
492 | { |
a1073ae2 |
493 | anImmFbo = aMainFbo; |
494 | anImmFboOit = aMainFboOit; |
c357e426 |
495 | } |
a1073ae2 |
496 | else if (myImmediateSceneFbos[0]->IsValid()) |
521b0d7f |
497 | { |
a1073ae2 |
498 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
499 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; |
521b0d7f |
500 | } |
c357e426 |
501 | |
502 | #if !defined(GL_ES_VERSION_2_0) |
3bffef55 |
503 | if (aMainFbo == NULL) |
c357e426 |
504 | { |
505 | aCtx->SetReadDrawBuffer (GL_BACK); |
506 | } |
507 | #endif |
56689b27 |
508 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
509 | aMainFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
510 | |
511 | redraw (aProjectType, aMainFbo, aMainFboOit); |
c357e426 |
512 | myBackBufferRestored = Standard_True; |
513 | myIsImmediateDrawn = Standard_False; |
56689b27 |
514 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
515 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
516 | if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit)) |
c357e426 |
517 | { |
518 | toSwap = false; |
519 | } |
520 | |
521 | if (anImmFbo != NULL |
522 | && anImmFbo != aFrameBuffer) |
523 | { |
524 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
525 | } |
526 | } |
527 | |
bf02aa7d |
528 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
529 | && myRenderParams.IsGlobalIlluminationEnabled) |
530 | { |
531 | myAccumFrames++; |
532 | } |
533 | |
c357e426 |
534 | // bind default FBO |
535 | bindDefaultFbo(); |
536 | |
7ccf8676 |
537 | if (wasDisabledMSAA != myToDisableMSAA |
538 | || hadFboBlit != myHasFboBlit) |
539 | { |
540 | // retry on error |
541 | Redraw(); |
542 | } |
543 | |
8613985b |
544 | // reset state for safety |
545 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
546 | if (aCtx->caps->ffpEnable) |
547 | { |
548 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
549 | } |
8613985b |
550 | |
c357e426 |
551 | // Swap the buffers |
552 | if (toSwap) |
553 | { |
554 | aCtx->SwapBuffers(); |
555 | if (!myMainSceneFbos[0]->IsValid()) |
556 | { |
557 | myBackBufferRestored = Standard_False; |
558 | } |
559 | } |
560 | else |
561 | { |
562 | aCtx->core11fwd->glFlush(); |
563 | } |
564 | |
565 | // reset render mode state |
566 | aCtx->FetchState(); |
567 | |
568 | myWasRedrawnGL = Standard_True; |
569 | } |
570 | |
571 | // ======================================================================= |
572 | // function : RedrawImmediate |
573 | // purpose : |
574 | // ======================================================================= |
575 | void OpenGl_View::RedrawImmediate() |
576 | { |
577 | if (!myWorkspace->Activate()) |
578 | return; |
579 | |
580 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
581 | if (!myTransientDrawToFront |
582 | || !myBackBufferRestored |
583 | || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) |
584 | { |
585 | Redraw(); |
586 | return; |
587 | } |
588 | |
589 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
590 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
b128c892 |
591 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->(); |
c357e426 |
592 | |
593 | if ( aFrameBuffer == NULL |
594 | && !aCtx->DefaultFrameBuffer().IsNull() |
595 | && aCtx->DefaultFrameBuffer()->IsValid()) |
596 | { |
597 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
598 | } |
599 | |
600 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
601 | { |
602 | if (myMainSceneFbos[0]->IsValid() |
603 | && !myMainSceneFbos[1]->IsValid()) |
604 | { |
605 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
606 | } |
607 | } |
608 | |
609 | bool toSwap = false; |
610 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
611 | { |
612 | OpenGl_FrameBuffer* aMainFbos[2] = |
613 | { |
614 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
615 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
616 | }; |
617 | OpenGl_FrameBuffer* anImmFbos[2] = |
618 | { |
619 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
620 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
621 | }; |
a1073ae2 |
622 | OpenGl_FrameBuffer* anImmFbosOit[2] = |
623 | { |
624 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, |
625 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : |
626 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL |
627 | }; |
c357e426 |
628 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
629 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
630 | { |
a1073ae2 |
631 | anImmFbos[0] = NULL; |
632 | anImmFbos[1] = NULL; |
633 | anImmFbosOit[0] = NULL; |
634 | anImmFbosOit[1] = NULL; |
c357e426 |
635 | } |
636 | |
637 | if (aCtx->arbFBO != NULL) |
638 | { |
639 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
640 | } |
641 | #if !defined(GL_ES_VERSION_2_0) |
642 | if (anImmFbos[0] == NULL) |
643 | { |
644 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
645 | } |
646 | #endif |
56689b27 |
647 | |
648 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
649 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
650 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, |
651 | aMainFbos[0], |
652 | anImmFbos[0], |
a1073ae2 |
653 | anImmFbosOit[0], |
c357e426 |
654 | Standard_True) || toSwap; |
655 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
656 | && toSwap |
657 | && !aCtx->caps->buffersNoSwap) |
658 | { |
659 | aCtx->SwapBuffers(); |
660 | } |
661 | |
662 | if (aCtx->arbFBO != NULL) |
663 | { |
664 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
665 | } |
666 | #if !defined(GL_ES_VERSION_2_0) |
667 | if (anImmFbos[1] == NULL) |
668 | { |
669 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
670 | } |
671 | #endif |
56689b27 |
672 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
673 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
674 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, |
675 | aMainFbos[1], |
676 | anImmFbos[1], |
a1073ae2 |
677 | anImmFbosOit[1], |
c357e426 |
678 | Standard_True) || toSwap; |
679 | if (anImmFbos[0] != NULL) |
680 | { |
3c4b62a4 |
681 | drawStereoPair (aFrameBuffer); |
c357e426 |
682 | } |
683 | } |
684 | else |
685 | { |
686 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
687 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
a1073ae2 |
688 | OpenGl_FrameBuffer* anImmFboOit = NULL; |
689 | if (myImmediateSceneFbos[0]->IsValid()) |
c357e426 |
690 | { |
a1073ae2 |
691 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
692 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; |
c357e426 |
693 | } |
694 | #if !defined(GL_ES_VERSION_2_0) |
695 | if (aMainFbo == NULL) |
696 | { |
697 | aCtx->SetReadDrawBuffer (GL_BACK); |
698 | } |
699 | #endif |
56689b27 |
700 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
701 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
702 | toSwap = redrawImmediate (aProjectType, |
703 | aMainFbo, |
704 | anImmFbo, |
a1073ae2 |
705 | anImmFboOit, |
c357e426 |
706 | Standard_True) || toSwap; |
707 | if (anImmFbo != NULL |
708 | && anImmFbo != aFrameBuffer) |
709 | { |
710 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
711 | } |
712 | } |
713 | |
714 | // bind default FBO |
715 | bindDefaultFbo(); |
716 | |
8613985b |
717 | // reset state for safety |
718 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
719 | if (aCtx->caps->ffpEnable) |
720 | { |
721 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
722 | } |
8613985b |
723 | |
c357e426 |
724 | if (toSwap && !aCtx->caps->buffersNoSwap) |
725 | { |
726 | aCtx->SwapBuffers(); |
727 | } |
728 | else |
729 | { |
730 | aCtx->core11fwd->glFlush(); |
731 | } |
732 | |
733 | myWasRedrawnGL = Standard_True; |
734 | } |
735 | |
736 | // ======================================================================= |
737 | // function : redraw |
738 | // purpose : |
739 | // ======================================================================= |
a1073ae2 |
740 | void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, |
741 | OpenGl_FrameBuffer* theReadDrawFbo, |
742 | OpenGl_FrameBuffer* theOitAccumFbo) |
c357e426 |
743 | { |
744 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
745 | if (theReadDrawFbo != NULL) |
746 | { |
747 | theReadDrawFbo->BindBuffer (aCtx); |
748 | theReadDrawFbo->SetupViewport (aCtx); |
749 | } |
750 | else |
751 | { |
3bffef55 |
752 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
753 | aCtx->ResizeViewport (aViewport); |
c357e426 |
754 | } |
755 | |
756 | // request reset of material |
8613985b |
757 | aCtx->ShaderManager()->UpdateMaterialState(); |
758 | |
c357e426 |
759 | myWorkspace->UseZBuffer() = Standard_True; |
760 | myWorkspace->UseDepthWrite() = Standard_True; |
761 | GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; |
762 | glDepthFunc (GL_LEQUAL); |
763 | glDepthMask (GL_TRUE); |
764 | glEnable (GL_DEPTH_TEST); |
765 | |
766 | #if !defined(GL_ES_VERSION_2_0) |
767 | glClearDepth (1.0); |
768 | #else |
769 | glClearDepthf (1.0f); |
770 | #endif |
771 | |
8613985b |
772 | const OpenGl_Vec4& aBgColor = myBgColor; |
773 | glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f); |
c357e426 |
774 | |
775 | glClear (toClear); |
776 | |
a1073ae2 |
777 | render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False); |
c357e426 |
778 | } |
779 | |
780 | // ======================================================================= |
781 | // function : redrawMonoImmediate |
782 | // purpose : |
783 | // ======================================================================= |
784 | bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, |
a1073ae2 |
785 | OpenGl_FrameBuffer* theReadFbo, |
786 | OpenGl_FrameBuffer* theDrawFbo, |
787 | OpenGl_FrameBuffer* theOitAccumFbo, |
788 | const Standard_Boolean theIsPartialUpdate) |
c357e426 |
789 | { |
790 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
791 | GLboolean toCopyBackToFront = GL_FALSE; |
521b0d7f |
792 | if (theDrawFbo == theReadFbo |
793 | && theDrawFbo != NULL) |
c357e426 |
794 | { |
795 | myBackBufferRestored = Standard_False; |
796 | } |
797 | else if (theReadFbo != NULL |
798 | && theReadFbo->IsValid() |
799 | && aCtx->IsRender()) |
800 | { |
801 | if (!blitBuffers (theReadFbo, theDrawFbo)) |
802 | { |
803 | return true; |
804 | } |
805 | } |
806 | else if (theDrawFbo == NULL) |
807 | { |
808 | #if !defined(GL_ES_VERSION_2_0) |
809 | aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); |
810 | #endif |
6cde53c4 |
811 | if (toCopyBackToFront |
812 | && myTransientDrawToFront) |
c357e426 |
813 | { |
814 | if (!HasImmediateStructures() |
815 | && !theIsPartialUpdate) |
816 | { |
817 | // prefer Swap Buffers within Redraw in compatibility mode (without FBO) |
818 | return true; |
819 | } |
a0b49de4 |
820 | if (!copyBackToFront()) |
821 | { |
822 | toCopyBackToFront = GL_FALSE; |
823 | myBackBufferRestored = Standard_False; |
824 | } |
c357e426 |
825 | } |
826 | else |
827 | { |
828 | myBackBufferRestored = Standard_False; |
829 | } |
830 | } |
831 | else |
832 | { |
833 | myBackBufferRestored = Standard_False; |
834 | } |
835 | myIsImmediateDrawn = Standard_True; |
836 | |
837 | myWorkspace->UseZBuffer() = Standard_True; |
838 | myWorkspace->UseDepthWrite() = Standard_True; |
839 | glDepthFunc (GL_LEQUAL); |
840 | glDepthMask (GL_TRUE); |
841 | glEnable (GL_DEPTH_TEST); |
842 | #if !defined(GL_ES_VERSION_2_0) |
843 | glClearDepth (1.0); |
844 | #else |
845 | glClearDepthf (1.0f); |
846 | #endif |
847 | |
a1073ae2 |
848 | render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True); |
c357e426 |
849 | |
850 | return !toCopyBackToFront; |
851 | } |
852 | |
853 | //======================================================================= |
854 | //function : Render |
855 | //purpose : |
856 | //======================================================================= |
857 | void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, |
858 | OpenGl_FrameBuffer* theOutputFBO, |
a1073ae2 |
859 | OpenGl_FrameBuffer* theOitAccumFbo, |
c357e426 |
860 | const Standard_Boolean theToDrawImmediate) |
861 | { |
862 | // ================================== |
863 | // Step 1: Prepare for render |
864 | // ================================== |
865 | |
866 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
867 | |
868 | #if !defined(GL_ES_VERSION_2_0) |
869 | // Disable current clipping planes |
870 | if (aContext->core11 != NULL) |
871 | { |
872 | const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes(); |
873 | for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId) |
874 | { |
875 | aContext->core11fwd->glDisable (aClipPlaneId); |
876 | } |
877 | } |
878 | #endif |
879 | |
4ecf34cc |
880 | // update states of OpenGl_BVHTreeSelector (frustum culling algorithm); |
881 | // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale |
c357e426 |
882 | myBVHSelector.SetViewVolume (myCamera); |
4ecf34cc |
883 | myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); |
c357e426 |
884 | |
885 | const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); |
886 | if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) |
887 | { |
016e5959 |
888 | aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &myNoShadingLight : &myLights); |
c357e426 |
889 | myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); |
890 | } |
891 | |
892 | // Update matrices if camera has changed. |
893 | Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); |
7c3ef2f7 |
894 | if (myWorldViewProjState != aWVPState) |
c357e426 |
895 | { |
bf02aa7d |
896 | myAccumFrames = 0; |
7c3ef2f7 |
897 | myWorldViewProjState = aWVPState; |
c357e426 |
898 | } |
899 | |
7c3ef2f7 |
900 | myLocalOrigin.SetCoord (0.0, 0.0, 0.0); |
901 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF()); |
902 | aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF()); |
903 | aContext->ApplyProjectionMatrix(); |
904 | aContext->ApplyWorldViewMatrix(); |
c357e426 |
905 | if (aManager->ModelWorldState().Index() == 0) |
906 | { |
907 | aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); |
908 | } |
909 | |
c357e426 |
910 | // ==================================== |
911 | // Step 2: Redraw background |
912 | // ==================================== |
913 | |
914 | // Render background |
915 | if (!theToDrawImmediate) |
916 | { |
a521d90d |
917 | drawBackground (myWorkspace); |
c357e426 |
918 | } |
919 | |
920 | #if !defined(GL_ES_VERSION_2_0) |
921 | // Switch off lighting by default |
dd1ae9df |
922 | if (aContext->core11 != NULL |
923 | && aContext->caps->ffpEnable) |
c357e426 |
924 | { |
925 | glDisable(GL_LIGHTING); |
926 | } |
927 | #endif |
928 | |
929 | // ================================= |
930 | // Step 3: Redraw main plane |
931 | // ================================= |
932 | |
933 | // Setup face culling |
934 | GLboolean isCullFace = GL_FALSE; |
935 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
936 | { |
937 | isCullFace = glIsEnabled (GL_CULL_FACE); |
938 | if (myBackfacing == Graphic3d_TOBM_DISABLE) |
939 | { |
940 | glEnable (GL_CULL_FACE); |
941 | glCullFace (GL_BACK); |
942 | } |
943 | else |
944 | glDisable (GL_CULL_FACE); |
945 | } |
946 | |
947 | #if !defined(GL_ES_VERSION_2_0) |
948 | // if the view is scaled normal vectors are scaled to unit |
949 | // length for correct displaying of shaded objects |
950 | const gp_Pnt anAxialScale = myCamera->AxialScale(); |
951 | if (anAxialScale.X() != 1.F || |
952 | anAxialScale.Y() != 1.F || |
953 | anAxialScale.Z() != 1.F) |
954 | { |
955 | aContext->SetGlNormalizeEnabled (Standard_True); |
956 | } |
957 | else |
958 | { |
959 | aContext->SetGlNormalizeEnabled (Standard_False); |
960 | } |
961 | |
c357e426 |
962 | // Apply InteriorShadingMethod |
963 | if (aContext->core11 != NULL) |
964 | { |
965 | aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET |
966 | || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH); |
967 | } |
968 | #endif |
969 | |
970 | aManager->SetShadingModel (myShadingModel); |
c357e426 |
971 | |
972 | // Redraw 3d scene |
973 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) |
974 | { |
975 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF()); |
976 | aContext->ApplyProjectionMatrix(); |
977 | } |
978 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) |
979 | { |
980 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF()); |
981 | aContext->ApplyProjectionMatrix(); |
982 | } |
83da37b1 |
983 | |
984 | myWorkspace->SetEnvironmentTexture (myTextureEnv); |
985 | |
a1073ae2 |
986 | renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate); |
c357e426 |
987 | |
cc8cbabe |
988 | myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); |
83da37b1 |
989 | |
c357e426 |
990 | // =============================== |
991 | // Step 4: Trihedron |
992 | // =============================== |
993 | |
994 | // Resetting GL parameters according to the default aspects |
995 | // in order to synchronize GL state with the graphic driver state |
996 | // before drawing auxiliary stuff (trihedrons, overlayer) |
c357e426 |
997 | myWorkspace->ResetAppliedAspect(); |
998 | |
c357e426 |
999 | // Render trihedron |
1000 | if (!theToDrawImmediate) |
1001 | { |
1002 | renderTrihedron (myWorkspace); |
1003 | |
1004 | // Restore face culling |
1005 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
1006 | { |
1007 | if (isCullFace) |
1008 | { |
1009 | glEnable (GL_CULL_FACE); |
1010 | glCullFace (GL_BACK); |
1011 | } |
1012 | else |
1013 | glDisable (GL_CULL_FACE); |
1014 | } |
1015 | } |
1016 | |
8613985b |
1017 | // reset FFP state for safety |
1018 | aContext->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
1019 | if (aContext->caps->ffpEnable) |
1020 | { |
1021 | aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
1022 | } |
8613985b |
1023 | |
c357e426 |
1024 | // ============================================================== |
1025 | // Step 6: Keep shader manager informed about last View |
1026 | // ============================================================== |
1027 | |
1028 | if (!aManager.IsNull()) |
1029 | { |
1030 | aManager->SetLastView (this); |
1031 | } |
1032 | } |
1033 | |
1034 | // ======================================================================= |
1035 | // function : InvalidateBVHData |
1036 | // purpose : |
1037 | // ======================================================================= |
1038 | void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) |
1039 | { |
1040 | myZLayers.InvalidateBVHData (theLayerId); |
1041 | } |
1042 | |
1043 | //======================================================================= |
1044 | //function : renderStructs |
1045 | //purpose : |
1046 | //======================================================================= |
bf02aa7d |
1047 | void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection, |
1048 | OpenGl_FrameBuffer* theReadDrawFbo, |
a1073ae2 |
1049 | OpenGl_FrameBuffer* theOitAccumFbo, |
bf02aa7d |
1050 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1051 | { |
1052 | if ( myZLayers.NbStructures() <= 0 ) |
1053 | return; |
1054 | |
1055 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
c357e426 |
1056 | Standard_Boolean toRenderGL = theToDrawImmediate || |
1057 | myRenderParams.Method != Graphic3d_RM_RAYTRACING || |
1058 | myRaytraceInitStatus == OpenGl_RT_FAIL || |
1059 | aCtx->IsFeedback(); |
1060 | |
1061 | if (!toRenderGL) |
1062 | { |
1063 | toRenderGL = !initRaytraceResources (aCtx) || |
1064 | !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx); |
1065 | |
1066 | toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL |
1067 | |
1068 | if (!toRenderGL) |
1069 | { |
1070 | const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width(); |
1071 | const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height(); |
3c4b62a4 |
1072 | myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0); |
c357e426 |
1073 | |
1074 | if (myRaytraceFilter.IsNull()) |
1075 | myRaytraceFilter = new OpenGl_RaytraceFilter; |
1076 | |
1077 | myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter()); |
1078 | |
1079 | if (theReadDrawFbo != NULL) |
1080 | theReadDrawFbo->UnbindBuffer (aCtx); |
1081 | |
1082 | // Prepare preliminary OpenGL output |
1083 | if (aCtx->arbFBOBlit != NULL) |
1084 | { |
1085 | // Render bottom OSD layer |
a1073ae2 |
1086 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1087 | |
1088 | myWorkspace->SetRenderFilter (myRaytraceFilter); |
1089 | { |
1090 | if (theReadDrawFbo != NULL) |
1091 | { |
3a9b5dc8 |
1092 | theReadDrawFbo->BindDrawBuffer (aCtx); |
c357e426 |
1093 | } |
1094 | else |
1095 | { |
3a9b5dc8 |
1096 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); |
c357e426 |
1097 | } |
1098 | |
c357e426 |
1099 | // Render non-polygonal elements in default layer |
a1073ae2 |
1100 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1101 | } |
1102 | myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter()); |
1103 | } |
1104 | |
1105 | if (theReadDrawFbo != NULL) |
1106 | { |
1107 | theReadDrawFbo->BindBuffer (aCtx); |
1108 | } |
1109 | else |
1110 | { |
1111 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0); |
1112 | } |
1113 | |
f55ba97f |
1114 | // Reset OpenGl aspects state to default to avoid enabling of |
1115 | // backface culling which is not supported in ray-tracing. |
1116 | myWorkspace->ResetAppliedAspect(); |
1117 | |
c357e426 |
1118 | // Ray-tracing polygonal primitive arrays |
bf02aa7d |
1119 | raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx); |
c357e426 |
1120 | |
1121 | // Render upper (top and topmost) OpenGL layers |
a1073ae2 |
1122 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1123 | } |
1124 | } |
1125 | |
1126 | // Redraw 3D scene using OpenGL in standard |
1127 | // mode or in case of ray-tracing failure |
1128 | if (toRenderGL) |
1129 | { |
a1073ae2 |
1130 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1131 | |
1132 | // Set flag that scene was redrawn by standard pipeline |
1133 | myWasRedrawnGL = Standard_True; |
1134 | } |
1135 | } |
1136 | |
1137 | //======================================================================= |
1138 | //function : renderTrihedron |
1139 | //purpose : |
1140 | //======================================================================= |
1141 | void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace) |
1142 | { |
c357e426 |
1143 | if (myToShowGradTrihedron) |
1144 | { |
1145 | myGraduatedTrihedron.Render (theWorkspace); |
1146 | } |
1147 | } |
1148 | |
1149 | // ======================================================================= |
1150 | // function : Invalidate |
1151 | // purpose : |
1152 | // ======================================================================= |
1153 | void OpenGl_View::Invalidate() |
1154 | { |
1155 | myBackBufferRestored = Standard_False; |
1156 | } |
1157 | |
1158 | //======================================================================= |
1159 | //function : renderScene |
1160 | //purpose : |
1161 | //======================================================================= |
bf02aa7d |
1162 | void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, |
1163 | OpenGl_FrameBuffer* theReadDrawFbo, |
a1073ae2 |
1164 | OpenGl_FrameBuffer* theOitAccumFbo, |
bf02aa7d |
1165 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1166 | { |
1167 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
1168 | |
c357e426 |
1169 | // Specify clipping planes in view transformation space |
3202bf1e |
1170 | aContext->ChangeClipping().Reset (aContext, myClipPlanes); |
1171 | if (!myClipPlanes.IsNull() |
1172 | && !myClipPlanes->IsEmpty()) |
c357e426 |
1173 | { |
deb02f86 |
1174 | aContext->ShaderManager()->UpdateClippingState(); |
c357e426 |
1175 | } |
1176 | |
a1073ae2 |
1177 | renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate); |
cc8cbabe |
1178 | aContext->BindTextures (Handle(OpenGl_TextureSet)()); |
c357e426 |
1179 | |
c357e426 |
1180 | // Apply restored view matrix. |
1181 | aContext->ApplyWorldViewMatrix(); |
1182 | |
3202bf1e |
1183 | aContext->ChangeClipping().Reset (aContext, Handle(Graphic3d_SequenceOfHClipPlane)()); |
1184 | if (!myClipPlanes.IsNull() |
1185 | && !myClipPlanes->IsEmpty()) |
deb02f86 |
1186 | { |
1187 | aContext->ShaderManager()->RevertClippingState(); |
deb02f86 |
1188 | } |
c357e426 |
1189 | } |
1190 | |
1191 | // ======================================================================= |
1192 | // function : bindDefaultFbo |
1193 | // purpose : |
1194 | // ======================================================================= |
1195 | void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) |
1196 | { |
1197 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1198 | OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) |
1199 | ? theCustomFbo |
1200 | : (!aCtx->DefaultFrameBuffer().IsNull() |
1201 | && aCtx->DefaultFrameBuffer()->IsValid() |
1202 | ? aCtx->DefaultFrameBuffer().operator->() |
1203 | : NULL); |
1204 | if (anFbo != NULL) |
1205 | { |
1206 | anFbo->BindBuffer (aCtx); |
521b0d7f |
1207 | anFbo->SetupViewport (aCtx); |
c357e426 |
1208 | } |
1209 | else |
1210 | { |
1211 | #if !defined(GL_ES_VERSION_2_0) |
1212 | aCtx->SetReadDrawBuffer (GL_BACK); |
1213 | #else |
1214 | if (aCtx->arbFBO != NULL) |
1215 | { |
1216 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1217 | } |
1218 | #endif |
3bffef55 |
1219 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
1220 | aCtx->ResizeViewport (aViewport); |
c357e426 |
1221 | } |
c357e426 |
1222 | } |
1223 | |
1224 | // ======================================================================= |
1225 | // function : initBlitQuad |
1226 | // purpose : |
1227 | // ======================================================================= |
1228 | OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip) |
1229 | { |
1230 | OpenGl_VertexBuffer* aVerts = NULL; |
1231 | if (!theToFlip) |
1232 | { |
1233 | aVerts = &myFullScreenQuad; |
1234 | if (!aVerts->IsValid()) |
1235 | { |
1236 | OpenGl_Vec4 aQuad[4] = |
1237 | { |
1238 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), |
1239 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), |
1240 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), |
1241 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) |
1242 | }; |
1243 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1244 | } |
1245 | } |
1246 | else |
1247 | { |
1248 | aVerts = &myFullScreenQuadFlip; |
1249 | if (!aVerts->IsValid()) |
1250 | { |
1251 | OpenGl_Vec4 aQuad[4] = |
1252 | { |
1253 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), |
1254 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), |
1255 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), |
1256 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) |
1257 | }; |
1258 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1259 | } |
1260 | } |
1261 | return aVerts; |
1262 | } |
1263 | |
1264 | // ======================================================================= |
1265 | // function : blitBuffers |
1266 | // purpose : |
1267 | // ======================================================================= |
1268 | bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, |
1269 | OpenGl_FrameBuffer* theDrawFbo, |
1270 | const Standard_Boolean theToFlip) |
1271 | { |
1272 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
56689b27 |
1273 | const Standard_Integer aReadSizeX = theReadFbo != NULL ? theReadFbo->GetVPSizeX() : myWindow->Width(); |
1274 | const Standard_Integer aReadSizeY = theReadFbo != NULL ? theReadFbo->GetVPSizeY() : myWindow->Height(); |
1275 | const Standard_Integer aDrawSizeX = theDrawFbo != NULL ? theDrawFbo->GetVPSizeX() : myWindow->Width(); |
1276 | const Standard_Integer aDrawSizeY = theDrawFbo != NULL ? theDrawFbo->GetVPSizeY() : myWindow->Height(); |
c357e426 |
1277 | if (theReadFbo == NULL || aCtx->IsFeedback()) |
1278 | { |
1279 | return false; |
1280 | } |
1281 | else if (theReadFbo == theDrawFbo) |
1282 | { |
1283 | return true; |
1284 | } |
1285 | |
1286 | // clear destination before blitting |
1287 | if (theDrawFbo != NULL |
1288 | && theDrawFbo->IsValid()) |
1289 | { |
1290 | theDrawFbo->BindBuffer (aCtx); |
1291 | } |
1292 | else |
1293 | { |
1294 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1295 | } |
56689b27 |
1296 | const Standard_Integer aViewport[4] = { 0, 0, aDrawSizeX, aDrawSizeY }; |
1297 | aCtx->ResizeViewport (aViewport); |
1298 | |
c357e426 |
1299 | #if !defined(GL_ES_VERSION_2_0) |
1300 | aCtx->core20fwd->glClearDepth (1.0); |
1301 | #else |
1302 | aCtx->core20fwd->glClearDepthf (1.0f); |
1303 | #endif |
1304 | aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
1305 | |
3c4b62a4 |
1306 | if (aCtx->arbFBOBlit != NULL |
1307 | && theReadFbo->NbSamples() != 0) |
c357e426 |
1308 | { |
3c4b62a4 |
1309 | GLbitfield aCopyMask = 0; |
c357e426 |
1310 | theReadFbo->BindReadBuffer (aCtx); |
1311 | if (theDrawFbo != NULL |
1312 | && theDrawFbo->IsValid()) |
1313 | { |
1314 | theDrawFbo->BindDrawBuffer (aCtx); |
3c4b62a4 |
1315 | if (theDrawFbo->HasColor() |
1316 | && theReadFbo->HasColor()) |
1317 | { |
1318 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1319 | } |
1320 | if (theDrawFbo->HasDepth() |
1321 | && theReadFbo->HasDepth()) |
1322 | { |
1323 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1324 | } |
c357e426 |
1325 | } |
1326 | else |
1327 | { |
3c4b62a4 |
1328 | if (theReadFbo->HasColor()) |
1329 | { |
1330 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1331 | } |
1332 | if (theReadFbo->HasDepth()) |
1333 | { |
1334 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1335 | } |
c357e426 |
1336 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1337 | } |
3c4b62a4 |
1338 | |
c357e426 |
1339 | // we don't copy stencil buffer here... does it matter for performance? |
56689b27 |
1340 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aReadSizeX, aReadSizeY, |
1341 | 0, 0, aDrawSizeX, aDrawSizeY, |
3c4b62a4 |
1342 | aCopyMask, GL_NEAREST); |
7ccf8676 |
1343 | const int anErr = ::glGetError(); |
1344 | if (anErr != GL_NO_ERROR) |
1345 | { |
1346 | // glBlitFramebuffer() might fail in several cases: |
1347 | // - Both FBOs have MSAA and they are samples number does not match. |
1348 | // OCCT checks that this does not happen, |
1349 | // however some graphics drivers provide an option for overriding MSAA. |
1350 | // In this case window MSAA might be non-zero (and application can not check it) |
1351 | // and might not match MSAA of our offscreen FBOs. |
1352 | // - Pixel formats of FBOs do not match. |
1353 | // This also might happen with window has pixel format, |
1354 | // e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion. |
1355 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error #" + anErr + "]\n" |
1356 | + " Please check your graphics driver settings or try updating driver."; |
1357 | if (theReadFbo->NbSamples() != 0) |
1358 | { |
1359 | myToDisableMSAA = true; |
1360 | aMsg += "\n MSAA settings should not be overridden by driver!"; |
1361 | } |
1362 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1363 | GL_DEBUG_TYPE_ERROR, |
1364 | 0, |
1365 | GL_DEBUG_SEVERITY_HIGH, |
1366 | aMsg); |
1367 | } |
1368 | |
c357e426 |
1369 | if (theDrawFbo != NULL |
3c4b62a4 |
1370 | && theDrawFbo->IsValid()) |
c357e426 |
1371 | { |
1372 | theDrawFbo->BindBuffer (aCtx); |
1373 | } |
1374 | else |
1375 | { |
1376 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1377 | } |
1378 | } |
1379 | else |
c357e426 |
1380 | { |
1381 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1382 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1383 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1ce0716b |
1384 | #if defined(GL_ES_VERSION_2_0) |
1385 | if (!aCtx->IsGlGreaterEqual (3, 0) |
1386 | && !aCtx->extFragDepth) |
1387 | { |
1388 | aCtx->core20fwd->glDisable (GL_DEPTH_TEST); |
1389 | } |
1390 | #endif |
c357e426 |
1391 | |
cc8cbabe |
1392 | aCtx->BindTextures (Handle(OpenGl_TextureSet)()); |
c357e426 |
1393 | |
56689b27 |
1394 | const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR; |
1395 | const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR; |
1396 | |
c357e426 |
1397 | OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); |
1398 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1399 | if (aVerts->IsValid() |
1400 | && aManager->BindFboBlitProgram()) |
1401 | { |
cc8cbabe |
1402 | theReadFbo->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); |
1403 | if (theReadFbo->ColorTexture()->Sampler()->Parameters()->Filter() != aFilter) |
56689b27 |
1404 | { |
cc8cbabe |
1405 | theReadFbo->ColorTexture()->Sampler()->Parameters()->SetFilter (aFilter); |
56689b27 |
1406 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); |
1407 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); |
1408 | } |
1409 | |
cc8cbabe |
1410 | theReadFbo->DepthStencilTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); |
1411 | if (theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->Filter() != aFilter) |
56689b27 |
1412 | { |
cc8cbabe |
1413 | theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->SetFilter (aFilter); |
56689b27 |
1414 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); |
1415 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); |
1416 | } |
1417 | |
c357e426 |
1418 | aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1419 | |
1420 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1421 | |
1422 | aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
cc8cbabe |
1423 | theReadFbo->DepthStencilTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); |
1424 | theReadFbo->ColorTexture() ->Unbind (aCtx, Graphic3d_TextureUnit_0); |
a521d90d |
1425 | aCtx->BindProgram (NULL); |
c357e426 |
1426 | } |
1427 | else |
1428 | { |
1429 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1430 | + "Error! FBO blitting has failed"; |
3b523c4c |
1431 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1432 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1433 | 0, |
3b523c4c |
1434 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1435 | aMsg); |
1436 | myHasFboBlit = Standard_False; |
1437 | theReadFbo->Release (aCtx.operator->()); |
1438 | return true; |
1439 | } |
1440 | } |
1441 | return true; |
1442 | } |
1443 | |
1444 | // ======================================================================= |
1445 | // function : drawStereoPair |
1446 | // purpose : |
1447 | // ======================================================================= |
3c4b62a4 |
1448 | void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) |
c357e426 |
1449 | { |
3c4b62a4 |
1450 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1451 | bindDefaultFbo (theDrawFbo); |
c357e426 |
1452 | OpenGl_FrameBuffer* aPair[2] = |
1453 | { |
1454 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
1455 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
1456 | }; |
1457 | if (aPair[0] == NULL |
1458 | || aPair[1] == NULL |
1459 | || !myTransientDrawToFront) |
1460 | { |
1461 | aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
1462 | aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; |
1463 | } |
1464 | |
1465 | if (aPair[0] == NULL |
1466 | || aPair[1] == NULL) |
1467 | { |
1468 | return; |
1469 | } |
1470 | |
3c4b62a4 |
1471 | if (aPair[0]->NbSamples() != 0) |
1472 | { |
1473 | // resolve MSAA buffers before drawing |
1474 | if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0) |
1475 | || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0)) |
1476 | { |
82f443b6 |
1477 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1478 | GL_DEBUG_TYPE_ERROR, |
3c4b62a4 |
1479 | 0, |
82f443b6 |
1480 | GL_DEBUG_SEVERITY_HIGH, |
3c4b62a4 |
1481 | "Error! Unable to allocate FBO for blitting stereo pair"); |
1482 | bindDefaultFbo (theDrawFbo); |
1483 | return; |
1484 | } |
1485 | |
1486 | if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False) |
1487 | || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False)) |
1488 | { |
1489 | bindDefaultFbo (theDrawFbo); |
1490 | return; |
1491 | } |
1492 | |
1493 | aPair[0] = myOpenGlFBO .operator->(); |
1494 | aPair[1] = myOpenGlFBO2.operator->(); |
1495 | bindDefaultFbo (theDrawFbo); |
1496 | } |
1497 | |
c357e426 |
1498 | struct |
1499 | { |
1500 | Standard_Integer left; |
1501 | Standard_Integer top; |
1502 | Standard_Integer right; |
1503 | Standard_Integer bottom; |
1504 | Standard_Integer dx() { return right - left; } |
1505 | Standard_Integer dy() { return bottom - top; } |
1506 | } aGeom; |
1507 | |
1508 | myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom); |
1509 | |
1510 | Standard_Boolean toReverse = myRenderParams.ToReverseStereo; |
1511 | const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1; |
1512 | const Standard_Boolean isOddX = aGeom.left % 2 == 1; |
1513 | if (isOddY |
1514 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced |
1515 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1516 | { |
1517 | toReverse = !toReverse; |
1518 | } |
1519 | if (isOddX |
1520 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced |
1521 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1522 | { |
1523 | toReverse = !toReverse; |
1524 | } |
1525 | |
1526 | if (toReverse) |
1527 | { |
1528 | std::swap (aPair[0], aPair[1]); |
1529 | } |
1530 | |
c357e426 |
1531 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1532 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1533 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1534 | |
cc8cbabe |
1535 | aCtx->BindTextures (Handle(OpenGl_TextureSet)()); |
c357e426 |
1536 | OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); |
1537 | |
1538 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1539 | if (aVerts->IsValid() |
1540 | && aManager->BindStereoProgram (myRenderParams.StereoMode)) |
1541 | { |
1542 | if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) |
1543 | { |
1544 | OpenGl_Mat4 aFilterL, aFilterR; |
1545 | aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1546 | aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1547 | switch (myRenderParams.AnaglyphFilter) |
1548 | { |
1549 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: |
1550 | { |
1551 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1552 | aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1553 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1554 | break; |
1555 | } |
1556 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: |
1557 | { |
1558 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); |
1559 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); |
1560 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); |
1561 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1562 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); |
1563 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); |
1564 | aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); |
1565 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1566 | break; |
1567 | } |
1568 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: |
1569 | { |
1570 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1571 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1572 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1573 | break; |
1574 | } |
1575 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: |
1576 | { |
1577 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); |
1578 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); |
1579 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); |
1580 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1581 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); |
1582 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); |
1583 | aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); |
1584 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1585 | break; |
1586 | } |
1587 | case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: |
1588 | { |
1589 | aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1590 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1591 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1592 | break; |
1593 | } |
1594 | case Graphic3d_RenderingParams::Anaglyph_UserDefined: |
1595 | { |
1596 | aFilterL = myRenderParams.AnaglyphLeft; |
1597 | aFilterR = myRenderParams.AnaglyphRight; |
1598 | break; |
1599 | } |
1600 | } |
1601 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL); |
1602 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR); |
1603 | } |
1604 | |
cc8cbabe |
1605 | aPair[0]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); |
1606 | aPair[1]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); |
c357e426 |
1607 | aVerts->BindVertexAttrib (aCtx, 0); |
1608 | |
1609 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1610 | |
1611 | aVerts->UnbindVertexAttrib (aCtx, 0); |
cc8cbabe |
1612 | aPair[1]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); |
1613 | aPair[0]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_0); |
c357e426 |
1614 | } |
1615 | else |
1616 | { |
1617 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1618 | + "Error! Anaglyph has failed"; |
3b523c4c |
1619 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1620 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1621 | 0, |
3b523c4c |
1622 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1623 | aMsg); |
1624 | } |
1625 | } |
1626 | |
1627 | // ======================================================================= |
1628 | // function : copyBackToFront |
1629 | // purpose : |
1630 | // ======================================================================= |
a0b49de4 |
1631 | bool OpenGl_View::copyBackToFront() |
c357e426 |
1632 | { |
a0b49de4 |
1633 | myIsImmediateDrawn = Standard_False; |
c357e426 |
1634 | #if !defined(GL_ES_VERSION_2_0) |
a0b49de4 |
1635 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1636 | if (aCtx->core11 == NULL) |
1637 | { |
1638 | return false; |
1639 | } |
c357e426 |
1640 | |
1641 | OpenGl_Mat4 aProjectMat; |
1642 | Graphic3d_TransformUtils::Ortho2D (aProjectMat, |
8613985b |
1643 | 0.0f, static_cast<GLfloat> (myWindow->Width()), |
1644 | 0.0f, static_cast<GLfloat> (myWindow->Height())); |
1645 | |
c357e426 |
1646 | aCtx->WorldViewState.Push(); |
1647 | aCtx->ProjectionState.Push(); |
1648 | |
1649 | aCtx->WorldViewState.SetIdentity(); |
1650 | aCtx->ProjectionState.SetCurrent (aProjectMat); |
1651 | |
1652 | aCtx->ApplyProjectionMatrix(); |
1653 | aCtx->ApplyWorldViewMatrix(); |
1654 | |
8613985b |
1655 | // synchronize FFP state before copying pixels |
1656 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
1657 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
c357e426 |
1658 | aCtx->DisableFeatures(); |
1659 | |
1660 | switch (aCtx->DrawBuffer()) |
1661 | { |
1662 | case GL_BACK_LEFT: |
1663 | { |
1664 | aCtx->SetReadBuffer (GL_BACK_LEFT); |
1665 | aCtx->SetDrawBuffer (GL_FRONT_LEFT); |
1666 | break; |
1667 | } |
1668 | case GL_BACK_RIGHT: |
1669 | { |
1670 | aCtx->SetReadBuffer (GL_BACK_RIGHT); |
1671 | aCtx->SetDrawBuffer (GL_FRONT_RIGHT); |
1672 | break; |
1673 | } |
1674 | default: |
1675 | { |
1676 | aCtx->SetReadBuffer (GL_BACK); |
1677 | aCtx->SetDrawBuffer (GL_FRONT); |
1678 | break; |
1679 | } |
1680 | } |
1681 | |
a0b49de4 |
1682 | aCtx->core11->glRasterPos2i (0, 0); |
1683 | aCtx->core11->glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR); |
1684 | //aCtx->core11->glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); |
c357e426 |
1685 | |
1686 | aCtx->EnableFeatures(); |
1687 | |
1688 | aCtx->WorldViewState.Pop(); |
1689 | aCtx->ProjectionState.Pop(); |
1690 | aCtx->ApplyProjectionMatrix(); |
1691 | |
1692 | // read/write from front buffer now |
1693 | aCtx->SetReadBuffer (aCtx->DrawBuffer()); |
a0b49de4 |
1694 | return true; |
1695 | #else |
1696 | return false; |
c357e426 |
1697 | #endif |
c357e426 |
1698 | } |
a1073ae2 |
1699 | |
1700 | // ======================================================================= |
1701 | // function : checkOitCompatibility |
1702 | // purpose : |
1703 | // ======================================================================= |
1704 | Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext, |
1705 | const Standard_Boolean theMSAA) |
1706 | { |
1707 | // determine if OIT is supported by current OpenGl context |
1708 | Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT; |
1709 | if (aToDisableOIT) |
1710 | { |
1711 | return Standard_False; |
1712 | } |
1713 | |
1714 | TCollection_ExtendedString aCompatibilityMsg; |
177781da |
1715 | if (theGlContext->hasFloatBuffer == OpenGl_FeatureNotAvailable |
1716 | && theGlContext->hasHalfFloatBuffer == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1717 | { |
1718 | aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n"; |
1719 | } |
177781da |
1720 | if (theMSAA && theGlContext->hasSampleVariables == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1721 | { |
1722 | aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n"; |
1723 | } |
177781da |
1724 | if (theGlContext->hasDrawBuffers == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1725 | { |
1726 | aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n"; |
1727 | } |
1728 | if (aCompatibilityMsg.IsEmpty()) |
1729 | { |
1730 | return Standard_True; |
1731 | } |
1732 | |
1733 | aCompatibilityMsg += " Blended order-independent transparency will not be available.\n"; |
1734 | theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1735 | GL_DEBUG_TYPE_ERROR, |
1736 | 0, |
1737 | GL_DEBUG_SEVERITY_HIGH, |
1738 | aCompatibilityMsg); |
1739 | |
1740 | aToDisableOIT = Standard_True; |
1741 | return Standard_False; |
1742 | } |
1743 | |
1744 | // ======================================================================= |
1745 | // function : chooseOitColorConfiguration |
1746 | // purpose : |
1747 | // ======================================================================= |
1748 | bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext, |
1749 | const Standard_Integer theConfigIndex, |
1750 | OpenGl_ColorFormats& theFormats) |
1751 | { |
1752 | theFormats.Clear(); |
1753 | switch (theConfigIndex) |
1754 | { |
1755 | case 0: // choose best applicable color format combination |
1756 | { |
177781da |
1757 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
1758 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_R16F : GL_R32F); |
a1073ae2 |
1759 | return true; |
1760 | } |
1761 | case 1: // choose non-optimal applicable color format combination |
1762 | { |
177781da |
1763 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
1764 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
a1073ae2 |
1765 | return true; |
1766 | } |
1767 | } |
1768 | return false; // color combination does not exist |
1769 | } |