From c39bb31bacfd30a9a604ece1feb84d5363c2e4df Mon Sep 17 00:00:00 2001 From: mnv Date: Thu, 13 Sep 2018 17:47:51 +0300 Subject: [PATCH] 0030136: Visualization, TKOpenGl - Graphic3d_TOSM_FACET does not work on mobile devices Added new type of graphic3d limit Graphic3d_TypeOfLimit_HasFlatShading. Added workaround for unexpected behaviour of mobile devices with Adreno GPU. Added new complex flag hasFlatShading to OpenGl_Context for indicating support of flat shading. --- src/Graphic3d/Graphic3d_TypeOfLimit.hxx | 1 + src/OpenGl/OpenGl_Context.cxx | 14 +++++++++++ src/OpenGl/OpenGl_Context.hxx | 4 +++ src/OpenGl/OpenGl_GraphicDriver.cxx | 2 ++ src/OpenGl/OpenGl_ShaderManager.cxx | 33 +++++++++++++++---------- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx index e27984a5d0..6770049ea5 100644 --- a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx +++ b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx @@ -28,6 +28,7 @@ enum Graphic3d_TypeOfLimit Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling, //!< indicates whether adaptive screen sampling is supported Graphic3d_TypeOfLimit_HasBlendedOit, //!< indicates whether necessary GL extensions for Weighted, Blended OIT available (without MSAA). Graphic3d_TypeOfLimit_HasBlendedOitMsaa, //!< indicates whether necessary GL extensions for Weighted, Blended OIT available (with MSAA). + Graphic3d_TypeOfLimit_HasFlatShading, //!< indicates whether Flat shading (Graphic3d_TOSM_FACET) is supported Graphic3d_TypeOfLimit_NB //!< number of elements in this enumeration }; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 6d07a82a8c..3498381c7f 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -114,10 +114,12 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) hasHighp (Standard_False), hasUintIndex(Standard_False), hasTexRGBA8(Standard_False), + hasFlatShading (OpenGl_FeatureNotAvailable), #else hasHighp (Standard_True), hasUintIndex(Standard_True), hasTexRGBA8(Standard_True), + hasFlatShading (OpenGl_FeatureInCore), #endif hasDrawBuffers (OpenGl_FeatureNotAvailable), hasFloatBuffer (OpenGl_FeatureNotAvailable), @@ -1406,6 +1408,18 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : oesSampleVariables ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; + // without hasHighp, dFdx/dFdy precision is considered too low for flat shading (visual artifacts) + hasFlatShading = IsGlGreaterEqual (3, 0) + ? OpenGl_FeatureInCore + : (oesStdDerivatives && hasHighp + ? OpenGl_FeatureInExtensions + : OpenGl_FeatureNotAvailable); + if (!IsGlGreaterEqual (3, 1) + && myVendor.Search("Qualcomm") != -1) + { + // dFdx/dFdy are completely broken on tested Adreno devices with versions below OpenGl ES 3.1 + hasFlatShading = OpenGl_FeatureNotAvailable; + } #else myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP; diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 36ef156f87..5f9b050230 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -784,6 +784,9 @@ public: //! @name methods to alter or retrieve current state myLineWidthScale = Max (1.0f, std::floor (theRatio + 0.5f)); } + //! Return Graphics Driver's vendor. + const TCollection_AsciiString& Vendor() const { return myVendor; } + private: //! Wrapper to system function to retrieve GL function pointer by name. @@ -827,6 +830,7 @@ public: //! @name extensions Standard_Boolean hasHighp; //!< highp in GLSL ES fragment shader is supported Standard_Boolean hasUintIndex; //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint) Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8 + OpenGl_FeatureFlag hasFlatShading; //!< Complex flag indicating support of Flat shading (Graphic3d_TOSM_FACET) (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_standard_derivatives) OpenGl_FeatureFlag hasDrawBuffers; //!< Complex flag indicating support of multiple draw buffers (desktop OpenGL 2.0, OpenGL ES 3.0, GL_ARB_draw_buffers, GL_EXT_draw_buffers) OpenGl_FeatureFlag hasFloatBuffer; //!< Complex flag indicating support of float color buffer format (desktop OpenGL 3.0, GL_ARB_color_buffer_float, GL_EXT_color_buffer_float) OpenGl_FeatureFlag hasHalfFloatBuffer; //!< Complex flag indicating support of half-float color buffer format (desktop OpenGL 3.0, GL_ARB_color_buffer_float, GL_EXT_color_buffer_half_float) diff --git a/src/OpenGl/OpenGl_GraphicDriver.cxx b/src/OpenGl/OpenGl_GraphicDriver.cxx index 14ceb7b3d2..c6fbdc2860 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver.cxx @@ -431,6 +431,8 @@ Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit return (!aCtx.IsNull() && aCtx->hasSampleVariables != OpenGl_FeatureNotAvailable && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0; + case Graphic3d_TypeOfLimit_HasFlatShading: + return !aCtx.IsNull() && aCtx->hasFlatShading != OpenGl_FeatureNotAvailable ? 1 : 0; case Graphic3d_TypeOfLimit_NB: return 0; } diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 71f6bda586..d89e2018e2 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -2066,12 +2066,24 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha const Standard_Boolean theIsFlatNormal) { #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)" -#if defined(GL_ES_VERSION_2_0) const bool isFlatNormal = theIsFlatNormal - && (myContext->IsGlGreaterEqual (3, 0) - || myContext->oesStdDerivatives); -#else - const bool isFlatNormal = theIsFlatNormal; + && myContext->hasFlatShading != OpenGl_FeatureNotAvailable; + const char* aDFdxSignReversion = ""; +#if defined(GL_ES_VERSION_2_0) + if (isFlatNormal != theIsFlatNormal) + { + myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, + GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, + "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension."); + } + else if (isFlatNormal + && myContext->Vendor().Search("Qualcomm") != -1) + { + // workaround Adreno driver bug computing reversed normal using dFdx/dFdy + aDFdxSignReversion = "-"; + myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, + "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno"); + } #endif Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); @@ -2191,8 +2203,9 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha EOL"{" + aSrcFragExtraMain + (isFlatNormal - ? EOL" Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));" - EOL" if (!gl_FrontFacing) { Normal = -Normal; }" + ? TCollection_AsciiString() + + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));" + EOL" if (!gl_FrontFacing) { Normal = -Normal; }" : "") + EOL" occSetFragColor (getColor());" + aSrcFragWriteOit @@ -2220,12 +2233,6 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha { aProgramSrc->SetHeader ("#extension GL_OES_standard_derivatives : enable"); } - else - { - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, - GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, - "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension."); - } } #endif aProgramSrc->SetNbLightsMax (aNbLights);