0027925: Visualization - implement order-independent transparency algorithm within...
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
index d654c1e..7e3b8ad 100755 (executable)
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ArbTexBindless.hxx>
 
-IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
+#include <OpenGl_GlCore32.hxx>
+
+#include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
+#include "../Shaders/Shaders_Declarations_glsl.pxx"
+
+#ifdef _WIN32
+  #include <malloc.h> // for alloca()
+#endif
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram,OpenGl_Resource)
 
 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
 
@@ -48,7 +56,6 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
 
   "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
-  "occClipPlaneSpaces",    // OpenGl_OCC_CLIP_PLANE_SPACES
   "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
 
   "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
@@ -63,8 +70,11 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
   "occBackMaterial",       // OpenGl_OCCT_BACK_MATERIAL
   "occColor",              // OpenGl_OCCT_COLOR
 
-  "occPointSize"           // OpenGl_OCCT_POINT_SIZE
+  "occOitOutput",          // OpenGl_OCCT_OIT_OUTPUT
+  "occOitDepthFactor",     // OpenGl_OCCT_OIT_DEPTH_FACTOR
 
+  "occTexTrsf2d",          // OpenGl_OCCT_TEXTURE_TRSF2D
+  "occPointSize"           // OpenGl_OCCT_POINT_SIZE
 };
 
 // =======================================================================
@@ -141,33 +151,13 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  OSD_File aDeclFile     (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
-  OSD_File aDeclImplFile (Graphic3d_ShaderProgram::ShadersFolder() + "/DeclarationsImpl.glsl");
-  if (!aDeclFile.Exists()
-   || !aDeclImplFile.Exists())
-  {
-    const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
-                         0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
-                         aMsg);
-    return Standard_False;
-  }
-
   TCollection_AsciiString aHeader = !myProxy.IsNull() && !myProxy->Header().IsEmpty()
                                   ? (myProxy->Header() + "\n")
                                   : TCollection_AsciiString();
 
-  TCollection_AsciiString aDeclarations;
-  aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
-  aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
-  aDeclFile.Close();
+  TCollection_AsciiString aDeclarations = Shaders_Declarations_glsl;
+  TCollection_AsciiString aDeclImpl = Shaders_DeclarationsImpl_glsl;
 
-  TCollection_AsciiString aDeclImpl;
-  aDeclImplFile.Open (OSD_ReadOnly, OSD_Protection());
-  aDeclImplFile.Read (aDeclImpl, (int)aDeclImplFile.Size());
-  aDeclImplFile.Close();
   aDeclarations += aDeclImpl;
 
   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
@@ -176,10 +166,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     if (!anIter.Value()->IsDone())
     {
       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
       return Standard_False;
     }
@@ -201,10 +191,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     if (aShader.IsNull())
     {
       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
       return Standard_False;
     }
@@ -216,11 +206,43 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     }
 
     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
+    TCollection_AsciiString anExtensions = "// This section enables extensions used in OCCT GLSL programs\n";
+    if (theCtx->hasDrawBuffers)
+    {
+      anExtensions += "#define OCC_ENABLE_draw_buffers\n";
+    }
+    if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
+    {
+      if (theCtx->arbDrawBuffers)
+      {
+        anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
+      }
+      else if (theCtx->extDrawBuffers)
+      {
+        anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
+      }
+    }
+
+    if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
+    {
+#if defined(GL_ES_VERSION_2_0)
+      if (theCtx->oesSampleVariables)
+      {
+        anExtensions += "#extension GL_OES_sample_variables : enable\n";
+      }
+#else
+      if (theCtx->arbSampleShading)
+      {
+        anExtensions += "#extension GL_ARB_sample_shading : enable\n";
+      }
+#endif
+    }
+
     switch (anIter.Value()->Type())
     {
       case Graphic3d_TOS_VERTEX:
       {
-        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
+        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + anExtensions + aSource;
         break;
       }
       case Graphic3d_TOS_FRAGMENT:
@@ -228,10 +250,12 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
       #if defined(GL_ES_VERSION_2_0)
         TCollection_AsciiString aPrefix (theCtx->hasHighp
                                        ? "precision highp float;\n"
-                                       : "precision mediump float;\n");
-        aSource = aHeader + aPrefix + aSource;
+                                         "precision highp int;\n"
+                                       : "precision mediump float;\n"
+                                         "precision mediump int;\n");
+        aSource = aHeader + aPrefix + anExtensions + aSource;
       #else
-        aSource = aHeader + aSource;
+        aSource = aHeader + anExtensions + aSource;
       #endif
         break;
       }
@@ -239,11 +263,12 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
 
     if (!aShader->LoadSource (theCtx, aSource))
     {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aSource);
       const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
       aShader->Release (theCtx.operator->());
       return Standard_False;
