0026025: Visualization, TKOpenGl - stereoscopic output does not work
[occt.git] / src / OpenGl / OpenGl_View_2.cxx
index 9fe7f64..3abea51 100644 (file)
@@ -38,6 +38,7 @@
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_ArbFBO.hxx>
 
 #define EPSI 0.0001
 
@@ -54,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
 */
@@ -240,6 +232,7 @@ void OpenGl_View::DrawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
   aCtx->WorldViewState.Pop();
   aCtx->ProjectionState.Pop();
   aCtx->ApplyProjectionMatrix();
+  aCtx->ApplyWorldViewMatrix();
 
   if (theWorkspace->UseZBuffer())
   {
@@ -252,6 +245,8 @@ void OpenGl_View::DrawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
 //call_func_redraw_all_structs_proc
 void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
                           const Handle(OpenGl_Workspace)&      theWorkspace,
+                          OpenGl_FrameBuffer*                  theOutputFBO,
+                          Graphic3d_Camera::Projection         theProjection,
                           const Graphic3d_CView&               theCView,
                           const Aspect_CLayer2d&               theCUnderLayer,
                           const Aspect_CLayer2d&               theCOverLayer,
@@ -264,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
@@ -340,15 +324,17 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   // ====================================
 
   // Render background
-  if (theWorkspace->ToRedrawGL()
-  && !theToDrawImmediate)
+  if (!theToDrawImmediate)
   {
     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
 
   // =================================
@@ -393,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)
@@ -421,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);
@@ -443,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, theToDrawImmediate);
-  }
-  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, theToDrawImmediate);
-
-    // 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, theToDrawImmediate);
-
-    // switch back to monographic rendering
-    aContext->SetDrawBufferMono();
   }
+  RedrawScene (thePrintContext, theWorkspace, theOutputFBO, theCView, theToDrawImmediate);
 
   // ===============================
   //      Step 5: Trihedron
@@ -504,8 +471,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 
   // Render trihedron
-  if (theWorkspace->ToRedrawGL()
-  && !theToDrawImmediate)
+  if (!theToDrawImmediate)
   {
     RedrawTrihedron (theWorkspace);
 
@@ -535,28 +501,8 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     theWorkspace->DisplayCallback (theCView, aMode);
   }
 
-  // ===============================
-  //      Step 7: Finalize
-  // ===============================
-
-#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);
-    }
-  }
-#endif
-
   // ==============================================================
-  //      Step 8: Keep shader manager informed about last View
+  //      Step 7: Keep shader manager informed about last View
   // ==============================================================
 
   if (!aManager.IsNull())
@@ -577,30 +523,31 @@ void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId 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);
@@ -608,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, theToDrawImmediate);
+  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;
+  }
 }
 
 /*----------------------------------------------------------------------*/
@@ -639,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];
@@ -770,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);
   }
 }
 
@@ -961,6 +999,8 @@ void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
 
 void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintContext,
                                const Handle(OpenGl_Workspace)&      theWorkspace,
+                               OpenGl_FrameBuffer*                  theReadDrawFbo,
+                               const Graphic3d_CView&               theCView,
                                const Standard_Boolean               theToDrawImmediate)
 {
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
@@ -1050,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],
@@ -1082,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)
   {
@@ -1089,14 +1133,14 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
       theWorkspace->DisableTexture();
       // Render the view
-      RenderStructs (theWorkspace, theToDrawImmediate);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       break;
 
     case Visual3d_TOD_ENVIRONMENT:
       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
       theWorkspace->EnableTexture (myTextureEnv);
       // Render the view
-      RenderStructs (theWorkspace, theToDrawImmediate);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       theWorkspace->DisableTexture();
       break;
 
@@ -1104,7 +1148,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
       // First pass
       theWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
       // Render the view
-      RenderStructs (theWorkspace, theToDrawImmediate);
+      RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
       theWorkspace->DisableTexture();
 
       // Second pass
@@ -1137,7 +1181,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
         theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
 
         // Render the view
-        RenderStructs (theWorkspace, theToDrawImmediate);
+        RenderStructs (theWorkspace, theReadDrawFbo, theCView, theToDrawImmediate);
         theWorkspace->DisableTexture();
 
         // Restore properties back