0029337: Visualization, TKOpenGl - visual artifacts on Intel Broadwell GPU
authorapl <apl@opencascade.com>
Mon, 27 Nov 2017 12:16:21 +0000 (15:16 +0300)
committerapn <apn@opencascade.com>
Thu, 15 Feb 2018 13:52:50 +0000 (16:52 +0300)
Enable multiple draw buffers in shader program only if its required by specific application.

occSetFragColor() - a new GLSL function has been introduced
as an alternative to setting occFragColor/occFragCoverage variables.

12 files changed:
src/Graphic3d/Graphic3d_ShaderProgram.cxx
src/Graphic3d/Graphic3d_ShaderProgram.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/Shaders/Declarations.glsl
src/Shaders/DeclarationsImpl.glsl
src/Shaders/PhongShading.fs
src/Shaders/Shaders_DeclarationsImpl_glsl.pxx
src/Shaders/Shaders_Declarations_glsl.pxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx

index 2d708d6..4ed1051 100755 (executable)
@@ -78,7 +78,9 @@ const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder()
 // =======================================================================
 Graphic3d_ShaderProgram::Graphic3d_ShaderProgram()
 : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT),
-  myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT)
+  myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT),
+  myNbFragOutputs (THE_NB_FRAG_OUTPUTS),
+  myHasWeightOitOutput (false)
 {
   myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_")
        + TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER));
index b723e9d..324465e 100755 (executable)
@@ -43,6 +43,9 @@ public:
   //! Default value of THE_MAX_CLIP_PLANES macros within GLSL program (see Declarations.glsl).
   static const Standard_Integer THE_MAX_CLIP_PLANES_DEFAULT = 8;
 
+  //! Default value of THE_NB_FRAG_OUTPUTS macros within GLSL program (see Declarations.glsl).
+  static const Standard_Integer THE_NB_FRAG_OUTPUTS = 1;
+
 public:
 
   //! Creates new empty program object.
@@ -115,6 +118,21 @@ public:
   //! Should be done before GLSL program initialization.
   Standard_EXPORT void SetVertexAttributes (const Graphic3d_ShaderAttributeList& theAttributes);
 
+  //! Returns the number (1+) of Fragment Shader outputs to be written to
+  //! (more than 1 can be in case of multiple draw buffers); 1 by default.
+  Standard_Integer NbFragmentOutputs() const { return myNbFragOutputs; }
+
+  //! Sets the number of Fragment Shader outputs to be written to.
+  //! Should be done before GLSL program initialization.
+  void SetNbFragmentOutputs (const Standard_Integer theNbOutputs) { myNbFragOutputs = theNbOutputs; }
+
+  //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default.
+  Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; }
+
+  //! Set if Fragment Shader color should output the weighted OIT coverage.
+  //! Note that weighted OIT also requires at least 2 Fragment Outputs (color + coverage).
+  void SetWeightOitOutput (Standard_Boolean theOutput) { myHasWeightOitOutput = theOutput; }
+
   //! Pushes custom uniform variable to the program.
   //! The list of pushed variables is automatically cleared after applying to GLSL program.
   //! Thus after program recreation even unchanged uniforms should be pushed anew.
@@ -164,6 +182,8 @@ private:
   TCollection_AsciiString       myHeader;        //!< GLSL header with version code and used extensions
   Standard_Integer              myNbLightsMax;   //!< length of array of light sources (THE_MAX_LIGHTS)
   Standard_Integer              myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
+  Standard_Integer              myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
+  Standard_Boolean              myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage
 
 };
 
index fdafc54..58fbe8e 100644 (file)
@@ -441,18 +441,13 @@ void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standar
   Standard_Boolean useDefaultFbo = Standard_False;
   for (Standard_Integer anI = 0; anI < theNb; ++anI)
   {
-#if !defined(GL_ES_VERSION_2_0)
-    const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffers[anI]) : theDrawBuffers[anI];
-#else
-    const Standard_Integer aDrawBuffer = theDrawBuffers[anI];
-#endif
-    if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && aDrawBuffer != GL_NONE)
+    if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE)
     {
       useDefaultFbo = Standard_True;
     }
