0026025: Visualization, TKOpenGl - stereoscopic output does not work
[occt.git] / src / OpenGl / OpenGl_View_2.cxx
index 010ea9e..3abea51 100644 (file)
@@ -19,6 +19,8 @@
 #include <OpenGl_GlCore11.hxx>
 #include <OpenGl_tgl_funcs.hxx>
 
+#include <Graphic3d_TextureParams.hxx>
+#include <Graphic3d_Texture2Dmanual.hxx>
 #include <Image_AlienPixMap.hxx>
 #include <Visual3d_Layer.hxx>
 
 #include <OpenGl_View.hxx>
 #include <OpenGl_Trihedron.hxx>
 #include <OpenGl_GraduatedTrihedron.hxx>
+#include <OpenGl_PrimitiveArray.hxx>
 #include <OpenGl_PrinterContext.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_ArbFBO.hxx>
 
 #define EPSI 0.0001
 
@@ -51,15 +55,6 @@ namespace
 extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
 
 /*----------------------------------------------------------------------*/
-
-struct OPENGL_CLIP_PLANE
-{
-  GLboolean isEnabled;
-  GLdouble Equation[4];
-  DEFINE_STANDARD_ALLOC
-};
-
-/*----------------------------------------------------------------------*/
 /*
 * Fonctions privees
 */
@@ -160,210 +155,102 @@ static void bindLight (const OpenGl_Light&             theLight,
 
 /*----------------------------------------------------------------------*/
 
-void OpenGl_View::DrawBackground (OpenGl_Workspace& theWorkspace)
+void OpenGl_View::DrawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
 {
-#if !defined(GL_ES_VERSION_2_0)
-  if ( (theWorkspace.NamedStatus & OPENGL_NS_WHITEBACK) == 0 &&
-       ( myBgTexture.TexId != 0 || myBgGradient.type != Aspect_GFM_NONE ) )
-  {
-    const Standard_Integer aViewWidth = theWorkspace.Width();
-    const Standard_Integer aViewHeight = theWorkspace.Height();
-
-    glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
-
-    const Handle(OpenGl_Context)& aContext = theWorkspace.GetGlContext();
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-    aContext->WorldViewState.Push();
-    aContext->ProjectionState.Push();
+  if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background
+    || (!myBgTextureArray->IsDefined()                       // no texture
+     && !myBgGradientArray->IsDefined()))                    // no gradient
+  {
+    return;
+  }
 
-    aContext->WorldViewState.SetIdentity();
-    aContext->ProjectionState.SetIdentity();
+  aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
+
+  aCtx->WorldViewState.Push();
+  aCtx->ProjectionState.Push();
+  aCtx->WorldViewState.SetIdentity();
+  aCtx->ProjectionState.SetIdentity();
+  aCtx->ApplyProjectionMatrix();
+  aCtx->ApplyWorldViewMatrix();
+
+  // Drawing background gradient if:
+  // - gradient fill type is not Aspect_GFM_NONE and
+  // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
+  if (myBgGradientArray->IsDefined()
+    && (!myTextureParams->DoTextureMap()
+      || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED
+      || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE))
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    GLint aShadingModelOld = GL_SMOOTH;
+    if (aCtx->core11 != NULL)
+    {
+      aCtx->core11fwd->glDisable (GL_LIGHTING);
+      aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld);
+      aCtx->core11->glShadeModel (GL_SMOOTH);
+    }
+  #endif
 
-    aContext->ApplyProjectionMatrix();
-    aContext->ApplyWorldViewMatrix();
+    if (myBgGradientArray->IsDataChanged())
+    {
+      myBgGradientArray->Init (theWorkspace);
+    }
 
-    if ( glIsEnabled( GL_DEPTH_TEST ) )
-      glDisable( GL_DEPTH_TEST ); //push GL_ENABLE_BIT
+    myBgGradientArray->Render (theWorkspace);
 
-    // drawing bg gradient if:
-    // - gradient fill type is not Aspect_GFM_NONE and
-    // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
-    if ( ( myBgGradient.type != Aspect_GFM_NONE ) &&
-      ( myBgTexture.TexId == 0 || myBgTexture.Style == Aspect_FM_CENTERED ||
-      myBgTexture.Style == Aspect_FM_NONE ) )
+  #if !defined(GL_ES_VERSION_2_0)
+    if (aCtx->core11 != NULL)
     {
-      Tfloat* corner1 = 0;/* -1,-1*/
-      Tfloat* corner2 = 0;/*  1,-1*/
-      Tfloat* corner3 = 0;/*  1, 1*/
-      Tfloat* corner4 = 0;/* -1, 1*/
-      Tfloat dcorner1[3];
-      Tfloat dcorner2[3];
-
-      switch( myBgGradient.type )
-      {
-      case Aspect_GFM_HOR:
-        corner1 = myBgGradient.color1.rgb;
-        corner2 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color2.rgb;
-        corner4 = myBgGradient.color1.rgb;
-        break;
-      case Aspect_GFM_VER:
-        corner1 = myBgGradient.color2.rgb;
-        corner2 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color1.rgb;
-        corner4 = myBgGradient.color1.rgb;
-        break;
-      case Aspect_GFM_DIAG1:
-        corner2 = myBgGradient.color2.rgb;
-        corner4 = myBgGradient.color1.rgb;
-        dcorner1 [0] = dcorner2[0] = 0.5F * (corner2[0] + corner4[0]);
-        dcorner1 [1] = dcorner2[1] = 0.5F * (corner2[1] + corner4[1]);
-        dcorner1 [2] = dcorner2[2] = 0.5F * (corner2[2] + corner4[2]);
-        corner1 = dcorner1;
-        corner3 = dcorner2;
-        break;
-      case Aspect_GFM_DIAG2:
-        corner1 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color1.rgb;
-        dcorner1 [0] = dcorner2[0] = 0.5F * (corner1[0] + corner3[0]);
-        dcorner1 [1] = dcorner2[1] = 0.5F * (corner1[1] + corner3[1]);
-        dcorner1 [2] = dcorner2[2] = 0.5F * (corner1[2] + corner3[2]);
-        corner2 = dcorner1;
-        corner4 = dcorner2;
-        break;
-      case Aspect_GFM_CORNER1:
-        corner1 = myBgGradient.color2.rgb;
-        corner2 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color2.rgb;
-        corner4 = myBgGradient.color1.rgb;
-        break;
-      case Aspect_GFM_CORNER2:
-        corner1 = myBgGradient.color2.rgb;
-        corner2 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color1.rgb;
-        corner4 = myBgGradient.color2.rgb;
-        break;
-      case Aspect_GFM_CORNER3:
-        corner1 = myBgGradient.color2.rgb;
-        corner2 = myBgGradient.color1.rgb;
-        corner3 = myBgGradient.color2.rgb;
-        corner4 = myBgGradient.color2.rgb;
-        break;
-      case Aspect_GFM_CORNER4:
-        corner1 = myBgGradient.color1.rgb;
-        corner2 = myBgGradient.color2.rgb;
-        corner3 = myBgGradient.color2.rgb;
-        corner4 = myBgGradient.color2.rgb;
-        break;
-      default:
-        //printf("gradient background type not right\n");
-        break;
-      }
+      aCtx->core11->glShadeModel (aShadingModelOld);
+    }
+  #endif
+  }
 
