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>
21 #include <Graphic3d_GraphicDriver.hxx>
22 #include <Graphic3d_TextureParams.hxx>
23 #include <Graphic3d_Texture2Dmanual.hxx>
24 #include <Graphic3d_TransformUtils.hxx>
25 #include <Image_AlienPixMap.hxx>
27 #include <NCollection_Mat4.hxx>
29 #include <OpenGl_AspectLine.hxx>
30 #include <OpenGl_Context.hxx>
31 #include <OpenGl_Matrix.hxx>
32 #include <OpenGl_Workspace.hxx>
33 #include <OpenGl_View.hxx>
34 #include <OpenGl_Trihedron.hxx>
35 #include <OpenGl_GraduatedTrihedron.hxx>
36 #include <OpenGl_PrimitiveArray.hxx>
37 #include <OpenGl_PrinterContext.hxx>
38 #include <OpenGl_ShaderManager.hxx>
39 #include <OpenGl_ShaderProgram.hxx>
40 #include <OpenGl_Structure.hxx>
41 #include <OpenGl_ArbFBO.hxx>
47 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
48 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
49 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
50 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
53 extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
55 #if !defined(GL_ES_VERSION_2_0)
57 //=======================================================================
58 //function : bindLight
60 //=======================================================================
61 static void bindLight (const OpenGl_Light& theLight,
63 Graphic3d_Vec4& theAmbientColor,
64 const Handle(OpenGl_Workspace)& theWorkspace)
66 // Only 8 lights in OpenGL...
67 if (theLightGlId > GL_LIGHT7)
72 if (theLight.Type == Graphic3d_TOLS_AMBIENT)
74 // add RGBA intensity of the ambient light
75 theAmbientColor += theLight.Color;
79 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
81 // the light is a headlight?
82 if (theLight.IsHeadlight)
84 aContext->WorldViewState.Push();
85 aContext->WorldViewState.SetIdentity();
87 aContext->ApplyWorldViewMatrix();
91 switch (theLight.Type)
93 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
94 case Graphic3d_TOLS_DIRECTIONAL:
96 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
97 const OpenGl_Vec4 anInfDir = -theLight.Direction;
99 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
100 glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
101 glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
102 glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
103 glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
104 glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
105 glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
106 glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
109 case Graphic3d_TOLS_POSITIONAL:
111 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
112 glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
113 glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
114 glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
115 glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData());
116 glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
117 glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
118 glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
119 glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
120 glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
121 glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
124 case Graphic3d_TOLS_SPOT:
126 glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
127 glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
128 glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
129 glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData());
130 glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.Direction.GetData());
131 glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
132 glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
133 glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
134 glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
135 glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
140 // restore matrix in case of headlight
141 if (theLight.IsHeadlight)
143 aContext->WorldViewState.Pop();
146 glEnable (theLightGlId++);
150 //=======================================================================
151 //function : drawBackground
153 //=======================================================================
154 void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
156 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
158 if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background
159 || (!myBgTextureArray->IsDefined() // no texture
160 && !myBgGradientArray->IsDefined())) // no gradient
165 const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False);
168 aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
171 aCtx->ProjectionState.Push();
172 aCtx->WorldViewState.Push();
173 aCtx->ModelWorldState.Push();
174 aCtx->ProjectionState.SetIdentity();
175 aCtx->WorldViewState.SetIdentity();
176 aCtx->ModelWorldState.SetIdentity();
177 aCtx->ApplyProjectionMatrix();
178 aCtx->ApplyModelViewMatrix();
180 // Drawing background gradient if:
181 // - gradient fill type is not Aspect_GFM_NONE and
182 // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
183 if (myBgGradientArray->IsDefined()
184 && (!myTextureParams->DoTextureMap()
185 || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED
186 || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE))
188 #if !defined(GL_ES_VERSION_2_0)
189 GLint aShadingModelOld = GL_SMOOTH;
190 if (aCtx->core11 != NULL)
192 aCtx->core11fwd->glDisable (GL_LIGHTING);
193 aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld);
194 aCtx->core11->glShadeModel (GL_SMOOTH);
198 if (myBgGradientArray->IsDataChanged())
200 myBgGradientArray->Init (theWorkspace);
203 myBgGradientArray->Render (theWorkspace);
205 #if !defined(GL_ES_VERSION_2_0)
206 if (aCtx->core11 != NULL)
208 aCtx->core11->glShadeModel (aShadingModelOld);
213 // Drawing background image if it is defined
214 // (texture is defined and fill type is not Aspect_FM_NONE)
215 if (myBgTextureArray->IsDefined()
216 && myTextureParams->DoTextureMap())
218 aCtx->core11fwd->glDisable (GL_BLEND);
220 const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams);
222 if (myBgTextureArray->IsDataChanged()
223 || myBgTextureArray->IsViewSizeChanged (theWorkspace))
225 myBgTextureArray->Init (theWorkspace);
228 myBgTextureArray->Render (theWorkspace);
231 theWorkspace->SetAspectFace (anOldAspectFace);
234 aCtx->ModelWorldState.Pop();
235 aCtx->WorldViewState.Pop();
236 aCtx->ProjectionState.Pop();
237 aCtx->ApplyProjectionMatrix();
238 aCtx->ApplyModelViewMatrix();
242 theWorkspace->SetUseZBuffer (Standard_True);
243 aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
247 //=======================================================================
250 //=======================================================================
251 void OpenGl_View::Redraw()
253 if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
254 && !myCaps->vboDisable
255 && !myCaps->keepArrayData)
259 myDeviceLostFlag = Standard_True;
262 myCaps->keepArrayData = Standard_True;
265 if (!myWorkspace->Activate())
270 myWindow->SetSwapInterval();
273 const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
274 Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
275 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
277 // release pending GL resources
278 aCtx->ReleaseDelayed();
280 // fetch OpenGl context state
283 // set resolution ratio
284 aCtx->SetResolutionRatio (RenderingParams().ResolutionRatio());
286 OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->();
287 bool toSwap = aCtx->IsRender()
288 && !aCtx->caps->buffersNoSwap
289 && aFrameBuffer == NULL;
291 Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width();
292 Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height();
294 // determine multisampling parameters
295 Standard_Integer aNbSamples = Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0);
298 aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
301 if ( aFrameBuffer == NULL
302 && !aCtx->DefaultFrameBuffer().IsNull()
303 && aCtx->DefaultFrameBuffer()->IsValid())
305 aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
309 && (myTransientDrawToFront
310 || aProjectType == Graphic3d_Camera::Projection_Stereo
313 if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
314 || myMainSceneFbos[0]->GetVPSizeY() != aSizeY
315 || myMainSceneFbos[0]->NbSamples() != aNbSamples)
317 // prepare FBOs containing main scene
318 // for further blitting and rendering immediate presentations on top
319 if (aCtx->core20fwd != NULL)
321 myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples);
323 if (!aCtx->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid())
325 myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
331 myMainSceneFbos [0]->Release (aCtx.operator->());
332 myMainSceneFbos [1]->Release (aCtx.operator->());
333 myImmediateSceneFbos[0]->Release (aCtx.operator->());
334 myImmediateSceneFbos[1]->Release (aCtx.operator->());
335 myMainSceneFbos [0]->ChangeViewport (0, 0);
336 myMainSceneFbos [1]->ChangeViewport (0, 0);
337 myImmediateSceneFbos[0]->ChangeViewport (0, 0);
338 myImmediateSceneFbos[1]->ChangeViewport (0, 0);
341 if (aProjectType == Graphic3d_Camera::Projection_Stereo
342 && myMainSceneFbos[0]->IsValid())
344 myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]);
345 if (!myMainSceneFbos[1]->IsValid())
348 aProjectType = Graphic3d_Camera::Projection_Perspective;
350 else if (!myTransientDrawToFront)
354 else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
356 myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
357 myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]);
358 if (!myImmediateSceneFbos[0]->IsValid()
359 || !myImmediateSceneFbos[1]->IsValid())
361 aProjectType = Graphic3d_Camera::Projection_Perspective;
366 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
368 OpenGl_FrameBuffer* aMainFbos[2] =
370 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
371 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
373 OpenGl_FrameBuffer* anImmFbos[2] =
375 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
376 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
379 if (!myTransientDrawToFront)
381 anImmFbos[0] = aMainFbos[0];
382 anImmFbos[1] = aMainFbos[1];
384 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
385 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
391 #if !defined(GL_ES_VERSION_2_0)
392 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
394 redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]);
395 myBackBufferRestored = Standard_True;
396 myIsImmediateDrawn = Standard_False;
397 #if !defined(GL_ES_VERSION_2_0)
398 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
400 if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0]))
404 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap)
409 #if !defined(GL_ES_VERSION_2_0)
410 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
412 redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]);
413 myBackBufferRestored = Standard_True;
414 myIsImmediateDrawn = Standard_False;
415 if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1]))
420 if (anImmFbos[0] != NULL)
422 drawStereoPair (aFrameBuffer);
427 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
428 OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
429 if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
431 anImmFbo = myImmediateSceneFbos[0].operator->();
434 #if !defined(GL_ES_VERSION_2_0)
436 && aFrameBuffer == NULL)
438 aCtx->SetReadDrawBuffer (GL_BACK);
441 redraw (aProjectType, aMainFbo != NULL ? aMainFbo : aFrameBuffer);
442 myBackBufferRestored = Standard_True;
443 myIsImmediateDrawn = Standard_False;
444 if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo))
450 && anImmFbo != aFrameBuffer)
452 blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
456 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
457 if (OpenGl_AVIWriter_AllowWriting (myWindow->PlatformWindow()->NativeHandle()))
460 glGetIntegerv (GL_VIEWPORT, params);
461 int nWidth = params[2] & ~0x7;
462 int nHeight = params[3] & ~0x7;
464 const int nBitsPerPixel = 24;
465 GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
467 glPixelStorei (GL_PACK_ALIGNMENT, 1);
468 glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
469 OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
474 if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
475 && myRenderParams.IsGlobalIlluminationEnabled)
487 if (!myMainSceneFbos[0]->IsValid())
489 myBackBufferRestored = Standard_False;
494 aCtx->core11fwd->glFlush();
497 // reset render mode state
500 myWasRedrawnGL = Standard_True;
503 // =======================================================================
504 // function : RedrawImmediate
506 // =======================================================================
507 void OpenGl_View::RedrawImmediate()
509 if (!myWorkspace->Activate())
512 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
513 if (!myTransientDrawToFront
514 || !myBackBufferRestored
515 || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
521 const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
522 Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
523 OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->();
525 if ( aFrameBuffer == NULL
526 && !aCtx->DefaultFrameBuffer().IsNull()
527 && aCtx->DefaultFrameBuffer()->IsValid())
529 aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
532 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
534 if (myMainSceneFbos[0]->IsValid()
535 && !myMainSceneFbos[1]->IsValid())
537 aProjectType = Graphic3d_Camera::Projection_Perspective;
542 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
544 OpenGl_FrameBuffer* aMainFbos[2] =
546 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
547 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
549 OpenGl_FrameBuffer* anImmFbos[2] =
551 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
552 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
554 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
555 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
561 if (aCtx->arbFBO != NULL)
563 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
565 #if !defined(GL_ES_VERSION_2_0)
566 if (anImmFbos[0] == NULL)
568 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
571 toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
574 Standard_True) || toSwap;
575 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
577 && !aCtx->caps->buffersNoSwap)
582 if (aCtx->arbFBO != NULL)
584 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
586 #if !defined(GL_ES_VERSION_2_0)
587 if (anImmFbos[1] == NULL)
589 aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
592 toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
595 Standard_True) || toSwap;
596 if (anImmFbos[0] != NULL)
598 drawStereoPair (aFrameBuffer);
603 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
604 OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
605 if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
607 anImmFbo = myImmediateSceneFbos[0].operator->();
609 #if !defined(GL_ES_VERSION_2_0)
610 if (aMainFbo == NULL)
612 aCtx->SetReadDrawBuffer (GL_BACK);
615 toSwap = redrawImmediate (aProjectType,
618 Standard_True) || toSwap;
620 && anImmFbo != aFrameBuffer)
622 blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
629 if (toSwap && !aCtx->caps->buffersNoSwap)
635 aCtx->core11fwd->glFlush();
638 myWasRedrawnGL = Standard_True;
641 // =======================================================================
644 // =======================================================================
645 void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo)
647 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
648 if (theReadDrawFbo != NULL)
650 theReadDrawFbo->BindBuffer (aCtx);
651 theReadDrawFbo->SetupViewport (aCtx);
655 aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
658 // request reset of material
659 myWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
660 myWorkspace->UseZBuffer() = Standard_True;
661 myWorkspace->UseDepthWrite() = Standard_True;
662 GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
663 glDepthFunc (GL_LEQUAL);
664 glDepthMask (GL_TRUE);
665 glEnable (GL_DEPTH_TEST);
667 #if !defined(GL_ES_VERSION_2_0)
670 glClearDepthf (1.0f);
673 if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK)
675 // set background to white
676 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
680 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
685 render (theProjection, theReadDrawFbo, Standard_False);
688 // =======================================================================
689 // function : redrawMonoImmediate
691 // =======================================================================
692 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
693 OpenGl_FrameBuffer* theReadFbo,
694 OpenGl_FrameBuffer* theDrawFbo,
695 const Standard_Boolean theIsPartialUpdate)
697 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
698 GLboolean toCopyBackToFront = GL_FALSE;
699 if (!myTransientDrawToFront)
701 myBackBufferRestored = Standard_False;
703 else if (theReadFbo != NULL
704 && theReadFbo->IsValid()
707 if (!blitBuffers (theReadFbo, theDrawFbo))
712 else if (theDrawFbo == NULL)
714 #if !defined(GL_ES_VERSION_2_0)
715 aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
717 if (toCopyBackToFront)
719 if (!HasImmediateStructures()
720 && !theIsPartialUpdate)
722 // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
729 myBackBufferRestored = Standard_False;
734 myBackBufferRestored = Standard_False;
736 myIsImmediateDrawn = Standard_True;
738 myWorkspace->UseZBuffer() = Standard_True;
739 myWorkspace->UseDepthWrite() = Standard_True;
740 glDepthFunc (GL_LEQUAL);
741 glDepthMask (GL_TRUE);
742 glEnable (GL_DEPTH_TEST);
743 #if !defined(GL_ES_VERSION_2_0)
746 glClearDepthf (1.0f);
749 render (theProjection, theDrawFbo, Standard_True);
751 return !toCopyBackToFront;
754 //=======================================================================
757 //=======================================================================
758 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
759 OpenGl_FrameBuffer* theOutputFBO,
760 const Standard_Boolean theToDrawImmediate)
762 // ==================================
763 // Step 1: Prepare for render
764 // ==================================
766 const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
768 #if !defined(GL_ES_VERSION_2_0)
769 // Disable current clipping planes
770 if (aContext->core11 != NULL)
772 const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
773 for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
775 aContext->core11fwd->glDisable (aClipPlaneId);
780 // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
781 myBVHSelector.SetViewVolume (myCamera);
783 const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager();
784 if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
786 aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &OpenGl_NoShadingLight() : &myLights);
787 myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
790 // Update matrices if camera has changed.
791 Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState();
792 const Standard_Boolean isCameraChanged = myWorldViewProjState != aWVPState;
793 const Standard_Boolean isSameView = aManager->IsSameView (this);
796 aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
797 aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF());
801 // Apply new matrix state if camera has changed or this view differs from the one
802 // that was previously used for configuring matrices of shader manager
803 // (ApplyProjectionMatrix and ApplyWorldViewMatrix will affect the manager).
804 if (isCameraChanged || !isSameView)
806 aContext->ApplyProjectionMatrix();
807 aContext->ApplyWorldViewMatrix();
810 if (aManager->ModelWorldState().Index() == 0)
812 aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
815 myWorldViewProjState = aWVPState;
817 // ====================================
818 // Step 2: Redraw background
819 // ====================================
822 if (!theToDrawImmediate)
824 drawBackground (myWorkspace);
827 #if !defined(GL_ES_VERSION_2_0)
828 // Switch off lighting by default
829 if (aContext->core11 != NULL)
831 glDisable(GL_LIGHTING);
835 // =================================
836 // Step 3: Redraw main plane
837 // =================================
839 // Setup face culling
840 GLboolean isCullFace = GL_FALSE;
841 if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
843 isCullFace = glIsEnabled (GL_CULL_FACE);
844 if (myBackfacing == Graphic3d_TOBM_DISABLE)
846 glEnable (GL_CULL_FACE);
847 glCullFace (GL_BACK);
850 glDisable (GL_CULL_FACE);
853 #if !defined(GL_ES_VERSION_2_0)
854 // if the view is scaled normal vectors are scaled to unit
855 // length for correct displaying of shaded objects
856 const gp_Pnt anAxialScale = myCamera->AxialScale();
857 if (anAxialScale.X() != 1.F ||
858 anAxialScale.Y() != 1.F ||
859 anAxialScale.Z() != 1.F)
861 aContext->SetGlNormalizeEnabled (Standard_True);
865 aContext->SetGlNormalizeEnabled (Standard_False);
870 && aContext->core11 != NULL)
872 Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
873 if (myCamera->ZFar() < aFogFrontConverted)
875 aFogFrontConverted = myCamera->ZFar();
876 myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
879 Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
880 if (myCamera->ZFar() < aFogFrontConverted)
882 aFogBackConverted = myCamera->ZFar();
883 myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
886 if (aFogFrontConverted > aFogBackConverted)
888 myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
889 myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
892 glFogi(GL_FOG_MODE, GL_LINEAR);
893 glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted);
894 glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted);
895 glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
898 else if (aContext->core11 != NULL)
903 // Apply InteriorShadingMethod
904 if (aContext->core11 != NULL)
906 aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET
907 || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH);
911 aManager->SetShadingModel (myShadingModel);
913 // Apply AntiAliasing
915 myWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
917 myWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
919 if (!aManager->IsEmpty())
921 aManager->UpdateClippingState();
925 if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
927 aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
928 aContext->ApplyProjectionMatrix();
930 else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
932 aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
933 aContext->ApplyProjectionMatrix();
936 myWorkspace->SetEnvironmentTexture (myTextureEnv);
938 renderScene (theProjection, theOutputFBO, theToDrawImmediate);
940 myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
942 // ===============================
944 // ===============================
946 // Resetting GL parameters according to the default aspects
947 // in order to synchronize GL state with the graphic driver state
948 // before drawing auxiliary stuff (trihedrons, overlayer)
949 myWorkspace->ResetAppliedAspect();
951 aContext->ChangeClipping().RemoveAll (aContext);
953 if (!aManager->IsEmpty())
955 aManager->ResetMaterialStates();
956 aManager->RevertClippingState();
958 // We need to disable (unbind) all shaders programs to ensure
959 // that all objects without specified aspect will be drawn
960 // correctly (such as background)
961 aContext->BindProgram (NULL);
965 if (!theToDrawImmediate)
967 renderTrihedron (myWorkspace);
969 // Restore face culling
970 if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
974 glEnable (GL_CULL_FACE);
975 glCullFace (GL_BACK);
978 glDisable (GL_CULL_FACE);
982 // ==============================================================
983 // Step 6: Keep shader manager informed about last View
984 // ==============================================================
986 if (!aManager.IsNull())
988 aManager->SetLastView (this);
992 // =======================================================================
993 // function : InvalidateBVHData
995 // =======================================================================
996 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
998 myZLayers.InvalidateBVHData (theLayerId);
1001 //=======================================================================
1002 //function : renderStructs
1004 //=======================================================================
1005 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
1006 OpenGl_FrameBuffer* theReadDrawFbo,
1007 const Standard_Boolean theToDrawImmediate)
1009 if ( myZLayers.NbStructures() <= 0 )
1012 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1013 if ( (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
1015 #if !defined(GL_ES_VERSION_2_0)
1016 const int anAntiAliasingMode = myWorkspace->AntiAliasingMode();
1019 if ( !myAntiAliasing )
1021 #if !defined(GL_ES_VERSION_2_0)
1022 if (aCtx->core11 != NULL)
1024 glDisable (GL_POINT_SMOOTH);
1026 glDisable(GL_LINE_SMOOTH);
1027 if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1029 glBlendFunc (GL_ONE, GL_ZERO);
1030 glDisable (GL_BLEND);
1034 #if !defined(GL_ES_VERSION_2_0)
1035 if (aCtx->core11 != NULL)
1037 glEnable(GL_POINT_SMOOTH);
1039 glEnable(GL_LINE_SMOOTH);
1040 if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1042 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1043 glEnable (GL_BLEND);
1047 Standard_Boolean toRenderGL = theToDrawImmediate ||
1048 myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
1049 myRaytraceInitStatus == OpenGl_RT_FAIL ||
1054 toRenderGL = !initRaytraceResources (aCtx) ||
1055 !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx);
1057 toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
1061 const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width();
1062 const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height();
1063 myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0);
1065 if (myRaytraceFilter.IsNull())
1066 myRaytraceFilter = new OpenGl_RaytraceFilter;
1068 myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter());
1070 if (theReadDrawFbo != NULL)
1071 theReadDrawFbo->UnbindBuffer (aCtx);
1073 // Prepare preliminary OpenGL output
1074 if (aCtx->arbFBOBlit != NULL)
1076 // Render bottom OSD layer
1077 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
1079 myWorkspace->SetRenderFilter (myRaytraceFilter);
1081 if (theReadDrawFbo != NULL)
1083 theReadDrawFbo->BindReadBuffer (aCtx);
1087 aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
1090 myOpenGlFBO->BindDrawBuffer (aCtx);
1092 aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY,
1093 0, 0, aSizeX, aSizeY,
1094 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
1097 // Render non-polygonal elements in default layer
1098 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default);
1100 myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
1103 if (theReadDrawFbo != NULL)
1105 theReadDrawFbo->BindBuffer (aCtx);
1109 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0);
1112 // Reset OpenGl aspects state to default to avoid enabling of
1113 // backface culling which is not supported in ray-tracing.
1114 myWorkspace->ResetAppliedAspect();
1116 // Ray-tracing polygonal primitive arrays
1117 raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
1119 // Render upper (top and topmost) OpenGL layers
1120 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
1124 // Redraw 3D scene using OpenGL in standard
1125 // mode or in case of ray-tracing failure
1128 myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All);
1130 // Set flag that scene was redrawn by standard pipeline
1131 myWasRedrawnGL = Standard_True;
1135 //=======================================================================
1136 //function : renderTrihedron
1138 //=======================================================================
1139 void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
1141 // display global trihedron
1142 if (myToShowTrihedron)
1144 // disable environment texture
1145 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
1146 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
1148 myTrihedron.Render (theWorkspace);
1150 // restore environment texture
1151 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
1153 if (myToShowGradTrihedron)
1155 myGraduatedTrihedron.Render (theWorkspace);
1159 // =======================================================================
1160 // function : Invalidate
1162 // =======================================================================
1163 void OpenGl_View::Invalidate()
1165 myBackBufferRestored = Standard_False;
1168 //=======================================================================
1169 //function : renderScene
1171 //=======================================================================
1172 void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
1173 OpenGl_FrameBuffer* theReadDrawFbo,
1174 const Standard_Boolean theToDrawImmediate)
1176 const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
1178 if (myZClip.Back.IsOn || myZClip.Front.IsOn)
1180 Handle(Graphic3d_ClipPlane) aPlaneBack;
1181 Handle(Graphic3d_ClipPlane) aPlaneFront;
1183 if (myZClip.Back.IsOn)
1185 Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1186 if (myCamera->ZFar() < aClipBackConverted)
1188 aClipBackConverted = myCamera->ZFar();
1189 myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance());
1191 const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted);
1192 aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
1195 if (myZClip.Front.IsOn)
1197 Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1198 if (myCamera->ZNear() > aClipFrontConverted)
1200 aClipFrontConverted = myCamera->ZNear();
1201 myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance());
1203 const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted);
1204 aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
1207 // Specify slicing planes with identity transformation
1208 if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
1210 Graphic3d_SequenceOfHClipPlane aSlicingPlanes;
1211 if (!aPlaneBack.IsNull())
1213 aSlicingPlanes.Append (aPlaneBack);
1216 if (!aPlaneFront.IsNull())
1218 aSlicingPlanes.Append (aPlaneFront);
1221 // add planes at loaded view matrix state
1222 aContext->ChangeClipping().AddView (aContext, aSlicingPlanes);
1227 // set printing scale/tiling transformation
1228 Handle(OpenGl_PrinterContext) aPrintContext = myWorkspace->PrinterContext();
1229 if (!aPrintContext.IsNull())
1231 aContext->ProjectionState.Push();
1232 aContext->ProjectionState.SetCurrent (aPrintContext->ProjTransformation() * aContext->ProjectionState.Current());
1233 aContext->ApplyProjectionMatrix();
1237 // Specify clipping planes in view transformation space
1238 if (!myClipPlanes.IsEmpty())
1240 Graphic3d_SequenceOfHClipPlane aUserPlanes;
1241 Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1242 for (; aClippingIt.More(); aClippingIt.Next())
1244 const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1245 if (aClipPlane->IsOn())
1247 aUserPlanes.Append (aClipPlane);
1251 if (!aUserPlanes.IsEmpty())
1253 aContext->ChangeClipping().AddWorldLazy (aContext, aUserPlanes);
1256 if (!aContext->ShaderManager()->IsEmpty())
1258 aContext->ShaderManager()->UpdateClippingState();
1262 #if !defined(GL_ES_VERSION_2_0)
1264 if (aContext->core11 != NULL)
1267 Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
1268 THE_DEFAULT_AMBIENT[1],
1269 THE_DEFAULT_AMBIENT[2],
1270 THE_DEFAULT_AMBIENT[3]);
1271 GLenum aLightGlId = GL_LIGHT0;
1273 OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? OpenGl_NoShadingLight() : myLights);
1274 for (; aLightIt.More(); aLightIt.Next())
1276 bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace);
1279 // apply accumulated ambient color
1280 anAmbientColor.a() = 1.0f;
1281 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
1283 if (aLightGlId != GL_LIGHT0)
1285 glEnable (GL_LIGHTING);
1287 // switch off unused lights
1288 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
1290 glDisable (aLightGlId);
1295 // Clear status bitfields
1296 myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1299 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1300 myWorkspace->DisableTexture();
1303 if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1305 myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1307 // Remember OpenGl properties
1308 GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
1309 GLint aSaveZbuffFunc;
1310 GLboolean aSaveZbuffWrite;
1311 glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
1312 glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
1313 #if !defined(GL_ES_VERSION_2_0)
1314 glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
1315 glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
1317 GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
1318 GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
1320 // Change the properties for second rendering pass
1321 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1322 glEnable (GL_BLEND);
1324 glDepthFunc (GL_EQUAL);
1325 glDepthMask (GL_FALSE);
1326 glEnable (GL_DEPTH_TEST);
1329 renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1330 myWorkspace->DisableTexture();
1332 // Restore properties back
1333 glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
1334 if (!wasBlendEnabled)
1335 glDisable (GL_BLEND);
1337 glDepthFunc (aSaveZbuffFunc);
1338 glDepthMask (aSaveZbuffWrite);
1339 if (!wasZbuffEnabled)
1340 glDisable (GL_DEPTH_FUNC);
1343 // Apply restored view matrix.
1344 aContext->ApplyWorldViewMatrix();
1347 // set printing scale/tiling transformation
1348 if (!aPrintContext.IsNull())
1350 aContext->ProjectionState.Pop();
1351 aContext->ApplyProjectionMatrix();
1356 // =======================================================================
1357 // function : bindDefaultFbo
1359 // =======================================================================
1360 void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
1362 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1363 OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
1365 : (!aCtx->DefaultFrameBuffer().IsNull()
1366 && aCtx->DefaultFrameBuffer()->IsValid()
1367 ? aCtx->DefaultFrameBuffer().operator->()
1371 anFbo->BindBuffer (aCtx);
1375 #if !defined(GL_ES_VERSION_2_0)
1376 aCtx->SetReadDrawBuffer (GL_BACK);
1378 if (aCtx->arbFBO != NULL)
1380 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1384 aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
1387 // =======================================================================
1388 // function : initBlitQuad
1390 // =======================================================================
1391 OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip)
1393 OpenGl_VertexBuffer* aVerts = NULL;
1396 aVerts = &myFullScreenQuad;
1397 if (!aVerts->IsValid())
1399 OpenGl_Vec4 aQuad[4] =
1401 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1402 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f),
1403 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1404 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f)
1406 aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1411 aVerts = &myFullScreenQuadFlip;
1412 if (!aVerts->IsValid())
1414 OpenGl_Vec4 aQuad[4] =
1416 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f),
1417 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f),
1418 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1419 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f)
1421 aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1427 // =======================================================================
1428 // function : blitBuffers
1430 // =======================================================================
1431 bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
1432 OpenGl_FrameBuffer* theDrawFbo,
1433 const Standard_Boolean theToFlip)
1435 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1436 if (theReadFbo == NULL || aCtx->IsFeedback())
1440 else if (theReadFbo == theDrawFbo)
1445 // clear destination before blitting
1446 if (theDrawFbo != NULL
1447 && theDrawFbo->IsValid())
1449 theDrawFbo->BindBuffer (aCtx);
1453 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1455 #if !defined(GL_ES_VERSION_2_0)
1456 aCtx->core20fwd->glClearDepth (1.0);
1458 aCtx->core20fwd->glClearDepthf (1.0f);
1460 aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1462 #if !defined(GL_ES_VERSION_2_0)
1463 if (aCtx->arbFBOBlit != NULL
1464 && theReadFbo->NbSamples() != 0)
1466 GLbitfield aCopyMask = 0;
1467 theReadFbo->BindReadBuffer (aCtx);
1468 if (theDrawFbo != NULL
1469 && theDrawFbo->IsValid())
1471 theDrawFbo->BindDrawBuffer (aCtx);
1472 if (theDrawFbo->HasColor()
1473 && theReadFbo->HasColor())
1475 aCopyMask |= GL_COLOR_BUFFER_BIT;
1477 if (theDrawFbo->HasDepth()
1478 && theReadFbo->HasDepth())
1480 aCopyMask |= GL_DEPTH_BUFFER_BIT;
1485 if (theReadFbo->HasColor())
1487 aCopyMask |= GL_COLOR_BUFFER_BIT;
1489 if (theReadFbo->HasDepth())
1491 aCopyMask |= GL_DEPTH_BUFFER_BIT;
1493 aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1496 // we don't copy stencil buffer here... does it matter for performance?
1497 aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1498 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1499 aCopyMask, GL_NEAREST);
1500 if (theDrawFbo != NULL
1501 && theDrawFbo->IsValid())
1503 theDrawFbo->BindBuffer (aCtx);
1507 aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1513 aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1514 aCtx->core20fwd->glDepthMask (GL_TRUE);
1515 aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1517 myWorkspace->DisableTexture();
1519 OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
1520 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1521 if (aVerts->IsValid()
1522 && aManager->BindFboBlitProgram())
1524 theReadFbo->ColorTexture() ->Bind (aCtx, GL_TEXTURE0 + 0);
1525 theReadFbo->DepthStencilTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1526 aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1528 aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1530 aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1531 theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1532 theReadFbo->ColorTexture() ->Unbind (aCtx, GL_TEXTURE0 + 0);
1533 aCtx->BindProgram (NULL);
1537 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1538 + "Error! FBO blitting has failed";
1539 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1540 GL_DEBUG_TYPE_ERROR,
1542 GL_DEBUG_SEVERITY_HIGH,
1544 myHasFboBlit = Standard_False;
1545 theReadFbo->Release (aCtx.operator->());
1552 // =======================================================================
1553 // function : drawStereoPair
1555 // =======================================================================
1556 void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
1558 const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
1559 bindDefaultFbo (theDrawFbo);
1560 OpenGl_FrameBuffer* aPair[2] =
1562 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1563 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1565 if (aPair[0] == NULL
1567 || !myTransientDrawToFront)
1569 aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1570 aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
1573 if (aPair[0] == NULL
1574 || aPair[1] == NULL)
1579 if (aPair[0]->NbSamples() != 0)
1581 // resolve MSAA buffers before drawing
1582 if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0)
1583 || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0))
1585 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1586 GL_DEBUG_TYPE_ERROR,
1588 GL_DEBUG_SEVERITY_HIGH,
1589 "Error! Unable to allocate FBO for blitting stereo pair");
1590 bindDefaultFbo (theDrawFbo);
1594 if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False)
1595 || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False))
1597 bindDefaultFbo (theDrawFbo);
1601 aPair[0] = myOpenGlFBO .operator->();
1602 aPair[1] = myOpenGlFBO2.operator->();
1603 bindDefaultFbo (theDrawFbo);
1608 Standard_Integer left;
1609 Standard_Integer top;
1610 Standard_Integer right;
1611 Standard_Integer bottom;
1612 Standard_Integer dx() { return right - left; }
1613 Standard_Integer dy() { return bottom - top; }
1616 myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom);
1618 Standard_Boolean toReverse = myRenderParams.ToReverseStereo;
1619 const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1;
1620 const Standard_Boolean isOddX = aGeom.left % 2 == 1;
1622 && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
1623 || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1625 toReverse = !toReverse;
1628 && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
1629 || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1631 toReverse = !toReverse;
1636 std::swap (aPair[0], aPair[1]);
1639 aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1640 aCtx->core20fwd->glDepthMask (GL_TRUE);
1641 aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1643 myWorkspace->DisableTexture();
1644 OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
1646 const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1647 if (aVerts->IsValid()
1648 && aManager->BindStereoProgram (myRenderParams.StereoMode))
1650 if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
1652 OpenGl_Mat4 aFilterL, aFilterR;
1653 aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1654 aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1655 switch (myRenderParams.AnaglyphFilter)
1657 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
1659 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1660 aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1661 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1664 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
1666 aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f));
1667 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f));
1668 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f));
1669 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1670 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
1671 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f));
1672 aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f));
1673 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1676 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
1678 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1679 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1680 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1683 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
1685 aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f));
1686 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f));
1687 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f));
1688 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1689 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
1690 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f));
1691 aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f));
1692 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
1695 case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
1697 aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1698 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1699 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1702 case Graphic3d_RenderingParams::Anaglyph_UserDefined:
1704 aFilterL = myRenderParams.AnaglyphLeft;
1705 aFilterR = myRenderParams.AnaglyphRight;
1709 aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL);
1710 aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
1713 aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
1714 aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1715 aVerts->BindVertexAttrib (aCtx, 0);
1717 aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1719 aVerts->UnbindVertexAttrib (aCtx, 0);
1720 aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1721 aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0);
1725 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1726 + "Error! Anaglyph has failed";
1727 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1728 GL_DEBUG_TYPE_ERROR,
1730 GL_DEBUG_SEVERITY_HIGH,
1735 // =======================================================================
1736 // function : copyBackToFront
1738 // =======================================================================
1739 void OpenGl_View::copyBackToFront()
1741 #if !defined(GL_ES_VERSION_2_0)
1743 OpenGl_Mat4 aProjectMat;
1744 Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1745 0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height()));
1747 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1748 aCtx->WorldViewState.Push();
1749 aCtx->ProjectionState.Push();
1751 aCtx->WorldViewState.SetIdentity();
1752 aCtx->ProjectionState.SetCurrent (aProjectMat);
1754 aCtx->ApplyProjectionMatrix();
1755 aCtx->ApplyWorldViewMatrix();
1757 aCtx->DisableFeatures();
1759 switch (aCtx->DrawBuffer())
1763 aCtx->SetReadBuffer (GL_BACK_LEFT);
1764 aCtx->SetDrawBuffer (GL_FRONT_LEFT);
1769 aCtx->SetReadBuffer (GL_BACK_RIGHT);
1770 aCtx->SetDrawBuffer (GL_FRONT_RIGHT);
1775 aCtx->SetReadBuffer (GL_BACK);
1776 aCtx->SetDrawBuffer (GL_FRONT);
1781 glRasterPos2i (0, 0);
1782 glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR);
1783 //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1785 aCtx->EnableFeatures();
1787 aCtx->WorldViewState.Pop();
1788 aCtx->ProjectionState.Pop();
1789 aCtx->ApplyProjectionMatrix();
1791 // read/write from front buffer now
1792 aCtx->SetReadBuffer (aCtx->DrawBuffer());
1794 myIsImmediateDrawn = Standard_False;