-    else if (aDrawBuffer != GL_NONE)
+    else if (theDrawBuffers[anI] != GL_NONE)
     {
-      myDrawBuffers.SetValue (anI, aDrawBuffer);
+      myDrawBuffers.SetValue (anI, theDrawBuffers[anI]);
     }
   }
   if (arbFBO != NULL && useDefaultFbo)
index fe84cac..a664c07 100644 (file)
@@ -265,12 +265,6 @@ const char THE_FRAG_CLIP_PLANES_2[] =
   EOL"    discard;"
   EOL"  }";
 
-//! Output color and coverage for accumulation by OIT algorithm.
-const char THE_FRAG_write_oit_buffers[] =
-  EOL"  float aWeight     = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);"
-  EOL"  occFragCoverage.r = occFragColor.a * aWeight;"
-  EOL"  occFragColor      = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);";
-
 #if !defined(GL_ES_VERSION_2_0)
 
   static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
@@ -1194,7 +1188,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
        EOL"  vec4 aColor = occColor;"
        EOL"  aColor.a *= getAlpha();"
        EOL"  if (aColor.a <= 0.285) discard;"
-       EOL"  occFragColor = aColor;"
+       EOL"  occSetFragColor (aColor);"
        EOL"}";
 
 #if !defined(GL_ES_VERSION_2_0)
@@ -1245,7 +1239,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
       EOL"void main()"
       EOL"{"
       EOL"  gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
-      EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
+      EOL"  occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
       EOL"}";
 
 #if defined(GL_ES_VERSION_2_0)
@@ -1268,7 +1262,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
       EOL
       EOL"void main()"
       EOL"{"
-      EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
+      EOL"  occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
       EOL"}";
   }
 #else
@@ -1325,7 +1319,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
       EOL"{"
       EOL"  vec4 aAccum   = occTexture2D (uAccumTexture,  TexCoord);"
       EOL"  float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
-      EOL"  occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
+      EOL"  occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
       EOL"}";
   #if !defined(GL_ES_VERSION_2_0)
     if (myContext->IsGlGreaterEqual (3, 2))
@@ -1352,7 +1346,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
       EOL"  ivec2 aTexel  = ivec2 (textureSize (uAccumTexture) * TexCoord);"
       EOL"  vec4 aAccum   = texelFetch (uAccumTexture,  aTexel, gl_SampleID);"
       EOL"  float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
-      EOL"  occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
+      EOL"  occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
       EOL"}";
   #if !defined(GL_ES_VERSION_2_0)
     if (myContext->IsGlGreaterEqual (4, 0))
@@ -1429,7 +1423,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
   TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha;
   TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
   TCollection_AsciiString aSrcFragGetColor     = EOL"vec4 getColor(void) { return occColor; }";
-  TCollection_AsciiString aSrcFragMainGetColor = EOL"  occFragColor = getColor();";
+  TCollection_AsciiString aSrcFragMainGetColor = EOL"  occSetFragColor (getColor());";
   if ((theBits & OpenGl_PO_Point) != 0)
   {
   #if defined(GL_ES_VERSION_2_0)
@@ -1458,14 +1452,14 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
         EOL"  vec4 aColor = getColor();"
         EOL"  aColor.a = getAlpha();"
         EOL"  if (aColor.a <= 0.1) discard;"
-        EOL"  occFragColor = aColor;";
+        EOL"  occSetFragColor (aColor);";
     }
     else
     {
       aSrcFragMainGetColor =
         EOL"  vec4 aColor = getColor();"
         EOL"  if (aColor.a <= 0.1) discard;"
-        EOL"  occFragColor = aColor;";
+        EOL"  occSetFragColor (aColor);";
     }
   }
   else