-      // Save GL parameters
-      glDisable( GL_LIGHTING ); //push GL_ENABLE_BIT
+  // Drawing background image if it is defined
+  // (texture is defined and fill type is not Aspect_FM_NONE)
+  if (myBgTextureArray->IsDefined()
+   && myTextureParams->DoTextureMap())
+  {
+    aCtx->core11fwd->glDisable (GL_BLEND);
 
-      GLint curSM;
-      glGetIntegerv( GL_SHADE_MODEL, &curSM );
-      if ( curSM != GL_SMOOTH )
-        glShadeModel( GL_SMOOTH ); //push GL_LIGHTING_BIT
+    const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams);
 
-      glBegin(GL_TRIANGLE_FAN);
-      if( myBgGradient.type != Aspect_GFM_CORNER1 && myBgGradient.type != Aspect_GFM_CORNER3 )
-      {
-        glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
-        glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
-        glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
-        glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
-      }
-      else //if ( myBgGradient.type == Aspect_GFM_CORNER1 || myBgGradient.type == Aspect_GFM_CORNER3 )
-      {
-        glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
-        glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
-        glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
-        glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
-      }
-      glEnd();
-
-      // Restore GL parameters
-      if ( curSM != GL_SMOOTH )
-        glShadeModel( curSM );
-    }
-    // drawing bg image if:
-    // - it is defined and
-    // - fill type is not Aspect_FM_NONE
-    if ( myBgTexture.TexId != 0 && myBgTexture.Style != Aspect_FM_NONE )
+    if (myBgTextureArray->IsDataChanged()
+     || myBgTextureArray->IsViewSizeChanged (theWorkspace))
     {
-      GLfloat texX_range = 1.F; // texture <s> coordinate
-      GLfloat texY_range = 1.F; // texture <t> coordinate
-
-      // Set up for stretching or tiling
-      GLfloat x_offset, y_offset;
-      if ( myBgTexture.Style == Aspect_FM_CENTERED )
-      {
-        x_offset = (GLfloat)myBgTexture.Width / (GLfloat)aViewWidth;
-        y_offset = (GLfloat)myBgTexture.Height / (GLfloat)aViewHeight;
-      }
-      else
-      {
-        x_offset = 1.F;
-        y_offset = 1.F;
-        if ( myBgTexture.Style == Aspect_FM_TILED )
-        {
-          texX_range = (GLfloat)aViewWidth / (GLfloat)myBgTexture.Width;
-          texY_range = (GLfloat)aViewHeight / (GLfloat)myBgTexture.Height;
-        }
-      }
-
-      // OCCT issue 0023000: Improve the way the gradient and textured
-      // background is managed in 3d viewer (note 0020339)
-      // Setting this coefficient to -1.F allows to tile textures relatively
-      // to the top-left corner of the view (value 1.F corresponds to the
-      // initial behaviour - tiling from the bottom-left corner)
-      GLfloat aCoef = -1.F;
-
-      glEnable( GL_TEXTURE_2D ); //push GL_ENABLE_BIT
-      glBindTexture( GL_TEXTURE_2D, myBgTexture.TexId ); //push GL_TEXTURE_BIT
-
-      glDisable( GL_BLEND ); //push GL_ENABLE_BIT
-
-      glColor3fv (theWorkspace.BackgroundColor().rgb);
-      glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //push GL_TEXTURE_BIT
-
-      // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
-      // is simply ignored, and negative multiplier is here for convenience only
-      // and does not result e.g. in texture mirroring
-      glBegin( GL_QUADS );
-      glTexCoord2f(0.F, 0.F); glVertex2f( -x_offset, -aCoef * y_offset );
-      glTexCoord2f(texX_range, 0.F); glVertex2f( x_offset, -aCoef * y_offset );
-      glTexCoord2f(texX_range, aCoef * texY_range); glVertex2f( x_offset, aCoef * y_offset );
-      glTexCoord2f(0.F, aCoef * texY_range); glVertex2f( -x_offset, aCoef * y_offset );
-      glEnd();
+      myBgTextureArray->Init (theWorkspace);
     }
 