@@ -251,16 +276,17 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
 
     if (!aShader->Compile (theCtx))
     {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aSource);
       TCollection_AsciiString aLog;
       aShader->FetchInfoLog (theCtx, aLog);
       if (aLog.IsEmpty())
       {
         aLog = "Compilation log is empty.";
       }
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
       aShader->Release (theCtx.operator->());
       return Standard_False;
@@ -272,10 +298,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
       if (!aLog.IsEmpty()
        && !aLog.IsEqual ("No errors.\n"))
       {
-        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                             GL_DEBUG_TYPE_PORTABILITY_ARB,
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                             GL_DEBUG_TYPE_PORTABILITY,
                              0,
-                             GL_DEBUG_SEVERITY_LOW_ARB,
+                             GL_DEBUG_SEVERITY_LOW,
                              TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
       }
     }
@@ -293,6 +319,16 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
   SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
   SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
 
+  // bind custom Vertex Attributes
+  if (!myProxy.IsNull())
+  {
+    for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
+         anAttribIter.More(); anAttribIter.Next())
+    {
+      SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
+    }
+  }
+
   if (!Link (theCtx))
   {
     TCollection_AsciiString aLog;
@@ -301,10 +337,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     {
       aLog = "Linker log is empty.";
     }
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                         GL_DEBUG_TYPE_ERROR,
                          0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
+                         GL_DEBUG_SEVERITY_HIGH,
                          TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
     return Standard_False;
   }
@@ -315,14 +351,27 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     if (!aLog.IsEmpty()
      && !aLog.IsEqual ("No errors.\n"))
     {
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_PORTABILITY_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_PORTABILITY,
                            0,
-                           GL_DEBUG_SEVERITY_LOW_ARB,
+                           GL_DEBUG_SEVERITY_LOW,
                            TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
     }
   }
 
+  // set uniform defaults
+  const GLint aLocSampler   = GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER);
+  const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
+  if (aLocSampler   != INVALID_LOCATION
+   || aLocTexEnable != INVALID_LOCATION)
+  {
+    const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
+    theCtx->core20fwd->glUseProgram (myProgramID);
+    SetUniform (theCtx, aLocSampler,   0); // GL_TEXTURE0
+    SetUniform (theCtx, aLocTexEnable, 0); // Off
+    theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
+  }
+
   return Standard_True;
 }
 
@@ -464,32 +513,6 @@ Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Contex
   return Standard_True;
 }
 
-// =======================================================================
-// function : ActiveState
-// purpose  : Returns index of last modification for specified state type
-// =======================================================================
-Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
-{
-  if (theType < MaxStateTypes)
-  {
-    return myCurrentState[theType];
-  }
-  return 0;
-}
-
-// =======================================================================
-// function : UpdateState
-// purpose  : Updates index of last modification for specified state type
-// =======================================================================
-void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
-                                        const Standard_Size           theIndex)
-{
-  if (theType < MaxStateTypes)
-  {
-    myCurrentState[theType] = theIndex;
-  }
-}
-
 // =======================================================================
 // function : GetUniformLocation
 // purpose  : Returns location (index) of the specific uniform variable
@@ -793,66 +816,71 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 
 // =======================================================================
 // function : SetUniform
-// purpose  : Specifies the value of the 64-bit unsigned uniform variable
+// purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    const GLchar*                 theName,
-                                                   GLuint64                      theValue)
+                                                   const OpenGl_Vec2u&           theValue)
 {
   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
 }
 
 // =======================================================================
 // function : SetUniform
-// purpose  : Specifies the value of the 64-bit unsigned uniform variable
+// purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    GLint                         theLocation,
-                                                   GLuint64                      theValue)
+                                                   const OpenGl_Vec2u&           theValue)
 {
-  if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
   {
     return Standard_False;
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  theCtx->arbTexBindless->glUniformHandleui64ARB (theLocation, theValue);
-#endif
-
+  theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
   return Standard_True;
+#else
+  (void )theValue;
+  return Standard_False;
+#endif
 }
 
 // =======================================================================
 // function : SetUniform
-// purpose  : Specifies the value of the 64-bit unsigned uniform array
+// purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    const GLchar*                 theName,
                                                    const GLsizei                 theCount,
-                                                   const GLuint64*               theValue)
+                                                   const OpenGl_Vec2u*           theValue)
 {
   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
 }
 
 // =======================================================================
 // function : SetUniform
-// purpose  : Specifies the value of the 64-bit unsigned uniform array
+// purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    GLint                         theLocation,
                                                    const GLsizei                 theCount,
-                                                   const GLuint64*               theValue)
+                                                   const OpenGl_Vec2u*           theValue)
 {
-  if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
   {
     return Standard_False;
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  theCtx->arbTexBindless->glUniformHandleui64vARB (theLocation, theCount, theValue);
-#endif
-
+  theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
   return Standard_True;
+#else
+  (void )theCount;
+  (void )theValue;
+  return Standard_False;
+#endif
 }
 
 // =======================================================================