1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
19 #include <OpenGl_GlCore11.hxx>
20 #include <OpenGl_tgl_funcs.hxx>
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>
28 #include <NCollection_Mat4.hxx>
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>
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;
54 extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
56 #if !defined(GL_ES_VERSION_2_0)
58 //=======================================================================
59 //function : bindLight
61 //=======================================================================
62 static void bindLight (const OpenGl_Light& theLight,
64 Graphic3d_Vec4& theAmbientColor,
65 const Handle(OpenGl_Workspace)& theWorkspace)
67 // Only 8 lights in OpenGL...
68 if (theLightGlId > GL_LIGHT7)
73 if (theLight.Type == Graphic3d_TOLS_AMBIENT)
75 // add RGBA intensity of the ambient light
76 theAmbientColor += theLight.Color;
80 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
82 // the light is a headlight?
83 if (theLight.IsHeadlight)
85 aContext->WorldViewState.Push();
86 aContext->WorldViewState.SetIdentity();
88 aContext->ApplyWorldViewMatrix();
92 switch (theLight.Type)
94 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
95 case Graphic3d_TOLS_DIRECTIONAL:
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;
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);
110 case Graphic3d_TOLS_POSITIONAL:
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);
125 case Graphic3d_TOLS_SPOT:
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);
141 // restore matrix in case of headlight
142 if (theLight.IsHeadlight)
144 aContext->WorldViewState.Pop();
147 glEnable (theLightGlId++);
151 //=======================================================================
152 //function : drawBackground
154 //=======================================================================
155 void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
157 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
159 if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background
160 || (!myBgTextureArray->IsDefined() // no texture
161 && !myBgGradientArray->IsDefined())) // no gradient
166 const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False);
169 aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
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();
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))
189 #if !defined(GL_ES_VERSION_2_0)
190 GLint aShadingModelOld = GL_SMOOTH;
191 if (aCtx->core11 != NULL)
193 aCtx->core11fwd->glDisable (GL_LIGHTING);
194 aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld);
195 aCtx->core11->glShadeModel (GL_SMOOTH);
199 if (myBgGradientArray->IsDataChanged())
201 myBgGradientArray->Init (theWorkspace);
204 myBgGradientArray->Render (theWorkspace);
206 #if !defined(GL_ES_VERSION_2_0)
207 if (aCtx->core11 != NULL)
209 aCtx->core11->glShadeModel (aShadingModelOld);
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())
219 aCtx->core11fwd->glDisable (GL_BLEND);
221 const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams);
223 if (myBgTextureArray->IsDataChanged()
224 || myBgTextureArray->IsViewSizeChanged (theWorkspace))
226 myBgTextureArray->Init (theWorkspace);
229 myBgTextureArray->Render (theWorkspace);
232 theWorkspace->SetAspectFace (anOldAspectFace);
235 aCtx->ModelWorldState.Pop();
236 aCtx->WorldViewState.Pop();
237 aCtx->ProjectionState.Pop();
238 aCtx->ApplyProjectionMatrix();
239 aCtx->ApplyModelViewMatrix();
243 theWorkspace->SetUseZBuffer (Standard_True);
244 aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
248 //=======================================================================
251 //=======================================================================
252 void OpenGl_View::Redraw()
254 if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
255 && !myCaps->vboDisable
256 && !myCaps->keepArrayData)
260 myDeviceLostFlag = Standard_True;
263 myCaps->keepArrayData = Standard_True;
266 if (!myWorkspace->Activate())
271 myWindow->SetSwapInterval();
274 const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
275 Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
276 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
278 // release pending GL resources
279 aCtx->ReleaseDelayed();
281 // fetch OpenGl context state
284 // set resolution ratio
285 aCtx->SetResolutionRatio (RenderingParams().ResolutionRatio());
287 OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->();
288 bool toSwap = aCtx->IsRender()
289 && !aCtx->caps->buffersNoSwap
290 && aFrameBuffer == NULL;
292 Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width();
293 Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height();
295 // determine multisampling parameters
296 Standard_Integer aNbSamples = Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0);
299 aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
302 if ( aFrameBuffer == NULL
303 && !aCtx->DefaultFrameBuffer().IsNull()
304 && aCtx->DefaultFrameBuffer()->IsValid())
306 aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
310 && (myTransientDrawToFront
311 || aProjectType == Graphic3d_Camera::Projection_Stereo
314 if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
315 || myMainSceneFbos[0]->GetVPSizeY() != aSizeY
316 || myMainSceneFbos[0]->NbSamples() != aNbSamples)
318 // prepare FBOs containing main scene
319 // for further blitting and rendering immediate presentations on top
320 if (aCtx->core20fwd != NULL)
322 myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples);
324 if (!aCtx->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid())
326 myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
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);
342 if (aProjectType == Graphic3d_Camera::Projection_Stereo
343 && myMainSceneFbos[0]->IsValid())
345 myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]);
346 if (!myMainSceneFbos[1]->IsValid())
349 aProjectType = Graphic3d_Camera::Projection_Perspective;
351 else if (!myTransientDrawToFront)
355 else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
357 myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
358 myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]);
359 if (!myImmediateSceneFbos[0]->IsValid()
360 || !myImmediateSceneFbos[1]->IsValid())
362 aProjectType = Graphic3d_Camera::Projection_Perspective;
367 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
369 OpenGl_FrameBuffer* aMainFbos[2] =
371 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
372 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
374 OpenGl_FrameBuffer* anImmFbos[2] =
376 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
377 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
380 if (!myTransientDrawToFront)
382 anImmFbos[0] = aMainFbos[0];
383 anImmFbos[1] = aMainFbos[1];
385 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
386 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
392 #if !defined(GL_ES_VERSION_2_0)
393 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
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);
401 if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0]))
405 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap)
410 #if !defined(GL_ES_VERSION_2_0)
411 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
413 redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]);
414 myBackBufferRestored = Standard_True;
415 myIsImmediateDrawn = Standard_False;
416 if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1]))
421 if (anImmFbos[0] != NULL)
423 drawStereoPair (aFrameBuffer);
428 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
429 OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
430 if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
432 anImmFbo = myImmediateSceneFbos[0].operator->();
435 #if !defined(GL_ES_VERSION_2_0)
437 && aFrameBuffer == NULL)
439 aCtx->SetReadDrawBuffer (GL_BACK);
442 redraw (aProjectType, aMainFbo != NULL ? aMainFbo : aFrameBuffer);
443 myBackBufferRestored = Standard_True;
444 myIsImmediateDrawn = Standard_False;
445 if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo))
451 && anImmFbo != aFrameBuffer)
453 blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
457 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
458 if (OpenGl_AVIWriter_AllowWriting (myWindow->PlatformWindow()->NativeHandle()))
461 glGetIntegerv (GL_VIEWPORT, params);
462 int nWidth = params[2] & ~0x7;
463 int nHeight = params[3] & ~0x7;
465 const int nBitsPerPixel = 24;
466 GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
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);
475 if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
476 && myRenderParams.IsGlobalIlluminationEnabled)
488 if (!myMainSceneFbos[0]->IsValid())
490 myBackBufferRestored = Standard_False;
495 aCtx->core11fwd->glFlush();
498 // reset render mode state
501 myWasRedrawnGL = Standard_True;
504 // =======================================================================
505 // function : RedrawImmediate
507 // =======================================================================
508 void OpenGl_View::RedrawImmediate()
510 if (!myWorkspace->Activate())
513 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
514 if (!myTransientDrawToFront
515 || !myBackBufferRestored
516 || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
522 const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
523 Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
524 OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->();
526 if ( aFrameBuffer == NULL
527 && !aCtx->DefaultFrameBuffer().IsNull()
528 && aCtx->DefaultFrameBuffer()->IsValid())
530 aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
533 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
535 if (myMainSceneFbos[0]->IsValid()
536 && !myMainSceneFbos[1]->IsValid())
538 aProjectType = Graphic3d_Camera::Projection_Perspective;
543 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
545 OpenGl_FrameBuffer* aMainFbos[2] =
547 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
548 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
550 OpenGl_FrameBuffer* anImmFbos[2] =
552 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
553 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
555 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
556 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
562 if (aCtx->arbFBO != NULL)
564 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
566 #if !defined(GL_ES_VERSION_2_0)
567 if (anImmFbos[0] == NULL)
569 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
572 toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
575 Standard_True) || toSwap;
576 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
578 && !aCtx->caps->buffersNoSwap)
583 if (aCtx->arbFBO != NULL)
585 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
587 #if !defined(GL_ES_VERSION_2_0)
588 if (anImmFbos[1] == NULL)
590 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
593 toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
596 Standard_True) || toSwap;
597 if (anImmFbos[0] != NULL)
599 drawStereoPair (aFrameBuffer);
604 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
605 OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
606 if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
608 anImmFbo = myImmediateSceneFbos[0].operator->();
610 #if !defined(GL_ES_VERSION_2_0)
611 if (aMainFbo == NULL)
613 aCtx->SetReadDrawBuffer (GL_BACK);
616 toSwap = redrawImmediate (aProjectType,
619 Standard_True) || toSwap;
621 && anImmFbo != aFrameBuffer)
623 blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
630 if (toSwap && !aCtx->caps->buffersNoSwap)
636 aCtx->core11fwd->glFlush();
639 myWasRedrawnGL = Standard_True;
642 // =======================================================================
645 // =======================================================================
646 void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo)
648 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
649 if (theReadDrawFbo != NULL)
651 theReadDrawFbo->BindBuffer (aCtx);
652 theReadDrawFbo->SetupViewport (aCtx);
656 aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
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);
668 #if !defined(GL_ES_VERSION_2_0)
671 glClearDepthf (1.0f);
674 if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK)
676 // set background to white
677 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
681 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
686 render (theProjection, theReadDrawFbo, Standard_False);
689 // =======================================================================
690 // function : redrawMonoImmediate
692 // =======================================================================
693 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
694 OpenGl_FrameBuffer* theReadFbo,
695 OpenGl_FrameBuffer* theDrawFbo,
696 const Standard_Boolean theIsPartialUpdate)
698 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
699 GLboolean toCopyBackToFront = GL_FALSE;
700 if (!myTransientDrawToFront)
702 myBackBufferRestored = Standard_False;
704 else if (theReadFbo != NULL
705 && theReadFbo->IsValid()
708 if (!blitBuffers (theReadFbo, theDrawFbo))
713 else if (theDrawFbo == NULL)
715 #if !defined(GL_ES_VERSION_2_0)
716 aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
718 if (toCopyBackToFront)
720 if (!HasImmediateStructures()
721 && !theIsPartialUpdate)
723 // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
730 myBackBufferRestored = Standard_False;
735 myBackBufferRestored = Standard_False;
737 myIsImmediateDrawn = Standard_True;
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)
747 glClearDepthf (1.0f);
750 render (theProjection, theDrawFbo, Standard_True);
752 return !toCopyBackToFront;
755 //=======================================================================
758 //=======================================================================
759 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
760 OpenGl_FrameBuffer* theOutputFBO,
761 const Standard_Boolean theToDrawImmediate)
763 // ==================================
764 // Step 1: Prepare for render
765 // ==================================
767 const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
769 #if !defined(GL_ES_VERSION_2_0)
770 // Disable current clipping planes
771 if (aContext->core11 != NULL)
773 const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
774 for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
776 aContext->core11fwd->glDisable (aClipPlaneId);
781 // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
782 myBVHSelector.SetViewVolume (myCamera);
784 const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager();
785 if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
787 aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &OpenGl_NoShadingLight() : &myLights);
788 myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
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);
797 aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
798 aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF());
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)
807 aContext->ApplyProjectionMatrix();
808 aContext->ApplyWorldViewMatrix();
811 if (aManager->ModelWorldState().Index() == 0)
813 aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
816 myWorldViewProjState = aWVPState;
818 // ====================================
819 // Step 2: Redraw background
820 // ====================================
823 if (!theToDrawImmediate)
825 drawBackground (myWorkspace);
828 #if !defined(GL_ES_VERSION_2_0)
829 // Switch off lighting by default
830 if (aContext->core11 != NULL)
832 glDisable(GL_LIGHTING);
836 // =================================
837 // Step 3: Redraw main plane
838 // =================================
840 // Setup face culling
841 GLboolean isCullFace = GL_FALSE;
842 if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
844 isCullFace = glIsEnabled (GL_CULL_FACE);
845 if (myBackfacing == Graphic3d_TOBM_DISABLE)
847 glEnable (GL_CULL_FACE);
848 glCullFace (GL_BACK);
851 glDisable (GL_CULL_FACE);
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)
862 aContext->SetGlNormalizeEnabled (Standard_True);
866 aContext->SetGlNormalizeEnabled (Standard_False);
871 && aContext->core11 != NULL)
873 Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
874 if (myCamera->ZFar() < aFogFrontConverted)
876 aFogFrontConverted = myCamera->ZFar();
877 myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
880 Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
881 if (myCamera->ZFar() < aFogFrontConverted)
883 aFogBackConverted = myCamera->ZFar();
884 myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
887 if (aFogFrontConverted > aFogBackConverted)
889 myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
890 myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
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);
899 else if (aContext->core11 != NULL)
904 // Apply InteriorShadingMethod
905 if (aContext->core11 != NULL)
907 aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET
908 || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH);
912 aManager->SetShadingModel (myShadingModel);
914 // Apply AntiAliasing
916 myWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
918 myWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
920 if (!aManager->IsEmpty())
922 aManager->UpdateClippingState();
926 if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
928 aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
929 aContext->ApplyProjectionMatrix();
931 else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
933 aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
934 aContext->ApplyProjectionMatrix();
936 renderScene (theProjection, theOutputFBO, theToDrawImmediate);
938 // ===============================
940 // ===============================
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)
945 myWorkspace->ResetAppliedAspect();
947 aContext->ChangeClipping().RemoveAll (aContext);
949 if (!aManager->IsEmpty())
951 aManager->ResetMaterialStates();
952 aManager->RevertClippingState();
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);
961 if (!theToDrawImmediate)
963 renderTrihedron (myWorkspace);
965 // Restore face culling
966 if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
970 glEnable (GL_CULL_FACE);
971 glCullFace (GL_BACK);
974 glDisable (GL_CULL_FACE);
978 // ==============================================================
979 // Step 6: Keep shader manager informed about last View
980 // ==============================================================
982 if (!aManager.IsNull())
984 aManager->SetLastView (this);
988 // =======================================================================
989 // function : InvalidateBVHData
991 // =======================================================================
992 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
994 myZLayers.InvalidateBVHData (theLayerId);
997 //=======================================================================
998 //function : renderStructs
1000 //=======================================================================
1001 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
1002 OpenGl_FrameBuffer* theReadDrawFbo,
1003 const Standard_Boolean theToDrawImmediate)
1005 if ( myZLayers.NbStructures() <= 0 )
1008 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1009 if ( (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
1011 #if !defined(GL_ES_VERSION_2_0)
1012 const int anAntiAliasingMode = myWorkspace->AntiAliasingMode();
1015 if ( !myAntiAliasing )
1017 #if !defined(GL_ES_VERSION_2_0)
1018 if (aCtx->core11 != NULL)
1020 glDisable (GL_POINT_SMOOTH);
1022 glDisable(GL_LINE_SMOOTH);
1023 if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1025 glBlendFunc (GL_ONE, GL_ZERO);
1026 glDisable (GL_BLEND);
1030 #if !defined(GL_ES_VERSION_2_0)
1031 if (aCtx->core11 != NULL)
1033 glEnable(GL_POINT_SMOOTH);
1035 glEnable(GL_LINE_SMOOTH);
1036 if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1038 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1039 glEnable (GL_BLEND);
1043 Standard_Boolean toRenderGL = theToDrawImmediate ||
1044 myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
1045 myRaytraceInitStatus == OpenGl_RT_FAIL ||
1050 toRenderGL = !initRaytraceResources (aCtx) ||
1051 !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx);
1053 toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
1057 const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width();
1058 const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height();
1059 myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0);
1061 if (myRaytraceFilter.IsNull())
1062 myRaytraceFilter = new OpenGl_RaytraceFilter;
1064 myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter());
1066 if (theReadDrawFbo != NULL)
1067 theReadDrawFbo->UnbindBuffer (aCtx);
1069 // Prepare preliminary OpenGL output
1070 if (aCtx->arbFBOBlit != NULL)
1072 // Render bottom OSD layer
1073 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
1075 myWorkspace->SetRenderFilter (myRaytraceFilter);
1077 if (theReadDrawFbo != NULL)
1079 theReadDrawFbo->BindReadBuffer (aCtx);
1083 aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
1086 myOpenGlFBO->BindDrawBuffer (aCtx);
1088 aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY,
1089 0, 0, aSizeX, aSizeY,
1090 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
1093 // Render non-polygonal elements in default layer
1094 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default);
1096 myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
1099 if (theReadDrawFbo != NULL)
1101 theReadDrawFbo->BindBuffer (aCtx);
1105 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0);
1108 // Reset OpenGl aspects state to default to avoid enabling of
1109 // backface culling which is not supported in ray-tracing.
1110 myWorkspace->ResetAppliedAspect();
1112 // Ray-tracing polygonal primitive arrays
1113 raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
1115 // Render upper (top and topmost) OpenGL layers
1116 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
1120 // Redraw 3D scene using OpenGL in standard
1121 // mode or in case of ray-tracing failure
1124 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All);
1126 // Set flag that scene was redrawn by standard pipeline
1127 myWasRedrawnGL = Standard_True;
1131 //=======================================================================
1132 //function : renderTrihedron
1134 //=======================================================================
1135 void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
1137 // display global trihedron
1138 if (myToShowTrihedron)
1140 myTrihedron.Render (theWorkspace);
1142 if (myToShowGradTrihedron)
1144 myGraduatedTrihedron.Render (theWorkspace);
1148 // =======================================================================
1149 // function : Invalidate
1151 // =======================================================================
1152 void OpenGl_View::Invalidate()
1154 myBackBufferRestored = Standard_False;
1157 //=======================================================================
1158 //function : renderScene
1160 //=======================================================================
1161 void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
1162 OpenGl_FrameBuffer* theReadDrawFbo,
1163 const Standard_Boolean theToDrawImmediate)
1165 const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
1167 if (myZClip.Back.IsOn || myZClip.Front.IsOn)
1169 Handle(Graphic3d_ClipPlane) aPlaneBack;
1170 Handle(Graphic3d_ClipPlane) aPlaneFront;
1172 if (myZClip.Back.IsOn)
1174 Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1175 if (myCamera->ZFar() < aClipBackConverted)
1177 aClipBackConverted = myCamera->ZFar();
1178 myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance());
1180 const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted);
1181 aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
1184 if (myZClip.Front.IsOn)
1186 Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1187 if (myCamera->ZNear() > aClipFrontConverted)
1189 aClipFrontConverted = myCamera->ZNear();
1190 myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance());
1192 const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted);
1193 aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
1196 // Specify slicing planes with identity transformation
1197 if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
1199 Graphic3d_SequenceOfHClipPlane aSlicingPlanes;
1200 if (!aPlaneBack.IsNull())
1202 aSlicingPlanes.Append (aPlaneBack);
1205 if (!aPlaneFront.IsNull())
1207 aSlicingPlanes.Append (aPlaneFront);
1210 // add planes at loaded view matrix state
1211 aContext->ChangeClipping().AddView (aContext, aSlicingPlanes);
1216 // set printing scale/tiling transformation
1217 Handle(OpenGl_PrinterContext) aPrintContext = myWorkspace->PrinterContext();
1218 if (!aPrintContext.IsNull())
1220 aContext->ProjectionState.Push();
1221 aContext->ProjectionState.SetCurrent (aPrintContext->ProjTransformation() * aContext->ProjectionState.Current());
1222 aContext->ApplyProjectionMatrix();
1226 // Specify clipping planes in view transformation space
1227 if (!myClipPlanes.IsEmpty())
1229 Graphic3d_SequenceOfHClipPlane aUserPlanes;
1230 Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1231 for (; aClippingIt.More(); aClippingIt.Next())
1233 const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1234 if (aClipPlane->IsOn())
1236 aUserPlanes.Append (aClipPlane);
1240 if (!aUserPlanes.IsEmpty())
1242 aContext->ChangeClipping().AddWorldLazy (aContext, aUserPlanes);
1245 if (!aContext->ShaderManager()->IsEmpty())
1247 aContext->ShaderManager()->UpdateClippingState();
1251 #if !defined(GL_ES_VERSION_2_0)
1253 if (aContext->core11 != NULL)
1256 Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
1257 THE_DEFAULT_AMBIENT[1],
1258 THE_DEFAULT_AMBIENT[2],
1259 THE_DEFAULT_AMBIENT[3]);
1260 GLenum aLightGlId = GL_LIGHT0;
1262 OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? OpenGl_NoShadingLight() : myLights);
1263 for (; aLightIt.More(); aLightIt.Next())
1265 bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace);
1268 // apply accumulated ambient color
1269 anAmbientColor.a() = 1.0f;
1270 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
1272 if (aLightGlId != GL_LIGHT0)
1274 glEnable (GL_LIGHTING);
1276 // switch off unused lights
1277 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
1279 glDisable (aLightGlId);
1284 // Clear status bitfields
1285 myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1287 // Update state of surface detail level
1288 myWorkspace->GetGlContext()->ShaderManager()->UpdateSurfaceDetailStateTo (mySurfaceDetail);
1290 // Added PCT for handling of textures
1291 switch (mySurfaceDetail)
1293 case Graphic3d_TOD_NONE:
1294 myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1295 myWorkspace->DisableTexture();
1297 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1300 case Graphic3d_TOD_ENVIRONMENT:
1301 myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1302 if (myRenderParams.Method != Graphic3d_RM_RAYTRACING)
1304 myWorkspace->EnableTexture (myTextureEnv);
1307 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1308 myWorkspace->DisableTexture();
1311 case Graphic3d_TOD_ALL:
1313 myWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
1315 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1316 myWorkspace->DisableTexture();
1319 if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1321 myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1322 if (myRenderParams.Method != Graphic3d_RM_RAYTRACING)
1324 myWorkspace->EnableTexture (myTextureEnv);
1327 // Remember OpenGl properties
1328 GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
1329 GLint aSaveZbuffFunc;
1330 GLboolean aSaveZbuffWrite;
1331 glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
1332 glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
1333 #if !defined(GL_ES_VERSION_2_0)
1334 glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
1335 glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
1337 GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
1338 GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
1340 // Change the properties for second rendering pass
1341 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1342 glEnable (GL_BLEND);
1344 glDepthFunc (GL_EQUAL);
1345 glDepthMask (GL_FALSE);
1346 glEnable (GL_DEPTH_TEST);
1348 myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1351 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1352 myWorkspace->DisableTexture();
1354 // Restore properties back
1355 glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
1356 if (!wasBlendEnabled)
1357 glDisable (GL_BLEND);
1359 glDepthFunc (aSaveZbuffFunc);
1360 glDepthMask (aSaveZbuffWrite);
1361 if (!wasZbuffEnabled)
1362 glDisable (GL_DEPTH_FUNC);
1367 // Apply restored view matrix.
1368 aContext->ApplyWorldViewMatrix();
1371 // set printing scale/tiling transformation
1372 if (!aPrintContext.IsNull())
1374 aContext->ProjectionState.Pop();
1375 aContext->ApplyProjectionMatrix();
1380 // =======================================================================
1381 // function : bindDefaultFbo
1383 // =======================================================================
1384 void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
1386 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1387 OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
1389 : (!aCtx->DefaultFrameBuffer().IsNull()
1390 && aCtx->DefaultFrameBuffer()->IsValid()
1391 ? aCtx->DefaultFrameBuffer().operator->()
1395 anFbo->BindBuffer (aCtx);
1399 #if !defined(GL_ES_VERSION_2_0)
1400 aCtx->SetReadDrawBuffer (GL_BACK);
1402 if (aCtx->arbFBO != NULL)
1404 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1408 aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
1411 // =======================================================================
1412 // function : initBlitQuad
1414 // =======================================================================
1415 OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip)
1417 OpenGl_VertexBuffer* aVerts = NULL;
1420 aVerts = &myFullScreenQuad;
1421 if (!aVerts->IsValid())
1423 OpenGl_Vec4 aQuad[4] =
1425 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1426 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f),
1427 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1428 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f)
1430 aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1435 aVerts = &myFullScreenQuadFlip;
1436 if (!aVerts->IsValid())
1438 OpenGl_Vec4 aQuad[4] =
1440 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f),
1441 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f),
1442 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1443 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f)
1445 aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1451 // =======================================================================
1452 // function : blitBuffers
1454 // =======================================================================
1455 bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
1456 OpenGl_FrameBuffer* theDrawFbo,
1457 const Standard_Boolean theToFlip)
1459 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1460 if (theReadFbo == NULL || aCtx->IsFeedback())
1464 else if (theReadFbo == theDrawFbo)
1469 // clear destination before blitting
1470 if (theDrawFbo != NULL
1471 && theDrawFbo->IsValid())
1473 theDrawFbo->BindBuffer (aCtx);
1477 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1479 #if !defined(GL_ES_VERSION_2_0)
1480 aCtx->core20fwd->glClearDepth (1.0);
1482 aCtx->core20fwd->glClearDepthf (1.0f);
1484 aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1486 #if !defined(GL_ES_VERSION_2_0)
1487 if (aCtx->arbFBOBlit != NULL
1488 && theReadFbo->NbSamples() != 0)
1490 GLbitfield aCopyMask = 0;
1491 theReadFbo->BindReadBuffer (aCtx);
1492 if (theDrawFbo != NULL
1493 && theDrawFbo->IsValid())
1495 theDrawFbo->BindDrawBuffer (aCtx);
1496 if (theDrawFbo->HasColor()
1497 && theReadFbo->HasColor())
1499 aCopyMask |= GL_COLOR_BUFFER_BIT;
1501 if (theDrawFbo->HasDepth()
1502 && theReadFbo->HasDepth())
1504 aCopyMask |= GL_DEPTH_BUFFER_BIT;
1509 if (theReadFbo->HasColor())
1511 aCopyMask |= GL_COLOR_BUFFER_BIT;
1513 if (theReadFbo->HasDepth())
1515 aCopyMask |= GL_DEPTH_BUFFER_BIT;
1517 aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1520 // we don't copy stencil buffer here... does it matter for performance?
1521 aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1522 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1523 aCopyMask, GL_NEAREST);
1524 if (theDrawFbo != NULL
1525 && theDrawFbo->IsValid())
1527 theDrawFbo->BindBuffer (aCtx);
1531 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1537 aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1538 aCtx->core20fwd->glDepthMask (GL_TRUE);
1539 aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1541 myWorkspace->DisableTexture();
1543 OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
1544 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1545 if (aVerts->IsValid()
1546 && aManager->BindFboBlitProgram())
1548 theReadFbo->ColorTexture() ->Bind (aCtx, GL_TEXTURE0 + 0);
1549 theReadFbo->DepthStencilTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1550 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1552 aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1554 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1555 theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1556 theReadFbo->ColorTexture() ->Unbind (aCtx, GL_TEXTURE0 + 0);
1557 aCtx->BindProgram (NULL);
1561 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1562 + "Error! FBO blitting has failed";
1563 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1564 GL_DEBUG_TYPE_ERROR,
1566 GL_DEBUG_SEVERITY_HIGH,
1568 myHasFboBlit = Standard_False;
1569 theReadFbo->Release (aCtx.operator->());
1576 // =======================================================================
1577 // function : drawStereoPair
1579 // =======================================================================
1580 void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
1582 const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
1583 bindDefaultFbo (theDrawFbo);
1584 OpenGl_FrameBuffer* aPair[2] =
1586 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1587 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1589 if (aPair[0] == NULL
1591 || !myTransientDrawToFront)
1593 aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1594 aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
1597 if (aPair[0] == NULL
1598 || aPair[1] == NULL)
1603 if (aPair[0]->NbSamples() != 0)
1605 // resolve MSAA buffers before drawing
1606 if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0)
1607 || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0))
1609 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1610 GL_DEBUG_TYPE_ERROR,
1612 GL_DEBUG_SEVERITY_HIGH,
1613 "Error! Unable to allocate FBO for blitting stereo pair");
1614 bindDefaultFbo (theDrawFbo);
1618 if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False)
1619 || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False))
1621 bindDefaultFbo (theDrawFbo);
1625 aPair[0] = myOpenGlFBO .operator->();
1626 aPair[1] = myOpenGlFBO2.operator->();
1627 bindDefaultFbo (theDrawFbo);
1632 Standard_Integer left;
1633 Standard_Integer top;
1634 Standard_Integer right;
1635 Standard_Integer bottom;
1636 Standard_Integer dx() { return right - left; }
1637 Standard_Integer dy() { return bottom - top; }
1640 myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom);
1642 Standard_Boolean toReverse = myRenderParams.ToReverseStereo;
1643 const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1;
1644 const Standard_Boolean isOddX = aGeom.left % 2 == 1;
1646 && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
1647 || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1649 toReverse = !toReverse;
1652 && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
1653 || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1655 toReverse = !toReverse;
1660 std::swap (aPair[0], aPair[1]);
1663 aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1664 aCtx->core20fwd->glDepthMask (GL_TRUE);
1665 aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1667 myWorkspace->DisableTexture();
1668 OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
1670 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1671 if (aVerts->IsValid()
1672 && aManager->BindStereoProgram (myRenderParams.StereoMode))
1674 if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
1676 OpenGl_Mat4 aFilterL, aFilterR;
1677 aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1678 aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1679 switch (myRenderParams.AnaglyphFilter)
1681 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
1683 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1684 aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1685 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1688 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
1690 aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f));
1691 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f));
1692 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f));
1693 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1694 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
1695 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f));
1696 aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f));
1697 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1700 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
1702 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1703 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1704 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1707 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
1709 aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f));
1710 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f));
1711 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f));
1712 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1713 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
1714 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f));
1715 aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f));
1716 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1719 case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
1721 aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1722 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1723 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1726 case Graphic3d_RenderingParams::Anaglyph_UserDefined:
1728 aFilterL = myRenderParams.AnaglyphLeft;
1729 aFilterR = myRenderParams.AnaglyphRight;
1733 aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL);
1734 aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
1737 aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
1738 aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1739 aVerts->BindVertexAttrib (aCtx, 0);
1741 aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1743 aVerts->UnbindVertexAttrib (aCtx, 0);
1744 aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1745 aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0);
1749 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1750 + "Error! Anaglyph has failed";
1751 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1752 GL_DEBUG_TYPE_ERROR,
1754 GL_DEBUG_SEVERITY_HIGH,
1759 // =======================================================================
1760 // function : copyBackToFront
1762 // =======================================================================
1763 void OpenGl_View::copyBackToFront()
1765 #if !defined(GL_ES_VERSION_2_0)
1767 OpenGl_Mat4 aProjectMat;
1768 Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1769 0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height()));
1771 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1772 aCtx->WorldViewState.Push();
1773 aCtx->ProjectionState.Push();
1775 aCtx->WorldViewState.SetIdentity();
1776 aCtx->ProjectionState.SetCurrent (aProjectMat);
1778 aCtx->ApplyProjectionMatrix();
1779 aCtx->ApplyWorldViewMatrix();
1781 aCtx->DisableFeatures();
1783 switch (aCtx->DrawBuffer())
1787 aCtx->SetReadBuffer (GL_BACK_LEFT);
1788 aCtx->SetDrawBuffer (GL_FRONT_LEFT);
1793 aCtx->SetReadBuffer (GL_BACK_RIGHT);
1794 aCtx->SetDrawBuffer (GL_FRONT_RIGHT);
1799 aCtx->SetReadBuffer (GL_BACK);
1800 aCtx->SetDrawBuffer (GL_FRONT);
1805 glRasterPos2i (0, 0);
1806 glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR);
1807 //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1809 aCtx->EnableFeatures();
1811 aCtx->WorldViewState.Pop();
1812 aCtx->ProjectionState.Pop();
1813 aCtx->ApplyProjectionMatrix();
1815 // read/write from front buffer now
1816 aCtx->SetReadBuffer (aCtx->DrawBuffer());
1818 myIsImmediateDrawn = Standard_False;