-    aContext->WorldViewState.Pop();
-    aContext->ProjectionState.Pop();
+    myBgTextureArray->Render (theWorkspace);
 
-    aContext->ApplyProjectionMatrix();
+    // restore aspects
+    theWorkspace->SetAspectFace (anOldAspectFace);
+  }
 
-    glPopAttrib(); //GL_ENABLE_BIT | GL_TEXTURE_BIT
+  aCtx->WorldViewState.Pop();
+  aCtx->ProjectionState.Pop();
+  aCtx->ApplyProjectionMatrix();
+  aCtx->ApplyWorldViewMatrix();
 
-    if (theWorkspace.UseZBuffer())
-    {
-      glEnable (GL_DEPTH_TEST);
-    }
+  if (theWorkspace->UseZBuffer())
+  {
+    aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
   }
-#endif
 }
 
 /*----------------------------------------------------------------------*/
 
 //call_func_redraw_all_structs_proc
 void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
-                          const Handle(OpenGl_Workspace) &theWorkspace,
-                          const Graphic3d_CView& theCView,
-                          const Aspect_CLayer2d& theCUnderLayer,
-                          const Aspect_CLayer2d& theCOverLayer)
+                          const Handle(OpenGl_Workspace)&      theWorkspace,
+                          OpenGl_FrameBuffer*                  theOutputFBO,
+                          Graphic3d_Camera::Projection         theProjection,
+                          const Graphic3d_CView&               theCView,
+                          const Aspect_CLayer2d&               theCUnderLayer,
+                          const Aspect_CLayer2d&               theCOverLayer,
+                          const Standard_Boolean               theToDrawImmediate)
 {
   // ==================================
   //      Step 1: Prepare for redraw
@@ -372,24 +259,13 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
 
 #if !defined(GL_ES_VERSION_2_0)
-  // store and disable current clipping planes
-  const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
-  NCollection_Array1<OPENGL_CLIP_PLANE> aOldPlanes (GL_CLIP_PLANE0, GL_CLIP_PLANE0 + aMaxPlanes - 1);
+  // Disable current clipping planes
   if (aContext->core11 != NULL)
   {
-    for (Standard_Integer aClipPlaneId = aOldPlanes.Lower(); aClipPlaneId <= aOldPlanes.Upper(); ++aClipPlaneId)
+    const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
+    for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
     {
-      OPENGL_CLIP_PLANE& aPlane = aOldPlanes.ChangeValue (aClipPlaneId);
-      aContext->core11->glGetClipPlane (aClipPlaneId, aPlane.Equation);
-      if (aPlane.isEnabled)
-      {
-        aContext->core11fwd->glDisable (aClipPlaneId);
-        aPlane.isEnabled = GL_TRUE;
-      }
-      else
-      {
-        aPlane.isEnabled = GL_FALSE;
-      }
+      aContext->core11fwd->glDisable (aClipPlaneId);
     }
   }
 #endif
@@ -414,8 +290,8 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     myBVHSelector.SetViewVolume (myCamera);
   }
 
