]> OCCT Git - occt.git/commitdiff
0032036: Visualization, TKOpenGl - broken Cubemap background on GeForce 320M
authorkgv <kgv@opencascade.com>
Sun, 3 Jan 2021 00:05:32 +0000 (03:05 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 12 Jan 2021 10:51:20 +0000 (13:51 +0300)
Enable GL_DEPTH_CLAMP while rendering skybox to workaround unexpected clamping issue on some GPUs.

src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_View.cxx

index 53fb914d08f6908471aa8bdf1f5e6999331439f1..26bf048cf8ec54dc1817041d536e1c2c1f30126f 100644 (file)
@@ -177,6 +177,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   arbFBO (NULL),
   arbFBOBlit (NULL),
   arbSampleShading (Standard_False),
+  arbDepthClamp (Standard_False),
   extFragDepth (Standard_False),
   extDrawBuffers (Standard_False),
   extGS  (NULL),
@@ -1913,6 +1914,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
                   || CheckExtension ("GL_ARB_texture_float");
   hasTexFloatLinear = arbTexFloat;
   arbSampleShading = CheckExtension ("GL_ARB_sample_shading");
+  arbDepthClamp    = IsGlGreaterEqual (3, 2)
+                  || CheckExtension ("GL_ARB_depth_clamp")
+                  || CheckExtension ("NV_depth_clamp");
   extBgra          = IsGlGreaterEqual (1, 2)
                   || CheckExtension ("GL_EXT_bgra");
   extAnis          = CheckExtension ("GL_EXT_texture_filter_anisotropic");
index e3cc3d7df3901554617fe5b7acb766ca0d2dc5f5..7c55ba1eba667fcb532903de35466a9cc2a96d17 100644 (file)
@@ -1084,6 +1084,7 @@ public: //! @name extensions
   OpenGl_ArbFBO*         arbFBO;             //!< GL_ARB_framebuffer_object
   OpenGl_ArbFBOBlit*     arbFBOBlit;         //!< glBlitFramebuffer function, moved out from OpenGl_ArbFBO structure for compatibility with OpenGL ES 2.0
   Standard_Boolean       arbSampleShading;   //!< GL_ARB_sample_shading
+  Standard_Boolean       arbDepthClamp;      //!< GL_ARB_depth_clamp (on desktop OpenGL - since 3.2 or as extensions GL_ARB_depth_clamp,NV_depth_clamp; unavailable on OpenGL ES)
   Standard_Boolean       extFragDepth;       //!< GL_EXT_frag_depth on OpenGL ES 2.0 (gl_FragDepthEXT built-in variable, before OpenGL ES 3.0)
   Standard_Boolean       extDrawBuffers;     //!< GL_EXT_draw_buffers
   OpenGl_ExtGS*          extGS;              //!< GL_EXT_geometry_shader4
index 844101d3cc1086cfaaf740bab78a8daf623a4a07..274b298fbd0aacc3036c2b18df3c84dff73e0611 100644 (file)
@@ -3171,15 +3171,40 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram
       EOL"{"
       EOL"  ViewDirection = cubemapVectorTransform (occVertex.xyz, uYCoeff, uZCoeff);"
       EOL"  vec4 aPos = occProjectionMatrix * occWorldViewMatrix * vec4(occVertex.xyz, 1.0);"
+      // setting Z to W ensures that final Z will be 1.0 after perspective division, (w/w=1))
+      // which allows rendering skybox after everything else with depth test enabled (GL_LEQUAL)
       EOL"  gl_Position = aPos.xyww;"
       EOL"}";
 
-    TCollection_AsciiString aSrcFrag =
-      EOL"#define occEnvCubemap occSampler0"
+    TCollection_AsciiString aDepthClamp;
+    if (!myContext->arbDepthClamp)
+    {
+      // workaround Z clamping issues on some GPUs
+      aDepthClamp = EOL"  gl_FragDepth = clamp (gl_FragDepth, 0.0, 1.0);";
+    #if defined(GL_ES_VERSION_2_0)
+      if (myContext->IsGlGreaterEqual (3, 0))
+      {
+        myBgCubeMapProgram->SetHeader ("#version 300 es");
+      }
+      else if (myContext->extFragDepth)
+      {
+        myBgCubeMapProgram->SetHeader ("#extension GL_EXT_frag_depth : enable"
+                                    EOL"#define gl_FragDepth gl_FragDepthEXT");
+      }
+      else
+      {
+        aDepthClamp.Clear();
+      }
+    #endif
+    }
+
+    TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
+    + EOL"#define occEnvCubemap occSampler0"
       EOL"void main()"
       EOL"{"
       EOL"  occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));"
-      EOL"}";
+    + aDepthClamp
+    + EOL"}";
 
     defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
     myBgCubeMapProgram->SetDefaultSampler (false);
index 5d1aa160c54070e5d83df8b2489e742db804ee8d..5f8e602b5142ca2c9c6eebdc8136b3c18b4b9cbf 100644 (file)
@@ -902,12 +902,21 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace,
                                   Graphic3d_Camera::Projection theProjection)
 {
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
-  const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False);
+  const bool wasUsedZBuffer = theWorkspace->SetUseZBuffer (false);
   if (wasUsedZBuffer)
   {
     aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
   }
 
+#ifdef GL_DEPTH_CLAMP
+  const bool wasDepthClamped = aCtx->arbDepthClamp && glIsEnabled (GL_DEPTH_CLAMP);
+  if (aCtx->arbDepthClamp && !wasDepthClamped)
+  {
+    // make sure background is always drawn (workaround skybox rendering on some hardware)
+    aCtx->core11fwd->glEnable (GL_DEPTH_CLAMP);
+  }
+#endif
+
   if (myBackgroundType == Graphic3d_TOB_CUBEMAP)
   {
     myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uZCoeff", myBackgroundCubeMap->ZIsInverted() ? -1 : 1);
@@ -950,6 +959,12 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace,
     theWorkspace->SetUseZBuffer (Standard_True);
     aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
   }
+#ifdef GL_DEPTH_CLAMP
+  if (aCtx->arbDepthClamp && !wasDepthClamped)
+  {
+    aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP);
+  }
+#endif
 }
 
 //=======================================================================