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> |
20 | #include <OpenGl_tgl_funcs.hxx> |
21 | |
22 | #include <Graphic3d_GraphicDriver.hxx> |
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> |
35 | #include <OpenGl_Trihedron.hxx> |
36 | #include <OpenGl_GraduatedTrihedron.hxx> |
37 | #include <OpenGl_PrimitiveArray.hxx> |
38 | #include <OpenGl_PrinterContext.hxx> |
39 | #include <OpenGl_ShaderManager.hxx> |
40 | #include <OpenGl_ShaderProgram.hxx> |
41 | #include <OpenGl_Structure.hxx> |
42 | #include <OpenGl_ArbFBO.hxx> |
43 | |
44 | #define EPSI 0.0001 |
45 | |
46 | namespace |
47 | { |
48 | static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; |
49 | static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f }; |
50 | static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f; |
51 | static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f; |
52 | } |
53 | |
54 | extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx |
55 | |
56 | #if !defined(GL_ES_VERSION_2_0) |
57 | |
58 | //======================================================================= |
59 | //function : bindLight |
60 | //purpose : |
61 | //======================================================================= |
62 | static void bindLight (const OpenGl_Light& theLight, |
63 | GLenum& theLightGlId, |
64 | Graphic3d_Vec4& theAmbientColor, |
65 | const Handle(OpenGl_Workspace)& theWorkspace) |
66 | { |
67 | // Only 8 lights in OpenGL... |
68 | if (theLightGlId > GL_LIGHT7) |
69 | { |
70 | return; |
71 | } |
72 | |
73 | if (theLight.Type == Graphic3d_TOLS_AMBIENT) |
74 | { |
75 | // add RGBA intensity of the ambient light |
76 | theAmbientColor += theLight.Color; |
77 | return; |
78 | } |
79 | |
80 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
81 | |
82 | // the light is a headlight? |
83 | if (theLight.IsHeadlight) |
84 | { |
85 | aContext->WorldViewState.Push(); |
86 | aContext->WorldViewState.SetIdentity(); |
87 | |
88 | aContext->ApplyWorldViewMatrix(); |
89 | } |
90 | |
91 | // setup light type |
92 | switch (theLight.Type) |
93 | { |
94 | case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method |
95 | case Graphic3d_TOLS_DIRECTIONAL: |
96 | { |
97 | // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one |
98 | const OpenGl_Vec4 anInfDir = -theLight.Direction; |
99 | |
100 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE. |
101 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
102 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
103 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
104 | glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData()); |
105 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
106 | glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
107 | glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
108 | break; |
109 | } |
110 | case Graphic3d_TOLS_POSITIONAL: |
111 | { |
112 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE |
113 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
114 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
115 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
116 | glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData()); |
117 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
118 | glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
119 | glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
120 | glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
121 | glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
122 | glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0); |
123 | break; |
124 | } |
125 | case Graphic3d_TOLS_SPOT: |
126 | { |
127 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
128 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
129 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
130 | glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData()); |
131 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.Direction.GetData()); |
132 | glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f); |
133 | glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI)); |
134 | glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
135 | glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
136 | glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f); |
137 | break; |
138 | } |
139 | } |
140 | |
141 | // restore matrix in case of headlight |
142 | if (theLight.IsHeadlight) |
143 | { |
144 | aContext->WorldViewState.Pop(); |
145 | } |
146 | |
147 | glEnable (theLightGlId++); |
148 | } |
149 | #endif |
150 | |
151 | //======================================================================= |
a521d90d |
152 | //function : drawBackground |
c357e426 |
153 | //purpose : |
154 | //======================================================================= |
a521d90d |
155 | void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) |
c357e426 |
156 | { |
157 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
158 | |
159 | if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background |
160 | || (!myBgTextureArray->IsDefined() // no texture |
161 | && !myBgGradientArray->IsDefined())) // no gradient |
162 | { |
163 | return; |
164 | } |
165 | |
166 | const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False); |
167 | if (wasUsedZBuffer) |
168 | { |
169 | aCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
170 | } |
171 | |
172 | aCtx->ProjectionState.Push(); |
173 | aCtx->WorldViewState.Push(); |
174 | aCtx->ModelWorldState.Push(); |
175 | aCtx->ProjectionState.SetIdentity(); |
176 | aCtx->WorldViewState.SetIdentity(); |
177 | aCtx->ModelWorldState.SetIdentity(); |
178 | aCtx->ApplyProjectionMatrix(); |
179 | aCtx->ApplyModelViewMatrix(); |
180 | |
181 | // Drawing background gradient if: |
182 | // - gradient fill type is not Aspect_GFM_NONE and |
183 | // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode |
184 | if (myBgGradientArray->IsDefined() |
185 | && (!myTextureParams->DoTextureMap() |
186 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED |
187 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE)) |
188 | { |
189 | #if !defined(GL_ES_VERSION_2_0) |
190 | GLint aShadingModelOld = GL_SMOOTH; |
191 | if (aCtx->core11 != NULL) |
192 | { |
193 | aCtx->core11fwd->glDisable (GL_LIGHTING); |
194 | aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld); |
195 | aCtx->core11->glShadeModel (GL_SMOOTH); |
196 | } |
197 | #endif |
198 | |
199 | if (myBgGradientArray->IsDataChanged()) |
200 | { |
201 | myBgGradientArray->Init (theWorkspace); |
202 | } |
203 | |
204 | myBgGradientArray->Render (theWorkspace); |
205 | |
206 | #if !defined(GL_ES_VERSION_2_0) |
207 | if (aCtx->core11 != NULL) |
208 | { |
209 | aCtx->core11->glShadeModel (aShadingModelOld); |
210 | } |
211 | #endif |
212 | } |
213 | |
214 | // Drawing background image if it is defined |
215 | // (texture is defined and fill type is not Aspect_FM_NONE) |
216 | if (myBgTextureArray->IsDefined() |
217 | && myTextureParams->DoTextureMap()) |
218 | { |
219 | aCtx->core11fwd->glDisable (GL_BLEND); |
220 | |
221 | const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams); |
222 | |
223 | if (myBgTextureArray->IsDataChanged() |
224 | || myBgTextureArray->IsViewSizeChanged (theWorkspace)) |
225 | { |
226 | myBgTextureArray->Init (theWorkspace); |
227 | } |
228 | |
229 | myBgTextureArray->Render (theWorkspace); |
230 | |
231 | // restore aspects |
232 | theWorkspace->SetAspectFace (anOldAspectFace); |
233 | } |
234 | |
235 | aCtx->ModelWorldState.Pop(); |
236 | aCtx->WorldViewState.Pop(); |
237 | aCtx->ProjectionState.Pop(); |
238 | aCtx->ApplyProjectionMatrix(); |
239 | aCtx->ApplyModelViewMatrix(); |
240 | |
241 | if (wasUsedZBuffer) |
242 | { |
243 | theWorkspace->SetUseZBuffer (Standard_True); |
244 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); |
245 | } |
246 | } |
247 | |
248 | //======================================================================= |
249 | //function : Redraw |
250 | //purpose : |
251 | //======================================================================= |
252 | void OpenGl_View::Redraw() |
253 | { |
254 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
255 | && !myCaps->vboDisable |
256 | && !myCaps->keepArrayData) |
257 | { |
258 | if (myWasRedrawnGL) |
259 | { |
260 | myDeviceLostFlag = Standard_True; |
261 | } |
262 | |
263 | myCaps->keepArrayData = Standard_True; |
264 | } |
265 | |
266 | if (!myWorkspace->Activate()) |
267 | { |
268 | return; |
269 | } |
270 | |
271 | myWindow->SetSwapInterval(); |
272 | |
273 | ++myFrameCounter; |
274 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
275 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
276 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
277 | |
278 | // release pending GL resources |
279 | aCtx->ReleaseDelayed(); |
280 | |
281 | // fetch OpenGl context state |
282 | aCtx->FetchState(); |
283 | |
75c262a9 |
284 | // set resolution ratio |
285 | aCtx->SetResolutionRatio (RenderingParams().ResolutionRatio()); |
286 | |
c357e426 |
287 | OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )myFBO; |
288 | bool toSwap = aCtx->IsRender() |
289 | && !aCtx->caps->buffersNoSwap |
290 | && aFrameBuffer == NULL; |
291 | |
292 | Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width(); |
293 | Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height(); |
294 | |
3c4b62a4 |
295 | // determine multisampling parameters |
296 | Standard_Integer aNbSamples = Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0); |
297 | if (aNbSamples != 0) |
298 | { |
299 | aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); |
300 | } |
301 | |
c357e426 |
302 | if ( aFrameBuffer == NULL |
303 | && !aCtx->DefaultFrameBuffer().IsNull() |
304 | && aCtx->DefaultFrameBuffer()->IsValid()) |
305 | { |
306 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
307 | } |
308 | |
309 | if (myHasFboBlit |
3c4b62a4 |
310 | && (myTransientDrawToFront |
311 | || aProjectType == Graphic3d_Camera::Projection_Stereo |
312 | || aNbSamples != 0)) |
c357e426 |
313 | { |
314 | if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX |
3c4b62a4 |
315 | || myMainSceneFbos[0]->GetVPSizeY() != aSizeY |
316 | || myMainSceneFbos[0]->NbSamples() != aNbSamples) |
c357e426 |
317 | { |
318 | // prepare FBOs containing main scene |
319 | // for further blitting and rendering immediate presentations on top |
320 | if (aCtx->core20fwd != NULL) |
321 | { |
3c4b62a4 |
322 | myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples); |
c357e426 |
323 | } |
324 | if (!aCtx->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid()) |
325 | { |
3c4b62a4 |
326 | myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
327 | } |
328 | } |
329 | } |
330 | else |
331 | { |
332 | myMainSceneFbos [0]->Release (aCtx.operator->()); |
333 | myMainSceneFbos [1]->Release (aCtx.operator->()); |
334 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
335 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
336 | myMainSceneFbos [0]->ChangeViewport (0, 0); |
337 | myMainSceneFbos [1]->ChangeViewport (0, 0); |
338 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
339 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
340 | } |
341 | |
342 | if (aProjectType == Graphic3d_Camera::Projection_Stereo |
343 | && myMainSceneFbos[0]->IsValid()) |
344 | { |
3c4b62a4 |
345 | myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
346 | if (!myMainSceneFbos[1]->IsValid()) |
347 | { |
348 | // no enough memory? |
349 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
350 | } |
351 | else if (!myTransientDrawToFront) |
352 | { |
353 | // |
354 | } |
355 | else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer) |
356 | { |
3c4b62a4 |
357 | myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]); |
358 | myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
359 | if (!myImmediateSceneFbos[0]->IsValid() |
360 | || !myImmediateSceneFbos[1]->IsValid()) |
361 | { |
362 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
363 | } |
364 | } |
365 | } |
366 | |
367 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
368 | { |
369 | OpenGl_FrameBuffer* aMainFbos[2] = |
370 | { |
371 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
372 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
373 | }; |
374 | OpenGl_FrameBuffer* anImmFbos[2] = |
375 | { |
376 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
377 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
378 | }; |
379 | |
380 | if (!myTransientDrawToFront) |
381 | { |
382 | anImmFbos[0] = aMainFbos[0]; |
383 | anImmFbos[1] = aMainFbos[1]; |
384 | } |
385 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
386 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
387 | { |
388 | anImmFbos[0] = NULL; |
389 | anImmFbos[1] = NULL; |
390 | } |
391 | |
392 | #if !defined(GL_ES_VERSION_2_0) |
393 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
394 | #endif |
395 | redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]); |
396 | myBackBufferRestored = Standard_True; |
397 | myIsImmediateDrawn = Standard_False; |
398 | #if !defined(GL_ES_VERSION_2_0) |
399 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
400 | #endif |
b0dc79bc |
401 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0])) |
c357e426 |
402 | { |
403 | toSwap = false; |
404 | } |
405 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) |
406 | { |
407 | aCtx->SwapBuffers(); |
408 | } |
409 | |
410 | #if !defined(GL_ES_VERSION_2_0) |
411 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
412 | #endif |
413 | redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]); |
414 | myBackBufferRestored = Standard_True; |
415 | myIsImmediateDrawn = Standard_False; |
b0dc79bc |
416 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1])) |
c357e426 |
417 | { |
418 | toSwap = false; |
419 | } |
420 | |
421 | if (anImmFbos[0] != NULL) |
422 | { |
3c4b62a4 |
423 | drawStereoPair (aFrameBuffer); |
c357e426 |
424 | } |
425 | } |
426 | else |
427 | { |
428 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
429 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
430 | if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) |
431 | { |
432 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
433 | } |
434 | |
435 | #if !defined(GL_ES_VERSION_2_0) |
436 | if (aMainFbo == NULL |
437 | && aFrameBuffer == NULL) |
438 | { |
439 | aCtx->SetReadDrawBuffer (GL_BACK); |
440 | } |
441 | #endif |
442 | redraw (aProjectType, aMainFbo != NULL ? aMainFbo : aFrameBuffer); |
443 | myBackBufferRestored = Standard_True; |
444 | myIsImmediateDrawn = Standard_False; |
445 | if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo)) |
446 | { |
447 | toSwap = false; |
448 | } |
449 | |
450 | if (anImmFbo != NULL |
451 | && anImmFbo != aFrameBuffer) |
452 | { |
453 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
454 | } |
455 | } |
456 | |
457 | #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) |
458 | if (OpenGl_AVIWriter_AllowWriting (myWindow->PlatformWindow()->NativeHandle())) |
459 | { |
460 | GLint params[4]; |
461 | glGetIntegerv (GL_VIEWPORT, params); |
462 | int nWidth = params[2] & ~0x7; |
463 | int nHeight = params[3] & ~0x7; |
464 | |
465 | const int nBitsPerPixel = 24; |
466 | GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8]; |
467 | |
468 | glPixelStorei (GL_PACK_ALIGNMENT, 1); |
469 | glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData); |
470 | OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel); |
471 | delete[] aDumpData; |
472 | } |
473 | #endif |
474 | |
bf02aa7d |
475 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
476 | && myRenderParams.IsGlobalIlluminationEnabled) |
477 | { |
478 | myAccumFrames++; |
479 | } |
480 | |
c357e426 |
481 | // bind default FBO |
482 | bindDefaultFbo(); |
483 | |
484 | // Swap the buffers |
485 | if (toSwap) |
486 | { |
487 | aCtx->SwapBuffers(); |
488 | if (!myMainSceneFbos[0]->IsValid()) |
489 | { |
490 | myBackBufferRestored = Standard_False; |
491 | } |
492 | } |
493 | else |
494 | { |
495 | aCtx->core11fwd->glFlush(); |
496 | } |
497 | |
498 | // reset render mode state |
499 | aCtx->FetchState(); |
500 | |
501 | myWasRedrawnGL = Standard_True; |
502 | } |
503 | |
504 | // ======================================================================= |
505 | // function : RedrawImmediate |
506 | // purpose : |
507 | // ======================================================================= |
508 | void OpenGl_View::RedrawImmediate() |
509 | { |
510 | if (!myWorkspace->Activate()) |
511 | return; |
512 | |
513 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
514 | if (!myTransientDrawToFront |
515 | || !myBackBufferRestored |
516 | || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) |
517 | { |
518 | Redraw(); |
519 | return; |
520 | } |
521 | |
522 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
523 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
524 | OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )myFBO; |
525 | |
526 | if ( aFrameBuffer == NULL |
527 | && !aCtx->DefaultFrameBuffer().IsNull() |
528 | && aCtx->DefaultFrameBuffer()->IsValid()) |
529 | { |
530 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
531 | } |
532 | |
533 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
534 | { |
535 | if (myMainSceneFbos[0]->IsValid() |
536 | && !myMainSceneFbos[1]->IsValid()) |
537 | { |
538 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
539 | } |
540 | } |
541 | |
542 | bool toSwap = false; |
543 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
544 | { |
545 | OpenGl_FrameBuffer* aMainFbos[2] = |
546 | { |
547 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
548 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
549 | }; |
550 | OpenGl_FrameBuffer* anImmFbos[2] = |
551 | { |
552 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
553 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
554 | }; |
555 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
556 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
557 | { |
558 | anImmFbos[0] = NULL; |
559 | anImmFbos[1] = NULL; |
560 | } |
561 | |
562 | if (aCtx->arbFBO != NULL) |
563 | { |
564 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
565 | } |
566 | #if !defined(GL_ES_VERSION_2_0) |
567 | if (anImmFbos[0] == NULL) |
568 | { |
569 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
570 | } |
571 | #endif |
572 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, |
573 | aMainFbos[0], |
574 | anImmFbos[0], |
575 | Standard_True) || toSwap; |
576 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
577 | && toSwap |
578 | && !aCtx->caps->buffersNoSwap) |
579 | { |
580 | aCtx->SwapBuffers(); |
581 | } |
582 | |
583 | if (aCtx->arbFBO != NULL) |
584 | { |
585 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
586 | } |
587 | #if !defined(GL_ES_VERSION_2_0) |
588 | if (anImmFbos[1] == NULL) |
589 | { |
590 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
591 | } |
592 | #endif |
593 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, |
594 | aMainFbos[1], |
595 | anImmFbos[1], |
596 | Standard_True) || toSwap; |
597 | if (anImmFbos[0] != NULL) |
598 | { |
3c4b62a4 |
599 | drawStereoPair (aFrameBuffer); |
c357e426 |
600 | } |
601 | } |
602 | else |
603 | { |
604 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
605 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
606 | if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) |
607 | { |
608 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
609 | } |
610 | #if !defined(GL_ES_VERSION_2_0) |
611 | if (aMainFbo == NULL) |
612 | { |
613 | aCtx->SetReadDrawBuffer (GL_BACK); |
614 | } |
615 | #endif |
616 | toSwap = redrawImmediate (aProjectType, |
617 | aMainFbo, |
618 | anImmFbo, |
619 | Standard_True) || toSwap; |
620 | if (anImmFbo != NULL |
621 | && anImmFbo != aFrameBuffer) |
622 | { |
623 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
624 | } |
625 | } |
626 | |
627 | // bind default FBO |
628 | bindDefaultFbo(); |
629 | |
630 | if (toSwap && !aCtx->caps->buffersNoSwap) |
631 | { |
632 | aCtx->SwapBuffers(); |
633 | } |
634 | else |
635 | { |
636 | aCtx->core11fwd->glFlush(); |
637 | } |
638 | |
639 | myWasRedrawnGL = Standard_True; |
640 | } |
641 | |
642 | // ======================================================================= |
643 | // function : redraw |
644 | // purpose : |
645 | // ======================================================================= |
646 | void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo) |
647 | { |
648 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
649 | if (theReadDrawFbo != NULL) |
650 | { |
651 | theReadDrawFbo->BindBuffer (aCtx); |
652 | theReadDrawFbo->SetupViewport (aCtx); |
653 | } |
654 | else |
655 | { |
656 | aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height()); |
657 | } |
658 | |
659 | // request reset of material |
660 | myWorkspace->NamedStatus |= OPENGL_NS_RESMAT; |
661 | myWorkspace->UseZBuffer() = Standard_True; |
662 | myWorkspace->UseDepthWrite() = Standard_True; |
663 | GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; |
664 | glDepthFunc (GL_LEQUAL); |
665 | glDepthMask (GL_TRUE); |
666 | glEnable (GL_DEPTH_TEST); |
667 | |
668 | #if !defined(GL_ES_VERSION_2_0) |
669 | glClearDepth (1.0); |
670 | #else |
671 | glClearDepthf (1.0f); |
672 | #endif |
673 | |
674 | if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) |
675 | { |
676 | // set background to white |
677 | glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
678 | } |
679 | else |
680 | { |
681 | glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f); |
682 | } |
683 | |
684 | glClear (toClear); |
685 | |
686 | render (theProjection, theReadDrawFbo, Standard_False); |
687 | } |
688 | |
689 | // ======================================================================= |
690 | // function : redrawMonoImmediate |
691 | // purpose : |
692 | // ======================================================================= |
693 | bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, |
694 | OpenGl_FrameBuffer* theReadFbo, |
695 | OpenGl_FrameBuffer* theDrawFbo, |
696 | const Standard_Boolean theIsPartialUpdate) |
697 | { |
698 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
699 | GLboolean toCopyBackToFront = GL_FALSE; |
700 | if (!myTransientDrawToFront) |
701 | { |
702 | myBackBufferRestored = Standard_False; |
703 | } |
704 | else if (theReadFbo != NULL |
705 | && theReadFbo->IsValid() |
706 | && aCtx->IsRender()) |
707 | { |
708 | if (!blitBuffers (theReadFbo, theDrawFbo)) |
709 | { |
710 | return true; |
711 | } |
712 | } |
713 | else if (theDrawFbo == NULL) |
714 | { |
715 | #if !defined(GL_ES_VERSION_2_0) |
716 | aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); |
717 | #endif |
718 | if (toCopyBackToFront) |
719 | { |
720 | if (!HasImmediateStructures() |
721 | && !theIsPartialUpdate) |
722 | { |
723 | // prefer Swap Buffers within Redraw in compatibility mode (without FBO) |
724 | return true; |
725 | } |
726 | copyBackToFront(); |
727 | } |
728 | else |
729 | { |
730 | myBackBufferRestored = Standard_False; |
731 | } |
732 | } |
733 | else |
734 | { |
735 | myBackBufferRestored = Standard_False; |
736 | } |
737 | myIsImmediateDrawn = Standard_True; |
738 | |
739 | myWorkspace->UseZBuffer() = Standard_True; |
740 | myWorkspace->UseDepthWrite() = Standard_True; |
741 | glDepthFunc (GL_LEQUAL); |
742 | glDepthMask (GL_TRUE); |
743 | glEnable (GL_DEPTH_TEST); |
744 | #if !defined(GL_ES_VERSION_2_0) |
745 | glClearDepth (1.0); |
746 | #else |
747 | glClearDepthf (1.0f); |
748 | #endif |
749 | |
750 | render (theProjection, theDrawFbo, Standard_True); |
751 | |
752 | return !toCopyBackToFront; |
753 | } |
754 | |
755 | //======================================================================= |
756 | //function : Render |
757 | //purpose : |
758 | //======================================================================= |
759 | void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, |
760 | OpenGl_FrameBuffer* theOutputFBO, |
761 | const Standard_Boolean theToDrawImmediate) |
762 | { |
763 | // ================================== |
764 | // Step 1: Prepare for render |
765 | // ================================== |
766 | |
767 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
768 | |
769 | #if !defined(GL_ES_VERSION_2_0) |
770 | // Disable current clipping planes |
771 | if (aContext->core11 != NULL) |
772 | { |
773 | const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes(); |
774 | for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId) |
775 | { |
776 | aContext->core11fwd->glDisable (aClipPlaneId); |
777 | } |
778 | } |
779 | #endif |
780 | |
781 | // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm). |
782 | myBVHSelector.SetViewVolume (myCamera); |
783 | |
784 | const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); |
785 | if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) |
786 | { |
787 | aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &OpenGl_NoShadingLight() : &myLights); |
788 | myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); |
789 | } |
790 | |
791 | // Update matrices if camera has changed. |
792 | Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); |
793 | const Standard_Boolean isCameraChanged = myWorldViewProjState != aWVPState; |
794 | const Standard_Boolean isSameView = aManager->IsSameView (this); |
795 | if (isCameraChanged) |
796 | { |
797 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF()); |
798 | aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF()); |
bf02aa7d |
799 | myAccumFrames = 0; |
c357e426 |
800 | } |
801 | |
802 | // Apply new matrix state if camera has changed or this view differs from the one |
803 | // that was previously used for configuring matrices of shader manager |
804 | // (ApplyProjectionMatrix and ApplyWorldViewMatrix will affect the manager). |
805 | if (isCameraChanged || !isSameView) |
806 | { |
807 | aContext->ApplyProjectionMatrix(); |
808 | aContext->ApplyWorldViewMatrix(); |
809 | } |
810 | |
811 | if (aManager->ModelWorldState().Index() == 0) |
812 | { |
813 | aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); |
814 | } |
815 | |
816 | myWorldViewProjState = aWVPState; |
817 | |
818 | // ==================================== |
819 | // Step 2: Redraw background |
820 | // ==================================== |
821 | |
822 | // Render background |
823 | if (!theToDrawImmediate) |
824 | { |
a521d90d |
825 | drawBackground (myWorkspace); |
c357e426 |
826 | } |
827 | |
828 | #if !defined(GL_ES_VERSION_2_0) |
829 | // Switch off lighting by default |
830 | if (aContext->core11 != NULL) |
831 | { |
832 | glDisable(GL_LIGHTING); |
833 | } |
834 | #endif |
835 | |
836 | // ================================= |
837 | // Step 3: Redraw main plane |
838 | // ================================= |
839 | |
840 | // Setup face culling |
841 | GLboolean isCullFace = GL_FALSE; |
842 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
843 | { |
844 | isCullFace = glIsEnabled (GL_CULL_FACE); |
845 | if (myBackfacing == Graphic3d_TOBM_DISABLE) |
846 | { |
847 | glEnable (GL_CULL_FACE); |
848 | glCullFace (GL_BACK); |
849 | } |
850 | else |
851 | glDisable (GL_CULL_FACE); |
852 | } |
853 | |
854 | #if !defined(GL_ES_VERSION_2_0) |
855 | // if the view is scaled normal vectors are scaled to unit |
856 | // length for correct displaying of shaded objects |
857 | const gp_Pnt anAxialScale = myCamera->AxialScale(); |
858 | if (anAxialScale.X() != 1.F || |
859 | anAxialScale.Y() != 1.F || |
860 | anAxialScale.Z() != 1.F) |
861 | { |
862 | aContext->SetGlNormalizeEnabled (Standard_True); |
863 | } |
864 | else |
865 | { |
866 | aContext->SetGlNormalizeEnabled (Standard_False); |
867 | } |
868 | |
869 | // Apply Fog |
870 | if (myFog.IsOn |
871 | && aContext->core11 != NULL) |
872 | { |
873 | Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance(); |
874 | if (myCamera->ZFar() < aFogFrontConverted) |
875 | { |
876 | aFogFrontConverted = myCamera->ZFar(); |
877 | myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance()); |
878 | } |
879 | |
880 | Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance(); |
881 | if (myCamera->ZFar() < aFogFrontConverted) |
882 | { |
883 | aFogBackConverted = myCamera->ZFar(); |
884 | myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance()); |
885 | } |
886 | |
887 | if (aFogFrontConverted > aFogBackConverted) |
888 | { |
889 | myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance()); |
890 | myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance()); |
891 | } |
892 | |
893 | glFogi(GL_FOG_MODE, GL_LINEAR); |
894 | glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted); |
895 | glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted); |
896 | glFogfv(GL_FOG_COLOR, myFog.Color.rgb); |
897 | glEnable(GL_FOG); |
898 | } |
899 | else if (aContext->core11 != NULL) |
900 | { |
901 | glDisable (GL_FOG); |
902 | } |
903 | |
904 | // Apply InteriorShadingMethod |
905 | if (aContext->core11 != NULL) |
906 | { |
907 | aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET |
908 | || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH); |
909 | } |
910 | #endif |
911 | |
912 | aManager->SetShadingModel (myShadingModel); |
913 | |
914 | // Apply AntiAliasing |
915 | if (myAntiAliasing) |
916 | myWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING; |
917 | else |
918 | myWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING; |
919 | |
920 | if (!aManager->IsEmpty()) |
921 | { |
922 | aManager->UpdateClippingState(); |
923 | } |
924 | |
925 | // Redraw 3d scene |
926 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) |
927 | { |
928 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF()); |
929 | aContext->ApplyProjectionMatrix(); |
930 | } |
931 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) |
932 | { |
933 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF()); |
934 | aContext->ApplyProjectionMatrix(); |
935 | } |
bf02aa7d |
936 | renderScene (theProjection, theOutputFBO, theToDrawImmediate); |
c357e426 |
937 | |
938 | // =============================== |
939 | // Step 4: Trihedron |
940 | // =============================== |
941 | |
942 | // Resetting GL parameters according to the default aspects |
943 | // in order to synchronize GL state with the graphic driver state |
944 | // before drawing auxiliary stuff (trihedrons, overlayer) |
c357e426 |
945 | myWorkspace->ResetAppliedAspect(); |
946 | |
79f4f036 |
947 | aContext->ChangeClipping().RemoveAll (aContext); |
c357e426 |
948 | |
949 | if (!aManager->IsEmpty()) |
950 | { |
951 | aManager->ResetMaterialStates(); |
952 | aManager->RevertClippingState(); |
953 | |
954 | // We need to disable (unbind) all shaders programs to ensure |
955 | // that all objects without specified aspect will be drawn |
956 | // correctly (such as background) |
957 | aContext->BindProgram (NULL); |
958 | } |
959 | |
960 | // Render trihedron |
961 | if (!theToDrawImmediate) |
962 | { |
963 | renderTrihedron (myWorkspace); |
964 | |
965 | // Restore face culling |
966 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
967 | { |
968 | if (isCullFace) |
969 | { |
970 | glEnable (GL_CULL_FACE); |
971 | glCullFace (GL_BACK); |
972 | } |
973 | else |
974 | glDisable (GL_CULL_FACE); |
975 | } |
976 | } |
977 | |
c357e426 |
978 | // ============================================================== |
979 | // Step 6: Keep shader manager informed about last View |
980 | // ============================================================== |
981 | |
982 | if (!aManager.IsNull()) |
983 | { |
984 | aManager->SetLastView (this); |
985 | } |
986 | } |
987 | |
988 | // ======================================================================= |
989 | // function : InvalidateBVHData |
990 | // purpose : |
991 | // ======================================================================= |
992 | void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) |
993 | { |
994 | myZLayers.InvalidateBVHData (theLayerId); |
995 | } |
996 | |
997 | //======================================================================= |
998 | //function : renderStructs |
999 | //purpose : |
1000 | //======================================================================= |
bf02aa7d |
1001 | void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection, |
1002 | OpenGl_FrameBuffer* theReadDrawFbo, |
1003 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1004 | { |
1005 | if ( myZLayers.NbStructures() <= 0 ) |
1006 | return; |
1007 | |
1008 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1009 | if ( (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 ) |
1010 | { |
1011 | #if !defined(GL_ES_VERSION_2_0) |
1012 | const int anAntiAliasingMode = myWorkspace->AntiAliasingMode(); |
1013 | #endif |
1014 | |
1015 | if ( !myAntiAliasing ) |
1016 | { |
1017 | #if !defined(GL_ES_VERSION_2_0) |
1018 | if (aCtx->core11 != NULL) |
1019 | { |
1020 | glDisable (GL_POINT_SMOOTH); |
1021 | } |
1022 | glDisable(GL_LINE_SMOOTH); |
1023 | if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH); |
1024 | #endif |
1025 | glBlendFunc (GL_ONE, GL_ZERO); |
1026 | glDisable (GL_BLEND); |
1027 | } |
1028 | else |
1029 | { |
1030 | #if !defined(GL_ES_VERSION_2_0) |
1031 | if (aCtx->core11 != NULL) |
1032 | { |
1033 | glEnable(GL_POINT_SMOOTH); |
1034 | } |
1035 | glEnable(GL_LINE_SMOOTH); |
1036 | if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH); |
1037 | #endif |
1038 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
1039 | glEnable (GL_BLEND); |
1040 | } |
1041 | } |
1042 | |
1043 | Standard_Boolean toRenderGL = theToDrawImmediate || |
1044 | myRenderParams.Method != Graphic3d_RM_RAYTRACING || |
1045 | myRaytraceInitStatus == OpenGl_RT_FAIL || |
1046 | aCtx->IsFeedback(); |
1047 | |
1048 | if (!toRenderGL) |
1049 | { |
1050 | toRenderGL = !initRaytraceResources (aCtx) || |
1051 | !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx); |
1052 | |
1053 | toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL |
1054 | |
1055 | if (!toRenderGL) |
1056 | { |
1057 | const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width(); |
1058 | const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height(); |
3c4b62a4 |
1059 | myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0); |
c357e426 |
1060 | |
1061 | if (myRaytraceFilter.IsNull()) |
1062 | myRaytraceFilter = new OpenGl_RaytraceFilter; |
1063 | |
1064 | myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter()); |
1065 | |
1066 | if (theReadDrawFbo != NULL) |
1067 | theReadDrawFbo->UnbindBuffer (aCtx); |
1068 | |
1069 | // Prepare preliminary OpenGL output |
1070 | if (aCtx->arbFBOBlit != NULL) |
1071 | { |
1072 | // Render bottom OSD layer |
1073 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom); |
1074 | |
1075 | myWorkspace->SetRenderFilter (myRaytraceFilter); |
1076 | { |
1077 | if (theReadDrawFbo != NULL) |
1078 | { |
1079 | theReadDrawFbo->BindReadBuffer (aCtx); |
1080 | } |
1081 | else |
1082 | { |
1083 | aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0); |
1084 | } |
1085 | |
1086 | myOpenGlFBO->BindDrawBuffer (aCtx); |
1087 | |
1088 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY, |
1089 | 0, 0, aSizeX, aSizeY, |
1090 | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, |
1091 | GL_NEAREST); |
1092 | |
1093 | // Render non-polygonal elements in default layer |
1094 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default); |
1095 | } |
1096 | myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter()); |
1097 | } |
1098 | |
1099 | if (theReadDrawFbo != NULL) |
1100 | { |
1101 | theReadDrawFbo->BindBuffer (aCtx); |
1102 | } |
1103 | else |
1104 | { |
1105 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0); |
1106 | } |
1107 | |
1108 | // Ray-tracing polygonal primitive arrays |
bf02aa7d |
1109 | raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx); |
c357e426 |
1110 | |
1111 | // Render upper (top and topmost) OpenGL layers |
1112 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper); |
1113 | } |
1114 | } |
1115 | |
1116 | // Redraw 3D scene using OpenGL in standard |
1117 | // mode or in case of ray-tracing failure |
1118 | if (toRenderGL) |
1119 | { |
1120 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All); |
1121 | |
1122 | // Set flag that scene was redrawn by standard pipeline |
1123 | myWasRedrawnGL = Standard_True; |
1124 | } |
1125 | } |
1126 | |
1127 | //======================================================================= |
1128 | //function : renderTrihedron |
1129 | //purpose : |
1130 | //======================================================================= |
1131 | void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace) |
1132 | { |
1133 | // display global trihedron |
1134 | if (myToShowTrihedron) |
1135 | { |
1136 | myTrihedron.Render (theWorkspace); |
1137 | } |
1138 | if (myToShowGradTrihedron) |
1139 | { |
1140 | myGraduatedTrihedron.Render (theWorkspace); |
1141 | } |
1142 | } |
1143 | |
1144 | // ======================================================================= |
1145 | // function : Invalidate |
1146 | // purpose : |
1147 | // ======================================================================= |
1148 | void OpenGl_View::Invalidate() |
1149 | { |
1150 | myBackBufferRestored = Standard_False; |
1151 | } |
1152 | |
1153 | //======================================================================= |
1154 | //function : renderScene |
1155 | //purpose : |
1156 | //======================================================================= |
bf02aa7d |
1157 | void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, |
1158 | OpenGl_FrameBuffer* theReadDrawFbo, |
1159 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1160 | { |
1161 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
1162 | |
1163 | if (myZClip.Back.IsOn || myZClip.Front.IsOn) |
1164 | { |
1165 | Handle(Graphic3d_ClipPlane) aPlaneBack; |
1166 | Handle(Graphic3d_ClipPlane) aPlaneFront; |
1167 | |
1168 | if (myZClip.Back.IsOn) |
1169 | { |
1170 | Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance(); |
1171 | if (myCamera->ZFar() < aClipBackConverted) |
1172 | { |
1173 | aClipBackConverted = myCamera->ZFar(); |
1174 | myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance()); |
1175 | } |
1176 | const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted); |
1177 | aPlaneBack = new Graphic3d_ClipPlane (aBackEquation); |
1178 | } |
1179 | |
1180 | if (myZClip.Front.IsOn) |
1181 | { |
1182 | Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance(); |
1183 | if (myCamera->ZNear() > aClipFrontConverted) |
1184 | { |
1185 | aClipFrontConverted = myCamera->ZNear(); |
1186 | myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance()); |
1187 | } |
1188 | const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted); |
1189 | aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation); |
1190 | } |
1191 | |
1192 | // Specify slicing planes with identity transformation |
1193 | if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull()) |
1194 | { |
1195 | Graphic3d_SequenceOfHClipPlane aSlicingPlanes; |
1196 | if (!aPlaneBack.IsNull()) |
1197 | { |
1198 | aSlicingPlanes.Append (aPlaneBack); |
1199 | } |
1200 | |
1201 | if (!aPlaneFront.IsNull()) |
1202 | { |
1203 | aSlicingPlanes.Append (aPlaneFront); |
1204 | } |
1205 | |
1206 | // add planes at loaded view matrix state |
79f4f036 |
1207 | aContext->ChangeClipping().AddView (aContext, aSlicingPlanes); |
c357e426 |
1208 | } |
1209 | } |
1210 | |
1211 | #ifdef _WIN32 |
1212 | // set printing scale/tiling transformation |
1213 | Handle(OpenGl_PrinterContext) aPrintContext = myWorkspace->PrinterContext(); |
1214 | if (!aPrintContext.IsNull()) |
1215 | { |
1216 | aContext->ProjectionState.Push(); |
1217 | aContext->ProjectionState.SetCurrent (aPrintContext->ProjTransformation() * aContext->ProjectionState.Current()); |
1218 | aContext->ApplyProjectionMatrix(); |
1219 | } |
1220 | #endif |
1221 | |
1222 | // Specify clipping planes in view transformation space |
1223 | if (!myClipPlanes.IsEmpty()) |
1224 | { |
1225 | Graphic3d_SequenceOfHClipPlane aUserPlanes; |
1226 | Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes); |
1227 | for (; aClippingIt.More(); aClippingIt.Next()) |
1228 | { |
1229 | const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value(); |
1230 | if (aClipPlane->IsOn()) |
1231 | { |
1232 | aUserPlanes.Append (aClipPlane); |
1233 | } |
1234 | } |
1235 | |
1236 | if (!aUserPlanes.IsEmpty()) |
1237 | { |
79f4f036 |
1238 | aContext->ChangeClipping().AddWorldLazy (aContext, aUserPlanes); |
c357e426 |
1239 | } |
1240 | |
1241 | if (!aContext->ShaderManager()->IsEmpty()) |
1242 | { |
1243 | aContext->ShaderManager()->UpdateClippingState(); |
1244 | } |
1245 | } |
1246 | |
1247 | #if !defined(GL_ES_VERSION_2_0) |
1248 | // Apply Lights |
1249 | if (aContext->core11 != NULL) |
1250 | { |
1251 | // setup lights |
1252 | Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0], |
1253 | THE_DEFAULT_AMBIENT[1], |
1254 | THE_DEFAULT_AMBIENT[2], |
1255 | THE_DEFAULT_AMBIENT[3]); |
1256 | GLenum aLightGlId = GL_LIGHT0; |
1257 | |
1258 | OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? OpenGl_NoShadingLight() : myLights); |
1259 | for (; aLightIt.More(); aLightIt.Next()) |
1260 | { |
1261 | bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace); |
1262 | } |
1263 | |
1264 | // apply accumulated ambient color |
1265 | anAmbientColor.a() = 1.0f; |
1266 | glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData()); |
1267 | |
1268 | if (aLightGlId != GL_LIGHT0) |
1269 | { |
1270 | glEnable (GL_LIGHTING); |
1271 | } |
1272 | // switch off unused lights |
1273 | for (; aLightGlId <= GL_LIGHT7; ++aLightGlId) |
1274 | { |
1275 | glDisable (aLightGlId); |
1276 | } |
1277 | } |
1278 | #endif |
1279 | |
1280 | // Clear status bitfields |
1281 | myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO); |
1282 | |
1283 | // Update state of surface detail level |
1284 | myWorkspace->GetGlContext()->ShaderManager()->UpdateSurfaceDetailStateTo (mySurfaceDetail); |
1285 | |
1286 | // Added PCT for handling of textures |
1287 | switch (mySurfaceDetail) |
1288 | { |
1289 | case Graphic3d_TOD_NONE: |
1290 | myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX; |
1291 | myWorkspace->DisableTexture(); |
1292 | // Render the view |
bf02aa7d |
1293 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
c357e426 |
1294 | break; |
1295 | |
1296 | case Graphic3d_TOD_ENVIRONMENT: |
1297 | myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX; |
1298 | if (myRenderParams.Method != Graphic3d_RM_RAYTRACING) |
1299 | { |
1300 | myWorkspace->EnableTexture (myTextureEnv); |
1301 | } |
1302 | // Render the view |
bf02aa7d |
1303 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
c357e426 |
1304 | myWorkspace->DisableTexture(); |
1305 | break; |
1306 | |
1307 | case Graphic3d_TOD_ALL: |
1308 | // First pass |
1309 | myWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX; |
1310 | // Render the view |
bf02aa7d |
1311 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
c357e426 |
1312 | myWorkspace->DisableTexture(); |
1313 | |
1314 | // Second pass |
1315 | if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) |
1316 | { |
1317 | myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO; |
1318 | if (myRenderParams.Method != Graphic3d_RM_RAYTRACING) |
1319 | { |
1320 | myWorkspace->EnableTexture (myTextureEnv); |
1321 | } |
1322 | |
1323 | // Remember OpenGl properties |
1324 | GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA; |
1325 | GLint aSaveZbuffFunc; |
1326 | GLboolean aSaveZbuffWrite; |
1327 | glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite); |
1328 | glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc); |
1329 | #if !defined(GL_ES_VERSION_2_0) |
1330 | glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst); |
1331 | glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc); |
1332 | #endif |
1333 | GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST); |
1334 | GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND); |
1335 | |
1336 | // Change the properties for second rendering pass |
1337 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
1338 | glEnable (GL_BLEND); |
1339 | |
1340 | glDepthFunc (GL_EQUAL); |
1341 | glDepthMask (GL_FALSE); |
1342 | glEnable (GL_DEPTH_TEST); |
1343 | |
1344 | myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX; |
1345 | |
1346 | // Render the view |
bf02aa7d |
1347 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
c357e426 |
1348 | myWorkspace->DisableTexture(); |
1349 | |
1350 | // Restore properties back |
1351 | glBlendFunc (aSaveBlendSrc, aSaveBlendDst); |
1352 | if (!wasBlendEnabled) |
1353 | glDisable (GL_BLEND); |
1354 | |
1355 | glDepthFunc (aSaveZbuffFunc); |
1356 | glDepthMask (aSaveZbuffWrite); |
1357 | if (!wasZbuffEnabled) |
1358 | glDisable (GL_DEPTH_FUNC); |
1359 | } |
1360 | break; |
1361 | } |
1362 | |
1363 | // Apply restored view matrix. |
1364 | aContext->ApplyWorldViewMatrix(); |
1365 | |
1366 | #ifdef _WIN32 |
1367 | // set printing scale/tiling transformation |
1368 | if (!aPrintContext.IsNull()) |
1369 | { |
1370 | aContext->ProjectionState.Pop(); |
1371 | aContext->ApplyProjectionMatrix(); |
1372 | } |
1373 | #endif |
1374 | } |
1375 | |
1376 | // ======================================================================= |
1377 | // function : bindDefaultFbo |
1378 | // purpose : |
1379 | // ======================================================================= |
1380 | void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) |
1381 | { |
1382 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1383 | OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) |
1384 | ? theCustomFbo |
1385 | : (!aCtx->DefaultFrameBuffer().IsNull() |
1386 | && aCtx->DefaultFrameBuffer()->IsValid() |
1387 | ? aCtx->DefaultFrameBuffer().operator->() |
1388 | : NULL); |
1389 | if (anFbo != NULL) |
1390 | { |
1391 | anFbo->BindBuffer (aCtx); |
1392 | } |
1393 | else |
1394 | { |
1395 | #if !defined(GL_ES_VERSION_2_0) |
1396 | aCtx->SetReadDrawBuffer (GL_BACK); |
1397 | #else |
1398 | if (aCtx->arbFBO != NULL) |
1399 | { |
1400 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1401 | } |
1402 | #endif |
1403 | } |
1404 | aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height()); |
1405 | } |
1406 | |
1407 | // ======================================================================= |
1408 | // function : initBlitQuad |
1409 | // purpose : |
1410 | // ======================================================================= |
1411 | OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip) |
1412 | { |
1413 | OpenGl_VertexBuffer* aVerts = NULL; |
1414 | if (!theToFlip) |
1415 | { |
1416 | aVerts = &myFullScreenQuad; |
1417 | if (!aVerts->IsValid()) |
1418 | { |
1419 | OpenGl_Vec4 aQuad[4] = |
1420 | { |
1421 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), |
1422 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), |
1423 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), |
1424 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) |
1425 | }; |
1426 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1427 | } |
1428 | } |
1429 | else |
1430 | { |
1431 | aVerts = &myFullScreenQuadFlip; |
1432 | if (!aVerts->IsValid()) |
1433 | { |
1434 | OpenGl_Vec4 aQuad[4] = |
1435 | { |
1436 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), |
1437 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), |
1438 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), |
1439 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) |
1440 | }; |
1441 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1442 | } |
1443 | } |
1444 | return aVerts; |
1445 | } |
1446 | |
1447 | // ======================================================================= |
1448 | // function : blitBuffers |
1449 | // purpose : |
1450 | // ======================================================================= |
1451 | bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, |
1452 | OpenGl_FrameBuffer* theDrawFbo, |
1453 | const Standard_Boolean theToFlip) |
1454 | { |
1455 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1456 | if (theReadFbo == NULL || aCtx->IsFeedback()) |
1457 | { |
1458 | return false; |
1459 | } |
1460 | else if (theReadFbo == theDrawFbo) |
1461 | { |
1462 | return true; |
1463 | } |
1464 | |
1465 | // clear destination before blitting |
1466 | if (theDrawFbo != NULL |
1467 | && theDrawFbo->IsValid()) |
1468 | { |
1469 | theDrawFbo->BindBuffer (aCtx); |
1470 | } |
1471 | else |
1472 | { |
1473 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1474 | } |
1475 | #if !defined(GL_ES_VERSION_2_0) |
1476 | aCtx->core20fwd->glClearDepth (1.0); |
1477 | #else |
1478 | aCtx->core20fwd->glClearDepthf (1.0f); |
1479 | #endif |
1480 | aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
1481 | |
3c4b62a4 |
1482 | #if !defined(GL_ES_VERSION_2_0) |
1483 | if (aCtx->arbFBOBlit != NULL |
1484 | && theReadFbo->NbSamples() != 0) |
c357e426 |
1485 | { |
3c4b62a4 |
1486 | GLbitfield aCopyMask = 0; |
c357e426 |
1487 | theReadFbo->BindReadBuffer (aCtx); |
1488 | if (theDrawFbo != NULL |
1489 | && theDrawFbo->IsValid()) |
1490 | { |
1491 | theDrawFbo->BindDrawBuffer (aCtx); |
3c4b62a4 |
1492 | if (theDrawFbo->HasColor() |
1493 | && theReadFbo->HasColor()) |
1494 | { |
1495 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1496 | } |
1497 | if (theDrawFbo->HasDepth() |
1498 | && theReadFbo->HasDepth()) |
1499 | { |
1500 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1501 | } |
c357e426 |
1502 | } |
1503 | else |
1504 | { |
3c4b62a4 |
1505 | if (theReadFbo->HasColor()) |
1506 | { |
1507 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1508 | } |
1509 | if (theReadFbo->HasDepth()) |
1510 | { |
1511 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1512 | } |
c357e426 |
1513 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1514 | } |
3c4b62a4 |
1515 | |
c357e426 |
1516 | // we don't copy stencil buffer here... does it matter for performance? |
1517 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), |
1518 | 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), |
3c4b62a4 |
1519 | aCopyMask, GL_NEAREST); |
c357e426 |
1520 | if (theDrawFbo != NULL |
3c4b62a4 |
1521 | && theDrawFbo->IsValid()) |
c357e426 |
1522 | { |
1523 | theDrawFbo->BindBuffer (aCtx); |
1524 | } |
1525 | else |
1526 | { |
1527 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1528 | } |
1529 | } |
1530 | else |
3c4b62a4 |
1531 | #endif |
c357e426 |
1532 | { |
1533 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1534 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1535 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1536 | |
1537 | myWorkspace->DisableTexture(); |
1538 | |
1539 | OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); |
1540 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1541 | if (aVerts->IsValid() |
1542 | && aManager->BindFboBlitProgram()) |
1543 | { |
1544 | theReadFbo->ColorTexture() ->Bind (aCtx, GL_TEXTURE0 + 0); |
1545 | theReadFbo->DepthStencilTexture()->Bind (aCtx, GL_TEXTURE0 + 1); |
1546 | aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1547 | |
1548 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1549 | |
1550 | aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1551 | theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1); |
1552 | theReadFbo->ColorTexture() ->Unbind (aCtx, GL_TEXTURE0 + 0); |
a521d90d |
1553 | aCtx->BindProgram (NULL); |
c357e426 |
1554 | } |
1555 | else |
1556 | { |
1557 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1558 | + "Error! FBO blitting has failed"; |
3b523c4c |
1559 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1560 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1561 | 0, |
3b523c4c |
1562 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1563 | aMsg); |
1564 | myHasFboBlit = Standard_False; |
1565 | theReadFbo->Release (aCtx.operator->()); |
1566 | return true; |
1567 | } |
1568 | } |
1569 | return true; |
1570 | } |
1571 | |
1572 | // ======================================================================= |
1573 | // function : drawStereoPair |
1574 | // purpose : |
1575 | // ======================================================================= |
3c4b62a4 |
1576 | void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) |
c357e426 |
1577 | { |
3c4b62a4 |
1578 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1579 | bindDefaultFbo (theDrawFbo); |
c357e426 |
1580 | OpenGl_FrameBuffer* aPair[2] = |
1581 | { |
1582 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
1583 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
1584 | }; |
1585 | if (aPair[0] == NULL |
1586 | || aPair[1] == NULL |
1587 | || !myTransientDrawToFront) |
1588 | { |
1589 | aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
1590 | aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; |
1591 | } |
1592 | |
1593 | if (aPair[0] == NULL |
1594 | || aPair[1] == NULL) |
1595 | { |
1596 | return; |
1597 | } |
1598 | |
3c4b62a4 |
1599 | if (aPair[0]->NbSamples() != 0) |
1600 | { |
1601 | // resolve MSAA buffers before drawing |
1602 | if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0) |
1603 | || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0)) |
1604 | { |
82f443b6 |
1605 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1606 | GL_DEBUG_TYPE_ERROR, |
3c4b62a4 |
1607 | 0, |
82f443b6 |
1608 | GL_DEBUG_SEVERITY_HIGH, |
3c4b62a4 |
1609 | "Error! Unable to allocate FBO for blitting stereo pair"); |
1610 | bindDefaultFbo (theDrawFbo); |
1611 | return; |
1612 | } |
1613 | |
1614 | if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False) |
1615 | || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False)) |
1616 | { |
1617 | bindDefaultFbo (theDrawFbo); |
1618 | return; |
1619 | } |
1620 | |
1621 | aPair[0] = myOpenGlFBO .operator->(); |
1622 | aPair[1] = myOpenGlFBO2.operator->(); |
1623 | bindDefaultFbo (theDrawFbo); |
1624 | } |
1625 | |
c357e426 |
1626 | struct |
1627 | { |
1628 | Standard_Integer left; |
1629 | Standard_Integer top; |
1630 | Standard_Integer right; |
1631 | Standard_Integer bottom; |
1632 | Standard_Integer dx() { return right - left; } |
1633 | Standard_Integer dy() { return bottom - top; } |
1634 | } aGeom; |
1635 | |
1636 | myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom); |
1637 | |
1638 | Standard_Boolean toReverse = myRenderParams.ToReverseStereo; |
1639 | const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1; |
1640 | const Standard_Boolean isOddX = aGeom.left % 2 == 1; |
1641 | if (isOddY |
1642 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced |
1643 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1644 | { |
1645 | toReverse = !toReverse; |
1646 | } |
1647 | if (isOddX |
1648 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced |
1649 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1650 | { |
1651 | toReverse = !toReverse; |
1652 | } |
1653 | |
1654 | if (toReverse) |
1655 | { |
1656 | std::swap (aPair[0], aPair[1]); |
1657 | } |
1658 | |
c357e426 |
1659 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1660 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1661 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1662 | |
1663 | myWorkspace->DisableTexture(); |
1664 | OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); |
1665 | |
1666 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1667 | if (aVerts->IsValid() |
1668 | && aManager->BindStereoProgram (myRenderParams.StereoMode)) |
1669 | { |
1670 | if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) |
1671 | { |
1672 | OpenGl_Mat4 aFilterL, aFilterR; |
1673 | aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1674 | aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1675 | switch (myRenderParams.AnaglyphFilter) |
1676 | { |
1677 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: |
1678 | { |
1679 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1680 | aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1681 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1682 | break; |
1683 | } |
1684 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: |
1685 | { |
1686 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); |
1687 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); |
1688 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); |
1689 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1690 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); |
1691 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); |
1692 | aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); |
1693 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1694 | break; |
1695 | } |
1696 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: |
1697 | { |
1698 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1699 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1700 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1701 | break; |
1702 | } |
1703 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: |
1704 | { |
1705 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); |
1706 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); |
1707 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); |
1708 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1709 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); |
1710 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); |
1711 | aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); |
1712 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1713 | break; |
1714 | } |
1715 | case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: |
1716 | { |
1717 | aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1718 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1719 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1720 | break; |
1721 | } |
1722 | case Graphic3d_RenderingParams::Anaglyph_UserDefined: |
1723 | { |
1724 | aFilterL = myRenderParams.AnaglyphLeft; |
1725 | aFilterR = myRenderParams.AnaglyphRight; |
1726 | break; |
1727 | } |
1728 | } |
1729 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL); |
1730 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR); |
1731 | } |
1732 | |
1733 | aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0); |
1734 | aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1); |
1735 | aVerts->BindVertexAttrib (aCtx, 0); |
1736 | |
1737 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1738 | |
1739 | aVerts->UnbindVertexAttrib (aCtx, 0); |
1740 | aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1); |
1741 | aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0); |
1742 | } |
1743 | else |
1744 | { |
1745 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1746 | + "Error! Anaglyph has failed"; |
3b523c4c |
1747 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1748 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1749 | 0, |
3b523c4c |
1750 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1751 | aMsg); |
1752 | } |
1753 | } |
1754 | |
1755 | // ======================================================================= |
1756 | // function : copyBackToFront |
1757 | // purpose : |
1758 | // ======================================================================= |
1759 | void OpenGl_View::copyBackToFront() |
1760 | { |
1761 | #if !defined(GL_ES_VERSION_2_0) |
1762 | |
1763 | OpenGl_Mat4 aProjectMat; |
1764 | Graphic3d_TransformUtils::Ortho2D (aProjectMat, |
1765 | 0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height())); |
1766 | |
1767 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1768 | aCtx->WorldViewState.Push(); |
1769 | aCtx->ProjectionState.Push(); |
1770 | |
1771 | aCtx->WorldViewState.SetIdentity(); |
1772 | aCtx->ProjectionState.SetCurrent (aProjectMat); |
1773 | |
1774 | aCtx->ApplyProjectionMatrix(); |
1775 | aCtx->ApplyWorldViewMatrix(); |
1776 | |
1777 | aCtx->DisableFeatures(); |
1778 | |
1779 | switch (aCtx->DrawBuffer()) |
1780 | { |
1781 | case GL_BACK_LEFT: |
1782 | { |
1783 | aCtx->SetReadBuffer (GL_BACK_LEFT); |
1784 | aCtx->SetDrawBuffer (GL_FRONT_LEFT); |
1785 | break; |
1786 | } |
1787 | case GL_BACK_RIGHT: |
1788 | { |
1789 | aCtx->SetReadBuffer (GL_BACK_RIGHT); |
1790 | aCtx->SetDrawBuffer (GL_FRONT_RIGHT); |
1791 | break; |
1792 | } |
1793 | default: |
1794 | { |
1795 | aCtx->SetReadBuffer (GL_BACK); |
1796 | aCtx->SetDrawBuffer (GL_FRONT); |
1797 | break; |
1798 | } |
1799 | } |
1800 | |
1801 | glRasterPos2i (0, 0); |
1802 | glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR); |
1803 | //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); |
1804 | |
1805 | aCtx->EnableFeatures(); |
1806 | |
1807 | aCtx->WorldViewState.Pop(); |
1808 | aCtx->ProjectionState.Pop(); |
1809 | aCtx->ApplyProjectionMatrix(); |
1810 | |
1811 | // read/write from front buffer now |
1812 | aCtx->SetReadBuffer (aCtx->DrawBuffer()); |
1813 | #endif |
1814 | myIsImmediateDrawn = Standard_False; |
1815 | } |