@@ -1536,7 +1530,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
-    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+    aProgramSrc->SetNbFragmentOutputs (2);
+    aProgramSrc->SetWeightOitOutput (true);
   }
 
   TCollection_AsciiString aSrcVertEndMain;
@@ -1578,7 +1573,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
         EOL"  if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
         EOL"  vec4 aColor = getColor();"
         EOL"  if (aColor.a <= 0.1) discard;"
-        EOL"  occFragColor = aColor;";
+        EOL"  occSetFragColor (aColor);";
     }
     else
     {
@@ -1888,7 +1883,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
-    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+    aProgramSrc->SetNbFragmentOutputs (2);
+    aProgramSrc->SetWeightOitOutput (true);
   }
 
   Standard_Integer aNbLights = 0;
@@ -1923,7 +1919,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
     + EOL"void main()"
       EOL"{"
     + aSrcFragExtraMain
-    + EOL"  occFragColor = getColor();"
+    + EOL"  occSetFragColor (getColor());"
     + aSrcFragWriteOit
     + EOL"}";
 
@@ -2037,7 +2033,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
   }
   if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
-    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+    aProgramSrc->SetNbFragmentOutputs (2);
+    aProgramSrc->SetWeightOitOutput (true);
   }
 
   aSrcVert = TCollection_AsciiString()
@@ -2082,7 +2079,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
     + (isFlatNormal
     ? EOL"  Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
     : "")
-    + EOL"  occFragColor = getColor();"
+    + EOL"  occSetFragColor (getColor());"
     + aSrcFragWriteOit
     + EOL"}";
 
@@ -2163,7 +2160,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  aColorL = pow (aColorL, THE_POW_UP);" // normalize
           EOL"  aColorR = pow (aColorR, THE_POW_UP);"
           EOL"  vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
-          EOL"  occFragColor = pow (aColor, THE_POW_DOWN);"
+          EOL"  occSetFragColor (pow (aColor, THE_POW_DOWN));"
           EOL"}";
       break;
     }
@@ -2181,11 +2178,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
           EOL"  if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
           EOL"  {"
-          EOL"    occFragColor = aColorL;"
+          EOL"    occSetFragColor (aColorL);"
           EOL"  }"
           EOL"  else"
           EOL"  {"
-          EOL"    occFragColor = aColorR;"
+          EOL"    occSetFragColor (aColorR);"
           EOL"  }"
           EOL"}";
       break;
@@ -2204,11 +2201,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
           EOL"  if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
           EOL"  {"
-          EOL"    occFragColor = aColorL;"
+          EOL"    occSetFragColor (aColorL);"
           EOL"  }"
           EOL"  else"
           EOL"  {"
-          EOL"    occFragColor = aColorR;"
+          EOL"    occSetFragColor (aColorR);"
           EOL"  }"
           EOL"}";
       break;
@@ -2229,11 +2226,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
           EOL"  if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
           EOL"  {"
-          EOL"    occFragColor = aColorL;"
+          EOL"    occSetFragColor (aColorL);"
           EOL"  }"
           EOL"  else"
           EOL"  {"
-          EOL"    occFragColor = aColorR;"
+          EOL"    occSetFragColor (aColorR);"
           EOL"  }"
           EOL"}";
       break;
@@ -2257,11 +2254,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
           EOL"  if (TexCoord.x <= 0.5)"
           EOL"  {"
-          EOL"    occFragColor = aColorL;"
+          EOL"    occSetFragColor (aColorL);"
           EOL"  }"
           EOL"  else"
           EOL"  {"
-          EOL"    occFragColor = aColorR;"
+          EOL"    occSetFragColor (aColorR);"
           EOL"  }"
           EOL"}";
       break;
@@ -2285,11 +2282,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
           EOL"  if (TexCoord.y <= 0.5)"
           EOL"  {"
-          EOL"    occFragColor = aColorL;"
+          EOL"    occSetFragColor (aColorL);"
           EOL"  }"
           EOL"  else"
           EOL"  {"
-          EOL"    occFragColor = aColorR;"
+          EOL"    occSetFragColor (aColorR);"
           EOL"  }"
           EOL"}";
       break;