-  const Handle(OpenGl_ShaderManager) aManager   = aContext->ShaderManager();
-  const Standard_Boolean             isSameView = aManager->IsSameView (this); // force camera state update when needed
+  const Handle(OpenGl_ShaderManager)& aManager   = aContext->ShaderManager();
+  const Standard_Boolean              isSameView = aManager->IsSameView (this); // force camera state update when needed
   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
   {
     aManager->UpdateLightSourceStateTo (&myLights);
@@ -448,21 +324,26 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   // ====================================
 
   // Render background
-  if (theWorkspace->ToRedrawGL())
+  if (!theToDrawImmediate)
   {
-    DrawBackground (*theWorkspace);
+    DrawBackground (theWorkspace);
   }
 
 #if !defined(GL_ES_VERSION_2_0)
   // Switch off lighting by default
-  glDisable(GL_LIGHTING);
+  if (aContext->core11 != NULL)
+  {
+    glDisable(GL_LIGHTING);
+  }
 #endif
 
   // =================================
   //      Step 3: Draw underlayer
   // =================================
-
-  RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCUnderLayer);
+  if (!theToDrawImmediate)
+  {
+    RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCUnderLayer);
+  }
 
   // =================================
   //      Step 4: Redraw main plane
@@ -498,7 +379,8 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 
   // Apply Fog
-  if ( myFog.IsOn )
+  if (myFog.IsOn
+   && aContext->core11 != NULL)
   {
     Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
     if (myCamera->ZFar() < aFogFrontConverted)
@@ -526,12 +408,17 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
     glEnable(GL_FOG);
   }
-  else
-    glDisable(GL_FOG);
+  else if (aContext->core11 != NULL)
+  {
+    glDisable (GL_FOG);
+  }
 
   // Apply InteriorShadingMethod
-  aContext->core11->glShadeModel (myShadingModel == Visual3d_TOM_FACET
-                               || myShadingModel == Visual3d_TOM_NONE ? GL_FLAT : GL_SMOOTH);
+  if (aContext->core11 != NULL)
+  {
+    aContext->core11->glShadeModel (myShadingModel == Visual3d_TOM_FACET
+                                 || myShadingModel == Visual3d_TOM_NONE ? GL_FLAT : GL_SMOOTH);
+  }
 #endif
 
   aManager->SetShadingModel (myShadingModel);
@@ -548,42 +435,17 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 
   // Redraw 3d scene
-  if (!myCamera->IsStereo() || !aContext->HasStereoBuffers())
-  {
-    // single-pass monographic rendering
-    // redraw scene with normal orientation and projection
-    RedrawScene (thePrintContext, theWorkspace);
-  }
-  else
+  if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
   {
-    // two stereographic passes
-
-    // safely switch to left Eye buffer
-    aContext->SetDrawBufferLeft();
-
     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
     aContext->ApplyProjectionMatrix();
-
-    // redraw left Eye
-    RedrawScene (thePrintContext, theWorkspace);
-
-    // reset depth buffer of first rendering pass
-    if (theWorkspace->UseDepthTest())
-    {
-      glClear (GL_DEPTH_BUFFER_BIT);
-    }
-    // safely switch to right Eye buffer
-    aContext->SetDrawBufferRight();
-
+  }
+  else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
+  {
     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
     aContext->ApplyProjectionMatrix();
-
-    // redraw right Eye
-    RedrawScene (thePrintContext, theWorkspace);
-
-    // switch back to monographic rendering
-    aContext->SetDrawBufferMono();
   }
+  RedrawScene (thePrintContext, theWorkspace, theOutputFBO, theCView, theToDrawImmediate);
 
   // ===============================
   //      Step 5: Trihedron
@@ -609,7 +471,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 
   // Render trihedron
-  if (theWorkspace->ToRedrawGL())
+  if (!theToDrawImmediate)
   {
     RedrawTrihedron (theWorkspace);
 
@@ -629,36 +491,18 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   // ===============================
   //      Step 6: Redraw overlay
   // ===============================
+  if (!theToDrawImmediate)
+  {
+    const int aMode = 0;
+    theWorkspace->DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
 
-  const int aMode = 0;
-  theWorkspace->DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
-
-  RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCOverLayer);
-
-  theWorkspace->DisplayCallback (theCView, aMode);
-
-  // ===============================
-  //      Step 7: Finalize
-  // ===============================
+    RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCOverLayer);
 
