0025304: Visualization, TKOpenGl - support texturing within built-in GLSL programs
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
old mode 100755 (executable)
new mode 100644 (file)
index c0ce0eb..890d85b
@@ -36,6 +36,13 @@ namespace
 
 #define EOL "\n"
 
+//! Definition of VertColor varying.
+const char THE_VARY_VertColor[] =
+  EOL"varying vec4 VertColor;";
+
+const char THE_VARY_TexCoord[] =
+  EOL"varying vec2 TexCoord;";
+
 //! Auxiliary function to transform normal
 const char THE_FUNC_transformNormal[] =
   EOL"vec3 transformNormal (in vec3 theNormal)"
@@ -216,6 +223,20 @@ OpenGl_ShaderManager::~OpenGl_ShaderManager()
   myProgramList.Clear();
 }
 
+// =======================================================================
+// function : clear
+// purpose  :
+// =======================================================================
+void OpenGl_ShaderManager::clear()
+{
+  myProgramList.Clear();
+  myLightPrograms.Nullify();
+  myFlatPrograms = OpenGl_SetOfShaderPrograms();
+  myMapOfLightPrograms.Clear();
+  myFontProgram.Nullify();
+  switchLightPrograms();
+}
+
 // =======================================================================
 // function : Create
 // purpose  : Creates new shader program
@@ -370,7 +391,7 @@ void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
 // function : SetProjectionState
 // purpose  : Sets new state of OCCT projection transform
 // =======================================================================
-void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectionMatrix)
+void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
 {
   myProjectionState.Set (theProjectionMatrix);
   myProjectionState.Update();
@@ -380,7 +401,7 @@ void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectio
 // function : SetModelWorldState
 // purpose  : Sets new state of OCCT model-world transform
 // =======================================================================
-void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
+void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
 {
   myModelWorldState.Set (theModelWorldMatrix);
   myModelWorldState.Update();
@@ -390,42 +411,12 @@ void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorl
 // function : SetWorldViewState
 // purpose  : Sets new state of OCCT world-view transform
 // =======================================================================
-void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
+void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
 {
   myWorldViewState.Set (theWorldViewMatrix);
   myWorldViewState.Update();
 }
 
-// =======================================================================
-// function : RevertProjectionStateTo
-// purpose  : Reverts state of OCCT projection transform
-// =======================================================================
-void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3* theProjectionMatrix)
-{
-  myProjectionState.Set (theProjectionMatrix);
-  myProjectionState.Revert();
-}
-
-// =======================================================================
-// function : RevertModelWorldStateTo
-// purpose  : Reverts state of OCCT model-world transform
-// =======================================================================
-void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
-{
-  myModelWorldState.Set (theModelWorldMatrix);
-  myModelWorldState.Revert();
-}
-
-// =======================================================================
-// function : RevertWorldViewStateTo
-// purpose  : Reverts state of OCCT world-view transform
-// =======================================================================
-void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
-{
-  myWorldViewState.Set (theWorldViewMatrix);
-  myWorldViewState.Revert();
-}
-
 // =======================================================================
 // function : LightSourceState
 // purpose  : Returns current state of OCCT light sources
@@ -996,7 +987,7 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro
   PushMaterialState    (theProgram);
   PushWorldViewState   (theProgram);
   PushModelWorldState  (theProgram);
-  PushProjectionState  (theProgram);  
+  PushProjectionState  (theProgram);
   PushLightSourceState (theProgram);
 }
 
@@ -1076,11 +1067,24 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
         EOL"  gl_FragColor = aColor;";
     }
   }
+  else
+  {
+    if ((theBits & OpenGl_PO_TextureRGB) != 0)
+    {
+      aSrcVertExtraOut  += THE_VARY_TexCoord;
+      aSrcFragExtraOut  += THE_VARY_TexCoord;
+      aSrcVertExtraMain +=
+        EOL"  TexCoord = occTexCoord.st;";
+
+      aSrcFragGetColor =
+        EOL"vec4 getColor(void) { return texture2D(occActiveSampler, TexCoord.st); }";
+    }
+  }
   if ((theBits & OpenGl_PO_VertColor) != 0)
   {
-    aSrcVertExtraOut  += EOL"varying vec4 VertColor;";
+    aSrcVertExtraOut  += THE_VARY_VertColor;
     aSrcVertExtraMain += EOL"  VertColor = occVertColor;";
-    aSrcFragExtraOut  += EOL"varying vec4 VertColor;";
+    aSrcFragExtraOut  += THE_VARY_VertColor;
     aSrcFragGetColor  =  EOL"vec4 getColor(void) { return VertColor; }";
   }
   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
@@ -1130,7 +1134,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
 // function : stdComputeLighting
 // purpose  :
 // =======================================================================
-TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting()
+TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
 {
   bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
   TCollection_AsciiString aLightsFunc, aLightsLoop;
@@ -1173,6 +1177,14 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting()
     }
   }
 
+  TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient()  : occBackMaterial_Ambient();";
+  TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();";
+  if (theHasVertColor)
+  {
+    aGetMatAmbient = "getVertColor();";
+    aGetMatDiffuse = "getVertColor();";
+  }
+
   return TCollection_AsciiString()
     + THE_FUNC_lightDef
     + aLightsFunc
@@ -1187,9 +1199,9 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting()
       EOL"  Specular = vec3 (0.0);"
       EOL"  vec3 aPoint = thePoint.xyz / thePoint.w;"
     + aLightsLoop