@@ -2316,7 +2313,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
           EOL"  aColorL.b = 0.0;"
           EOL"  aColorL.g = 0.0;"
           EOL"  aColorR.r = 0.0;"
-          EOL"  occFragColor = aColorL + aColorR;"
+          EOL"  occSetFragColor (aColorL + aColorR);"
           EOL"}";
       break;
     }
index 17eae9c..1463fee 100755 (executable)
@@ -151,6 +151,8 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram
   myShareCount(1),
   myNbLightsMax (0),
   myNbClipPlanesMax (0),
+  myNbFragOutputs (1),
+  myHasWeightOitOutput (false),
   myHasTessShader (false)
 {
   memset (myCurrentState, 0, sizeof (myCurrentState));
@@ -180,6 +182,8 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     aShaderMask |= anIter.Value()->Type();
   }
   myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
+  myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
+  myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1;
 
   // detect the minimum GLSL version required for defined Shader Objects
 #if defined(GL_ES_VERSION_2_0)
@@ -275,19 +279,33 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     }
 
     TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
-    if (theCtx->hasDrawBuffers)
+    if (myNbFragOutputs > 1)
     {
-      anExtensions += "#define OCC_ENABLE_draw_buffers\n";
-    }
-    if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
-    {
-      if (theCtx->arbDrawBuffers)
+      if (theCtx->hasDrawBuffers)
       {
-        anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
+        anExtensions += "#define OCC_ENABLE_draw_buffers\n";
+        if (myHasWeightOitOutput)
+        {
+          anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
+        }
       }
-      else if (theCtx->extDrawBuffers)
+      else
+      {
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                             "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
+        return Standard_False;
+      }
+
+      if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
       {
-        anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
+        if (theCtx->arbDrawBuffers)
+        {
+          anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
+        }
+        else if (theCtx->extDrawBuffers)
+        {
+          anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
+        }
       }
     }
 
@@ -334,6 +352,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
+    aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
 
     const TCollection_AsciiString aSource = aHeaderVer                     // #version   - header defining GLSL version, should be first
                                           + (!aHeaderVer.IsEmpty() ? "\n" : "")
index 33d8e7d..86a239c 100755 (executable)
@@ -226,6 +226,13 @@ public:
   //! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS).
   Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; }
 
+  //! Return the length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS),
+  //! to be used for initialization occFragColorArray/occFragColorN.
+  Standard_Integer NbFragmentOutputs() const { return myNbFragOutputs; }
+
+  //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default.
+  Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; }
+
 private:
 
   //! Returns index of last modification of variables of specified state type.
@@ -569,6 +576,8 @@ protected:
   Standard_Integer                myShareCount;    //!< program users count, initialized with 1 (already shared by one user)
   Standard_Integer                myNbLightsMax;   //!< length of array of light sources (THE_MAX_LIGHTS)
   Standard_Integer                myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
+  Standard_Integer                myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
+  Standard_Boolean                myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage
   Standard_Boolean                myHasTessShader; //!< flag indicating that program defines tessellation stage
 
 protected:
index 929d909..0f5ba70 100644 (file)
 //! Specifies the length of array of clipping planes, which is 8 by default. Defined by Shader Manager.
 // #define THE_MAX_CLIP_PLANES 8
 
+//! @def THE_NB_FRAG_OUTPUTS
+//! Specifies the length of array of Fragment Shader outputs, which is 1 by default. Defined by Shader Manager.
+// #define THE_NB_FRAG_OUTPUTS 1
+
 // compatibility macros
 #if (__VERSION__ >= 130)
   #define THE_ATTRIBUTE  in
 #elif defined(FRAGMENT_SHADER)
   #if (__VERSION__ >= 130)
     #ifdef OCC_ENABLE_draw_buffers