-#if !defined(GL_ES_VERSION_2_0)
-  // restore clipping planes
-  if (aContext->core11 != NULL)
-  {
-    for (Standard_Integer aClipPlaneId = aOldPlanes.Lower(); aClipPlaneId <= aOldPlanes.Upper(); ++aClipPlaneId)
-    {
-      const OPENGL_CLIP_PLANE& aPlane = aOldPlanes.ChangeValue (aClipPlaneId);
-      aContext->core11->glClipPlane (aClipPlaneId, aPlane.Equation);
-      if (aPlane.isEnabled)
-        aContext->core11fwd->glEnable (aClipPlaneId);
-      else
-        aContext->core11fwd->glDisable (aClipPlaneId);
-    }
+    theWorkspace->DisplayCallback (theCView, aMode);
   }
-#endif
 
   // ==============================================================
-  //      Step 8: Keep shader manager informed about last View
+  //      Step 7: Keep shader manager informed about last View
   // ==============================================================
 
   if (!aManager.IsNull())
@@ -671,7 +515,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
 // function : InvalidateBVHData
 // purpose  :
 // =======================================================================
-void OpenGl_View::InvalidateBVHData (const Standard_Integer theLayerId)
+void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
 {
   myZLayers.InvalidateBVHData (theLayerId);
 }
@@ -679,29 +523,31 @@ void OpenGl_View::InvalidateBVHData (const Standard_Integer theLayerId)
 /*----------------------------------------------------------------------*/
 
 //ExecuteViewDisplay