-    + EOL"  vec4 aMaterialAmbient  = theIsFront ? occFrontMaterial_Ambient()  : occBackMaterial_Ambient();"
-      EOL"  vec4 aMaterialDiffuse  = theIsFront ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();"
-      EOL"  vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
+    + EOL"  vec4 aMaterialAmbient  = " + aGetMatAmbient
+    + EOL"  vec4 aMaterialDiffuse  = " + aGetMatDiffuse
+    + EOL"  vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
       EOL"  vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
       EOL"  return vec4 (Ambient,  1.0) * aMaterialAmbient"
       EOL"       + vec4 (Diffuse,  1.0) * aMaterialDiffuse"
@@ -1206,13 +1218,47 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
                                                                  const Standard_Integer        theBits)
 {
   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
-  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
   if ((theBits & OpenGl_PO_Point) != 0)
   {
   #if defined(GL_ES_VERSION_2_0)
     aSrcVertExtraMain += EOL"  gl_PointSize = occPointSize;";
   #endif
   }
+  if ((theBits & OpenGl_PO_VertColor) != 0)
+  {
+    aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
+  }
+  if ((theBits & OpenGl_PO_Point) != 0)
+  {
+    if ((theBits & OpenGl_PO_TextureRGB) != 0)
+    {
+      aSrcFragGetColor =
+        EOL"vec4 getColor(void)"
+        EOL"{"
+        EOL"  vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
+        EOL"  return texture2D(occActiveSampler, gl_PointCoord) * aColor;"
+        EOL"}";
+    }
+  }
+  else
+  {
+    if ((theBits & OpenGl_PO_TextureRGB) != 0)
+    {
+      aSrcVertExtraOut  += THE_VARY_TexCoord;
+      aSrcFragExtraOut  += THE_VARY_TexCoord;
+      aSrcVertExtraMain +=
+        EOL"  TexCoord = occTexCoord.st;";
+
+      aSrcFragGetColor =
+        EOL"vec4 getColor(void)"
+        EOL"{"
+        EOL"  vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
+        EOL"  return texture2D(occActiveSampler, TexCoord.st) * aColor;"
+        EOL"}";
+    }
+  }
   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
   {
     const char THE_POS_VARY[] =
@@ -1227,10 +1273,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
     aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
   }
 
-  const TCollection_AsciiString aLights = stdComputeLighting();
+  const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
   aSrcVert = TCollection_AsciiString()
     + THE_FUNC_transformNormal
     + EOL
+    + aSrcVertColor
     + aLights
     + EOL
       EOL"varying vec4 FrontColor;"
@@ -1253,10 +1300,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
     + EOL"varying vec4 FrontColor;"
       EOL"varying vec4 BackColor;"
     + aSrcFragExtraOut
+    + aSrcFragGetColor
     + EOL"void main()"
       EOL"{"
     + aSrcFragExtraMain
-    + EOL"  gl_FragColor = gl_FrontFacing ? FrontColor : BackColor;"
+    + EOL"  gl_FragColor = getColor();"
       EOL"}";
 
   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
@@ -1277,14 +1325,55 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
                                                                const Standard_Integer        theBits)
 {
+  #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
+
   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
-  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
   if ((theBits & OpenGl_PO_Point) != 0)
   {
   #if defined(GL_ES_VERSION_2_0)
     aSrcVertExtraMain += EOL"  gl_PointSize = occPointSize;";
   #endif
   }
+  if ((theBits & OpenGl_PO_VertColor) != 0)
+  {
+    aSrcVertExtraOut  += THE_VARY_VertColor;
+    aSrcVertExtraMain += EOL"  VertColor = occVertColor;";
+    aSrcFragGetColor   = EOL"varying vec4 VertColor;"
+                         EOL"vec4 getVertColor(void) { return VertColor; }";
+  }
+
+  if ((theBits & OpenGl_PO_Point) != 0)
+  {
+    if ((theBits & OpenGl_PO_TextureRGB) != 0)
+    {
+      aSrcFragGetColor =
+        EOL"vec4 getColor(void)"
+        EOL"{"
+        EOL"  vec4 aColor = " thePhongCompLight ";"
+        EOL"  return texture2D(occActiveSampler, gl_PointCoord) * aColor;"
+        EOL"}";
+    }
+  }
+  else
+  {
+    if ((theBits & OpenGl_PO_TextureRGB) != 0)
+    {
+      aSrcVertExtraOut  += THE_VARY_TexCoord;
+      aSrcFragExtraOut  += THE_VARY_TexCoord;
+      aSrcVertExtraMain +=
+        EOL"  TexCoord = occTexCoord.st;";
+
+      aSrcFragGetColor =
+        EOL"vec4 getColor(void)"
+        EOL"{"
+        EOL"  vec4 aColor = " thePhongCompLight ";"
+        EOL"  return texture2D(occActiveSampler, TexCoord.st) * aColor;"
+        EOL"}";
+    }
+  }
+
   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
   {
     aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
@@ -1309,19 +1398,22 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
     + EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
       EOL"}";
 
-  const TCollection_AsciiString aLights = stdComputeLighting();
+  const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
   aSrcFrag = TCollection_AsciiString()
     + EOL"varying vec4 PositionWorld;"
       EOL"varying vec4 Position;"
       EOL"varying vec3 Normal;"
       EOL"varying vec3 View;"
     + EOL
+    + aSrcFragExtraOut
+    + aSrcFragGetVertColor
     + aLights
+    + aSrcFragGetColor
     + EOL
       EOL"void main()"
       EOL"{"
     + aSrcFragExtraMain
-    + EOL"  gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing);"
+    + EOL"  gl_FragColor = getColor();"
       EOL"}";
 
   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));