-      out vec4 occFragColorArray[2];
-      #define occFragColor    occFragColorArray[0]
-      #define occFragCoverage occFragColorArray[1]
+      out vec4 occFragColorArray[THE_NB_FRAG_OUTPUTS];
+      #define occFragColorArrayAlias occFragColorArray
+      #define occFragColor0 occFragColorArray[0]
     #else
-      out vec4 occFragColor;
+      out vec4 occFragColor0;
     #endif
   #else
     #ifdef OCC_ENABLE_draw_buffers
-      #define occFragColor    gl_FragData[0]
-      #define occFragCoverage gl_FragData[1]
+      #define occFragColorArrayAlias gl_FragData
+      #define occFragColor0 gl_FragData[0]
     #else
-      #define occFragColor gl_FragColor
+      #define occFragColor0 gl_FragColor
     #endif
   #endif
+
+  #if (THE_NB_FRAG_OUTPUTS >= 2)
+    #define occFragColor1 occFragColorArrayAlias[1]
+  #else
+    vec4 occFragColor1;
+  #endif
+  #if (THE_NB_FRAG_OUTPUTS >= 3)
+    #define occFragColor2 occFragColorArrayAlias[2]
+  #else
+    vec4 occFragColor2;
+  #endif
+  #if (THE_NB_FRAG_OUTPUTS >= 4)
+    #define occFragColor3 occFragColorArrayAlias[3]
+  #else
+    vec4 occFragColor3;
+  #endif
+
+  // Built-in outputs notation
+  #define occFragColor    occFragColor0
+  #define occFragCoverage occFragColor1
+
+  //! Define the main Fragment Shader output - color value.
+  void occSetFragColor (in vec4 theColor);
 #endif
 
 // Matrix state
index e13307e..d3b1642 100644 (file)
 
 // This file includes implementation of common functions and properties accessors
 
+#if defined(FRAGMENT_SHADER)
+#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE)
+//! Output color and coverage for accumulation by OIT algorithm.
+void occSetFragColor (in vec4 theColor)
+{
+  float aWeight     = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);
+  occFragCoverage.r = theColor.a * aWeight;
+  occFragColor      = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a);
+}
+#else
+//! Output color.
+void occSetFragColor (in vec4 theColor) { occFragColor = theColor; }
+#endif
+#endif
+
 #if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)
 // arrays of light sources
 uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types
index 15311c7..d102812 100755 (executable)
@@ -186,14 +186,6 @@ void main()
     }
   }
 
-  occFragColor = computeLighting (normalize (Normal),
-                                  normalize (View),
-                                  Position);
-
-  if (occOitOutput != 0)
-  {
-    float aWeight     = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);
-    occFragCoverage.r = occFragColor.a * aWeight;
-    occFragColor      = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);
-  }
+  vec4 aColor = computeLighting (normalize (Normal), normalize (View), Position);
+  occSetFragColor (aColor);
 }
index 48e69b3..4ff7592 100644 (file)
@@ -18,6 +18,21 @@ static const char Shaders_DeclarationsImpl_glsl[] =
   "\n"
   "// This file includes implementation of common functions and properties accessors\n"
   "\n"
+  "#if defined(FRAGMENT_SHADER)\n"
+  "#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE)\n"
+  "//! Output color and coverage for accumulation by OIT algorithm.\n"
+  "void occSetFragColor (in vec4 theColor)\n"
+  "{\n"
+  "  float aWeight     = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);\n"
+  "  occFragCoverage.r = theColor.a * aWeight;\n"
+  "  occFragColor      = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a);\n"
+  "}\n"
+  "#else\n"
+  "//! Output color.\n"
+  "void occSetFragColor (in vec4 theColor) { occFragColor = theColor; }\n"
+  "#endif\n"
+  "#endif\n"
+  "\n"
   "#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n"
   "// arrays of light sources\n"
   "uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types\n"
index 46928f7..cec6805 100644 (file)
@@ -27,6 +27,10 @@ static const char Shaders_Declarations_glsl[] =
   "//! Specifies the length of array of clipping planes, which is 8 by default. Defined by Shader Manager.\n"
   "// #define THE_MAX_CLIP_PLANES 8\n"
   "\n"
