diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 53fb914d08..26bf048cf8 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -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"); diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index e3cc3d7df3..7c55ba1eba 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -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 diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 844101d3cc..274b298fbd 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -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); diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 5d1aa160c5..5f8e602b51 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -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 } //=======================================================================