0030136: Visualization, TKOpenGl - Graphic3d_TOSM_FACET does not work on mobile devices
authormnv <mnv@opencascade.com>
Thu, 13 Sep 2018 14:47:51 +0000 (17:47 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 20 Sep 2018 14:08:47 +0000 (17:08 +0300)
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
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_GraphicDriver.cxx
src/OpenGl/OpenGl_ShaderManager.cxx

index e27984a..6770049 100644 (file)
@@ -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
 };
 
index 6d07a82..3498381 100644 (file)
@@ -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;
index 36ef156..5f9b050 100644 (file)
@@ -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)
index 14ceb7b..c6fbdc2 100644 (file)
@@ -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;
   }
index 71f6bda..d89e201 100644 (file)
@@ -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);