+  "//! @def THE_NB_FRAG_OUTPUTS\n"
+  "//! Specifies the length of array of Fragment Shader outputs, which is 1 by default. Defined by Shader Manager.\n"
+  "// #define THE_NB_FRAG_OUTPUTS 1\n"
+  "\n"
   "// compatibility macros\n"
   "#if (__VERSION__ >= 130)\n"
   "  #define THE_ATTRIBUTE  in\n"
@@ -61,20 +65,43 @@ static const char Shaders_Declarations_glsl[] =
   "#elif defined(FRAGMENT_SHADER)\n"
   "  #if (__VERSION__ >= 130)\n"
   "    #ifdef OCC_ENABLE_draw_buffers\n"
-  "      out vec4 occFragColorArray[2];\n"
-  "      #define occFragColor    occFragColorArray[0]\n"
-  "      #define occFragCoverage occFragColorArray[1]\n"
+  "      out vec4 occFragColorArray[THE_NB_FRAG_OUTPUTS];\n"
+  "      #define occFragColorArrayAlias occFragColorArray\n"
+  "      #define occFragColor0 occFragColorArray[0]\n"
   "    #else\n"
-  "      out vec4 occFragColor;\n"
+  "      out vec4 occFragColor0;\n"
   "    #endif\n"
   "  #else\n"
   "    #ifdef OCC_ENABLE_draw_buffers\n"
-  "      #define occFragColor    gl_FragData[0]\n"
-  "      #define occFragCoverage gl_FragData[1]\n"
+  "      #define occFragColorArrayAlias gl_FragData\n"
+  "      #define occFragColor0 gl_FragData[0]\n"
   "    #else\n"
-  "      #define occFragColor gl_FragColor\n"
+  "      #define occFragColor0 gl_FragColor\n"
   "    #endif\n"
   "  #endif\n"
+  "\n"
+  "  #if (THE_NB_FRAG_OUTPUTS >= 2)\n"
+  "    #define occFragColor1 occFragColorArrayAlias[1]\n"
+  "  #else\n"
+  "    vec4 occFragColor1;\n"
+  "  #endif\n"
+  "  #if (THE_NB_FRAG_OUTPUTS >= 3)\n"
+  "    #define occFragColor2 occFragColorArrayAlias[2]\n"
+  "  #else\n"
+  "    vec4 occFragColor2;\n"
+  "  #endif\n"
+  "  #if (THE_NB_FRAG_OUTPUTS >= 4)\n"
+  "    #define occFragColor3 occFragColorArrayAlias[3]\n"
+  "  #else\n"
+  "    vec4 occFragColor3;\n"
+  "  #endif\n"
+  "\n"
+  "  // Built-in outputs notation\n"
+  "  #define occFragColor    occFragColor0\n"
+  "  #define occFragCoverage occFragColor1\n"
+  "\n"
+  "  //! Define the main Fragment Shader output - color value.\n"
+  "  void occSetFragColor (in vec4 theColor);\n"
   "#endif\n"
   "\n"
   "// Matrix state\n"
index 086ac82..e90d5b4 100644 (file)
@@ -736,7 +736,8 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
       const TCollection_AsciiString& aShaderSrc = aShader->Source();
 
       const bool hasVertPos   = aShaderSrc.Search ("gl_Position")  != -1;
-      const bool hasFragColor = aShaderSrc.Search ("occFragColor") != -1
+      const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1
+                             || aShaderSrc.Search ("occFragColor") != -1
                              || aShaderSrc.Search ("gl_FragColor") != -1
                              || aShaderSrc.Search ("gl_FragData")  != -1;
       Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg;
@@ -768,6 +769,13 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
     }
   }
 
+  if (!aProgram.IsNull()
+    && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
+  {
+    aProgram->SetNbFragmentOutputs (2);
+    aProgram->SetWeightOitOutput (true);
+  }
+
   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
   NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList);
   const bool isGlobalList = aPrsList.IsEmpty();