-void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
+void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace)& theWorkspace,
+                                 OpenGl_FrameBuffer*             theReadDrawFbo,
+                                 const Graphic3d_CView&          theCView,
+                                 const Standard_Boolean          theToDrawImmediate)
 {
   if ( myZLayers.NbStructures() <= 0 )
     return;
 
-#if !defined(GL_ES_VERSION_2_0)
-  glPushAttrib ( GL_DEPTH_BUFFER_BIT );
-#endif
-
-  //TsmPushAttri(); /* save previous graphics context */
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-  if ( (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
+  if ( (theWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
   {
   #if !defined(GL_ES_VERSION_2_0)
-    const int antiAliasingMode = AWorkspace->AntiAliasingMode();
+    const int anAntiAliasingMode = theWorkspace->AntiAliasingMode();
   #endif
 
     if ( !myAntiAliasing )
     {
     #if !defined(GL_ES_VERSION_2_0)
-      glDisable(GL_POINT_SMOOTH);
+      if (aCtx->core11 != NULL)
+      {
+        glDisable (GL_POINT_SMOOTH);
+      }
       glDisable(GL_LINE_SMOOTH);
-      if( antiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
+      if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
     #endif
       glBlendFunc (GL_ONE, GL_ZERO);
       glDisable (GL_BLEND);
@@ -709,21 +555,108 @@ void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
     else
     {
     #if !defined(GL_ES_VERSION_2_0)
-      glEnable(GL_POINT_SMOOTH);
+      if (aCtx->core11 != NULL)
+      {
+        glEnable(GL_POINT_SMOOTH);
+      }
       glEnable(GL_LINE_SMOOTH);
-      if( antiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
+      if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
     #endif
       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       glEnable (GL_BLEND);
     }
   }
 
-  myZLayers.Render (AWorkspace);
+  Standard_Boolean toRenderGL = theToDrawImmediate ||
+    theCView.RenderParams.Method != Graphic3d_RM_RAYTRACING || myRaytraceInitStatus == OpenGl_RT_FAIL;
 
-#if !defined(GL_ES_VERSION_2_0)
-  //TsmPopAttri(); /* restore previous graphics context; before update lights */
-  glPopAttrib();
-#endif
+  if (!toRenderGL)
+  {
+    toRenderGL = !initRaytraceResources (theCView, aCtx) ||
+      !updateRaytraceGeometry (OpenGl_GUM_CHECK, theWorkspace->ActiveViewId(), aCtx);
+
+    toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
+
+    if (!toRenderGL)
+    {
+      const Standard_Integer aSizeX = theReadDrawFbo != NULL ?
+        theReadDrawFbo->GetVPSizeX() : theWorkspace->Width();
+      const Standard_Integer aSizeY = theReadDrawFbo != NULL ?
+        theReadDrawFbo->GetVPSizeY() : theWorkspace->Height();
+
+      if (myOpenGlFBO.IsNull())
+        myOpenGlFBO = new OpenGl_FrameBuffer;
+
+      if (myOpenGlFBO->GetVPSizeX() != aSizeX
+       || myOpenGlFBO->GetVPSizeY() != aSizeY)
+      {
+        myOpenGlFBO->Init (aCtx, aSizeX, aSizeY);
+      }
+
+      if (myRaytraceFilter.IsNull())
+        myRaytraceFilter = new OpenGl_RaytraceFilter;
+
+      myRaytraceFilter->SetPrevRenderFilter (theWorkspace->GetRenderFilter());
+
+      if (theReadDrawFbo != NULL)
+        theReadDrawFbo->UnbindBuffer (aCtx);
+
+      // Prepare preliminary OpenGL output
+      if (aCtx->arbFBOBlit != NULL)
+      {
+        // Render bottom OSD layer
+        myZLayers.Render (theWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
+
+        theWorkspace->SetRenderFilter (myRaytraceFilter);
+        {
+          if (theReadDrawFbo != NULL)
+          {
+            theReadDrawFbo->BindReadBuffer (aCtx);
+          }
+          else
+          {
+            aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
+          }
+
+          myOpenGlFBO->BindDrawBuffer (aCtx);
+
+          aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY,
+                                               0, 0, aSizeX, aSizeY,
+                                               GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
+                                               GL_NEAREST);
+
+          // Render non-polygonal elements in default layer
+          myZLayers.Render (theWorkspace, theToDrawImmediate, OpenGl_LF_Default);
+        }
+        theWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
+      }
+
+      if (theReadDrawFbo != NULL)
+      {
+        theReadDrawFbo->BindBuffer (aCtx);
+      }
+      else
+      {
+        aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0);
+      }
+
+      // Ray-tracing polygonal primitive arrays
+      raytrace (theCView, aSizeX, aSizeY, theReadDrawFbo, aCtx);
+
+      // Render upper (top and topmost) OpenGL layers
+      myZLayers.Render (theWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
+    }
+  }
+
+  // Redraw 3D scene using OpenGL in standard
+  // mode or in case of ray-tracing failure
+  if (toRenderGL)
+  {
+    myZLayers.Render (theWorkspace, theToDrawImmediate, OpenGl_LF_All);
+
+    // Set flag that scene was redrawn by standard pipeline
+    theCView.WasRedrawnGL = Standard_True;
+  }
 }
 
 /*----------------------------------------------------------------------*/
@@ -731,7 +664,7 @@ void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
 //call_togl_redraw_layer2d
 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext,
                                  const Handle(OpenGl_Workspace)&      theWorkspace,
-                                 const Graphic3d_CView&               ACView,
+                                 const Graphic3d_CView&               /*ACView*/,
                                  const Aspect_CLayer2d&               ACLayer)
 {
 #if !defined(GL_ES_VERSION_2_0)
@@ -740,6 +673,10 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo
    || ACLayer.ptrLayer->listIndex == 0) return;
 
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+  if (aContext->core11 == NULL)
+  {
+    return;
+  }
 
   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
@@ -871,13 +808,13 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo
 void OpenGl_View::RedrawTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
 {
   // display global trihedron
-  if (myTrihedron != NULL)
+  if (myToShowTrihedron)
   {
-    myTrihedron->Render (theWorkspace);
+    myTrihedron.Render (theWorkspace);
   }
-  if (myGraduatedTrihedron != NULL)
+  if (myToShowGradTrihedron)
   {
-    myGraduatedTrihedron->Render (theWorkspace);
+    myGraduatedTrihedron.Render (theWorkspace);
   }
 }
 
@@ -887,116 +824,58 @@ void OpenGl_View::RedrawTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
 void OpenGl_View::CreateBackgroundTexture (const Standard_CString  theFilePath,
                                            const Aspect_FillMethod theFillStyle)
 {
-  if (myBgTexture.TexId != 0)
+  // Prepare aspect for texture storage
+  Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
+  Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
+  aTextureMap->EnableRepeat();
+  aTextureMap->DisableModulate();
+  aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
+                                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
+                                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
+  anAspect->SetTextureMap (aTextureMap);
+  anAspect->SetInteriorStyle (Aspect_IS_SOLID);
+  // Enable texture mapping
+  if (aTextureMap->IsDone())
   {
-    // delete existing texture
-    glDeleteTextures (1, (GLuint* )&(myBgTexture.TexId));
-    myBgTexture.TexId = 0;
-  }
-
-  // load image from file
-  Image_AlienPixMap anImageLoaded;
-  if (!anImageLoaded.Load (theFilePath))
-  {
-    return;
-  }
-
-  Image_PixMap anImage;
-  if (anImageLoaded.RowExtraBytes() == 0 &&
-      (anImageLoaded.Format() == Image_PixMap::ImgRGB
-    || anImageLoaded.Format() == Image_PixMap::ImgRGB32
-    || anImageLoaded.Format() == Image_PixMap::ImgRGBA))
-  {
-    anImage.InitWrapper (anImageLoaded.Format(), anImageLoaded.ChangeData(),
-                         anImageLoaded.SizeX(), anImageLoaded.SizeY(), anImageLoaded.SizeRowBytes());
+    anAspect->SetTextureMapOn();
   }
   else
   {
-    // convert image to RGB format
-    if (!anImage.InitTrash (Image_PixMap::ImgRGB, anImageLoaded.SizeX(), anImageLoaded.SizeY()))
-    {
-      return;
-    }
+    anAspect->SetTextureMapOff();
+    return;
 
-    anImage.SetTopDown (false);
-    Quantity_Color aSrcColor;
-    for (Standard_Size aRow = 0; aRow < anImage.SizeY(); ++aRow)
-    {
-      for (Standard_Size aCol = 0; aCol < anImage.SizeX(); ++aCol)
-      {
-        aSrcColor = anImageLoaded.PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
-        Image_ColorRGB& aColor = anImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
-        aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
-        aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
-        aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
-      }
-    }
-    anImageLoaded.Clear();
   }
 
-  // create MipMapped texture
-  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
-
-  GLuint aTextureId = 0;
-  glGenTextures (1, &aTextureId);
-  glBindTexture (GL_TEXTURE_2D, aTextureId);
-
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-
-  const GLenum aDataFormat = (anImage.Format() == Image_PixMap::ImgRGB) ? GL_RGB : GL_RGBA;
-
-#if !defined(GL_ES_VERSION_2_0)
-  gluBuild2DMipmaps (GL_TEXTURE_2D, 3/*4*/,
-                     GLint(anImage.SizeX()), GLint(anImage.SizeY()),
-                     aDataFormat, GL_UNSIGNED_BYTE, anImage.Data());
-#endif
+  // Set texture parameters
+  myTextureParams->SetAspect (anAspect);
 
-  myBgTexture.TexId  = aTextureId;
-  myBgTexture.Width  = (Standard_Integer )anImage.SizeX();
-  myBgTexture.Height = (Standard_Integer )anImage.SizeY();
-  myBgTexture.Style  = theFillStyle;
+  myBgTextureArray->SetTextureParameters (theFillStyle);
 }
 
 /*----------------------------------------------------------------------*/
 
 //call_togl_set_bg_texture_style
-void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod AFillStyle)
+void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod theFillStyle)
 {
-  myBgTexture.Style = AFillStyle;
+  myBgTextureArray->SetTextureFillMethod (theFillStyle);
 }
 
 /*----------------------------------------------------------------------*/
 
 //call_togl_gradient_background
-void OpenGl_View::SetBackgroundGradient (const Quantity_Color& AColor1,
-                                        const Quantity_Color& AColor2,
-                                        const Aspect_GradientFillMethod AType)
+void OpenGl_View::SetBackgroundGradient (const Quantity_Color& theColor1,
+                                        const Quantity_Color& theColor2,
+                                        const Aspect_GradientFillMethod theType)
 {
-  Standard_Real R,G,B;
-  AColor1.Values( R, G, B, Quantity_TOC_RGB );
-  myBgGradient.color1.rgb[0] = ( Tfloat )R;
-  myBgGradient.color1.rgb[1] = ( Tfloat )G;
-  myBgGradient.color1.rgb[2] = ( Tfloat )B;
-  myBgGradient.color1.rgb[3] = 0.F;
-
-  AColor2.Values( R, G, B, Quantity_TOC_RGB );
-  myBgGradient.color2.rgb[0] = ( Tfloat )R;
-  myBgGradient.color2.rgb[1] = ( Tfloat )G;
-  myBgGradient.color2.rgb[2] = ( Tfloat )B;
-  myBgGradient.color2.rgb[3] = 0.F;
-
-  myBgGradient.type = AType;
+  myBgGradientArray->SetGradientParameters (theColor1, theColor2, theType);
 }
 
 /*----------------------------------------------------------------------*/
 
 //call_togl_set_gradient_type
-void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod AType)
+void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod theType)
 {
-  myBgGradient.type = AType;
+  myBgGradientArray->SetGradientFillMethod (theType);
 }
 
 //=======================================================================
@@ -1004,7 +883,7 @@ void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod ATy
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::AddZLayer (const Standard_Integer theLayerId)
+void OpenGl_View::AddZLayer (const Graphic3d_ZLayerId theLayerId)
 {
   myZLayers.AddLayer (theLayerId);
 }
@@ -1014,7 +893,7 @@ void OpenGl_View::AddZLayer (const Standard_Integer theLayerId)
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::RemoveZLayer (const Standard_Integer theLayerId)
+void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
 {
   myZLayers.RemoveLayer (theLayerId);
 }
@@ -1024,11 +903,12 @@ void OpenGl_View::RemoveZLayer (const Standard_Integer theLayerId)
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::DisplayStructure (const OpenGl_Structure *theStructure,
-                                    const Standard_Integer  thePriority)
+void OpenGl_View::DisplayStructure (const Handle(Graphic3d_Structure)& theStructure,
+                                    const Standard_Integer             thePriority)
 {
-  Standard_Integer aZLayer = theStructure->GetZLayer ();
-  myZLayers.AddStructure (theStructure, aZLayer, thePriority);
+  const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure->CStructure().operator->());
+  const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
+  myZLayers.AddStructure (aStruct, aZLayer, thePriority);
 }
 
 //=======================================================================
@@ -1036,18 +916,19 @@ void OpenGl_View::DisplayStructure (const OpenGl_Structure *theStructure,
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::DisplayImmediateStructure (const OpenGl_Structure* theStructure)
+void OpenGl_View::DisplayImmediateStructure (const Handle(Graphic3d_Structure)& theStructure)
 {
+  const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure->CStructure().operator->());
   for (OpenGl_SequenceOfStructure::Iterator anIter (myImmediateList);
        anIter.More(); anIter.Next())
   {
-    if (anIter.Value() == theStructure)
+    if (anIter.Value() == aStruct)
     {
       return;
     }
   }
 
-  myImmediateList.Append (theStructure);
+  myImmediateList.Append (aStruct);
 }
 
 //=======================================================================
@@ -1055,10 +936,9 @@ void OpenGl_View::DisplayImmediateStructure (const OpenGl_Structure* theStructur
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::EraseStructure (const OpenGl_Structure *theStructure)
+void OpenGl_View::EraseStructure (const Handle(Graphic3d_Structure)& theStructure)
 {
-  Standard_Integer aZLayer = theStructure->GetZLayer ();
-  myZLayers.RemoveStructure (theStructure, aZLayer);
+  myZLayers.RemoveStructure (theStructure);
 }
 
 //=======================================================================
@@ -1084,10 +964,10 @@ void OpenGl_View::EraseImmediateStructure (const OpenGl_Structure* theStructure)
 //purpose  :
 //=======================================================================
 
-void OpenGl_View::ChangeZLayer (const OpenGl_Structure *theStructure,
-                                const Standard_Integer  theNewLayerId)
+void OpenGl_View::ChangeZLayer (const OpenGl_Structure*  theStructure,
+                                const Graphic3d_ZLayerId theNewLayerId)
 {
-  Standard_Integer anOldLayer = theStructure->GetZLayer ();
+  const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
   myZLayers.ChangeLayer (theStructure, anOldLayer, theNewLayerId);
 }
 
@@ -1095,10 +975,10 @@ void OpenGl_View::ChangeZLayer (const OpenGl_Structure *theStructure,
 //function : SetZLayerSettings
 //purpose  :
 //=======================================================================
-void OpenGl_View::SetZLayerSettings (const Standard_Integer theLayerId,
-                                     const Graphic3d_ZLayerSettings theSettings)
+void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
+                                     const Graphic3d_ZLayerSettings& theSettings)
 {
-  myZLayers.Layer (theLayerId).SetLayerSettings (theSettings);
+  myZLayers.SetLayerSettings (theLayerId, theSettings);
 }
 
 //=======================================================================
@@ -1108,7 +988,7 @@ void OpenGl_View::SetZLayerSettings (const Standard_Integer theLayerId,
 void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
                                   const Standard_Integer theNewPriority)
 {
-  Standard_Integer aLayerId = theStructure->GetZLayer();
+  const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
   myZLayers.ChangePriority (theStructure, aLayerId, theNewPriority);
 }
 
@@ -1118,7 +998,10 @@ void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
 //=======================================================================
 
 void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintContext,
-                               const Handle(OpenGl_Workspace)& theWorkspace)
+                               const Handle(OpenGl_Workspace)&      theWorkspace,
+                               OpenGl_FrameBuffer*                  theReadDrawFbo,
+                               const Graphic3d_CView&               theCView,
+                               const Standard_Boolean               theToDrawImmediate)
 {
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
 
@@ -1207,6 +1090,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
 
 #if !defined(GL_ES_VERSION_2_0)
   // Apply Lights
+  if (aContext->core11 != NULL)
   {
     // setup lights
     Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
@@ -1239,6 +1123,9 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
   // Clear status bitfields
   theWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
 
+  // Update state of surface detail level
+  theWorkspace->GetGlContext()->ShaderManager()->UpdateSurfaceDetailStateTo (mySurfaceDetail);
+
   // Added PCT for handling of textures
   switch (mySurfaceDetail)
   {
@@ -1246,14 +1133,14 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
       theWorkspace->DisableTexture();
       // Render the view
-      RenderStructs (theWorkspace);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       break;
 
     case Visual3d_TOD_ENVIRONMENT:
       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
       theWorkspace->EnableTexture (myTextureEnv);
       // Render the view
-      RenderStructs (theWorkspace);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       theWorkspace->DisableTexture();
       break;
 
@@ -1261,7 +1148,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
       // First pass
       theWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
       // Render the view
-      RenderStructs (theWorkspace);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       theWorkspace->DisableTexture();
 
       // Second pass
@@ -1294,7 +1181,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
         theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
 
         // Render the view
-        RenderStructs (theWorkspace);
+        RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
         theWorkspace->DisableTexture();
 
         // Restore properties back