0028180: Visualization, TKOpenGl - Performance of Shaded presentation dropped due...
authorkgv <kgv@opencascade.com>
Thu, 22 Dec 2016 09:48:16 +0000 (12:48 +0300)
committerkgv <kgv@opencascade.com>
Thu, 22 Dec 2016 14:24:05 +0000 (17:24 +0300)
FFP state management (light sources, matrices, clipping planes) has been
moved to OpenGl_ShaderManager for consistency with Programmable Pipeline.

OpenGl_Context::BindProgram() does not re-bind already active Program.
OpenGl_PrimitiveArray::Render() does not reset active Program at the end.

OpenGl_Context::ApplyModelViewMatrix() now checks if matrix differs
from already set one before modifying state in Shader Manager.
This allows avoing redundant state changes, matrix uploads onto GPU
and re-computation of inversed matrices.

NCollection_Mat4 has been extended with equality check operators for proper comparison.

OpenGl_ShaderManager - the tracking Material state has been added.
Removed unreachable states OPENGL_NS_RESMAT, OPENGL_NS_TEXTURE and OPENGL_NS_WHITEBACK.

Fixed resetting FFP material state after displaying GL_COLOR_ARRAY vertices;
the Material state within Shader Manager is now
invalidated within OpenGl_VertexBuffer::unbindFixedColor().

OpenGl_Workspace::ApplyAspectFace() - fixed invalidating Material State
when only Highlighting style is changing.

28 files changed:
src/NCollection/NCollection_Mat4.hxx
src/NCollection/NCollection_Vec2.hxx
src/NCollection/NCollection_Vec3.hxx
src/NCollection/NCollection_Vec4.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_Clipping.cxx
src/OpenGl/OpenGl_Clipping.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_Material.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_MaterialState.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_NamedStatus.hxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_ShaderStates.cxx
src/OpenGl/OpenGl_ShaderStates.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_VertexBuffer.cxx
src/OpenGl/OpenGl_VertexBuffer.hxx
src/OpenGl/OpenGl_VertexBuffer.lxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx

index 0f74844..df74c37 100755 (executable)
@@ -185,6 +185,20 @@ public:
     return std::memcmp (this, myIdentityArray, sizeof (NCollection_Mat4)) == 0;
   }
 
+  //! Check this matrix for equality with another matrix (without tolerance!).
+  bool IsEqual (const NCollection_Mat4& theOther) const
+  {
+    return std::memcmp (this, &theOther, sizeof(NCollection_Mat4)) == 0;
+  }
+
+  //! Check this matrix for equality with another matrix (without tolerance!).
+  bool operator== (const NCollection_Mat4& theOther)       { return IsEqual (theOther); }
+  bool operator== (const NCollection_Mat4& theOther) const { return IsEqual (theOther); }
+
+  //! Check this matrix for non-equality with another matrix (without tolerance!).
+  bool operator!= (const NCollection_Mat4& theOther)       { return !IsEqual (theOther); }
+  bool operator!= (const NCollection_Mat4& theOther) const { return !IsEqual (theOther); }
+
   //! Raw access to the data (for OpenGL exchange).
   const Element_t* GetData()    const { return myMat; }
   Element_t*       ChangeData()       { return myMat; }
@@ -456,4 +470,11 @@ Element_t NCollection_Mat4<Element_t>::myIdentityArray[] =
    0, 0, 1, 0,
    0, 0, 0, 1};
 
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+  #include <type_traits>
+
+  static_assert(std::is_trivially_copyable<NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_trivially_copyable() structure!");
+  static_assert(std::is_standard_layout   <NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_standard_layout() structure!");
+#endif
+
 #endif // _NCollection_Mat4_HeaderFile
index 79b9512..132b6db 100644 (file)
@@ -72,6 +72,21 @@ public:
   //! Alias to 2nd component as Y coordinate in XY.
   Element_t& y() { return v[1]; }
 
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool IsEqual (const NCollection_Vec2& theOther) const
+  {
+    return v[0] == theOther.v[0]
+        && v[1] == theOther.v[1];
+  }
+
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool operator== (const NCollection_Vec2& theOther)       { return IsEqual (theOther); }
+  bool operator== (const NCollection_Vec2& theOther) const { return IsEqual (theOther); }
+
+  //! Check this vector with another vector for non-equality (without tolerance!).
+  bool operator!= (const NCollection_Vec2& theOther)       { return !IsEqual (theOther); }
+  bool operator!= (const NCollection_Vec2& theOther) const { return !IsEqual (theOther); }
+
   //! Raw access to the data (for OpenGL exchange).
   const Element_t* GetData()    const { return v; }
         Element_t* ChangeData()       { return v; }
index 73b9743..91e2468 100644 (file)
@@ -129,6 +129,22 @@ public:
     return *((NCollection_Vec2<Element_t>* )&v[1]);
   }
 
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool IsEqual (const NCollection_Vec3& theOther) const
+  {
+    return v[0] == theOther.v[0]
+        && v[1] == theOther.v[1]
+        && v[2] == theOther.v[2];
+  }
+
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool operator== (const NCollection_Vec3& theOther)       { return IsEqual (theOther); }
+  bool operator== (const NCollection_Vec3& theOther) const { return IsEqual (theOther); }
+
+  //! Check this vector with another vector for non-equality (without tolerance!).
+  bool operator!= (const NCollection_Vec3& theOther)       { return !IsEqual (theOther); }
+  bool operator!= (const NCollection_Vec3& theOther) const { return !IsEqual (theOther); }
+
   //! Raw access to the data (for OpenGL exchange).
   const Element_t* GetData()    const { return v; }
         Element_t* ChangeData()       { return v; }
index 87948cb..9bc63f9 100644 (file)
@@ -175,6 +175,23 @@ public:
     return *((NCollection_Vec3<Element_t>* )&v[1]);
   }
 
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool IsEqual (const NCollection_Vec4& theOther) const
+  {
+    return v[0] == theOther.v[0]
+        && v[1] == theOther.v[1]
+        && v[2] == theOther.v[2]
+        && v[3] == theOther.v[3];
+  }
+
+  //! Check this vector with another vector for equality (without tolerance!).
+  bool operator== (const NCollection_Vec4& theOther)       { return IsEqual (theOther); }
+  bool operator== (const NCollection_Vec4& theOther) const { return IsEqual (theOther); }
+
+  //! Check this vector with another vector for non-equality (without tolerance!).
+  bool operator!= (const NCollection_Vec4& theOther)       { return !IsEqual (theOther); }
+  bool operator!= (const NCollection_Vec4& theOther) const { return !IsEqual (theOther); }
+
   //! Raw access to the data (for OpenGL exchange).
   const Element_t* GetData()    const { return v; }
         Element_t* ChangeData()       { return v; }
index e6f600d..b9dbf9e 100755 (executable)
@@ -36,6 +36,8 @@ OpenGl_Light.hxx
 OpenGl_GraduatedTrihedron.hxx
 OpenGl_GraduatedTrihedron.cxx
 OpenGl_MapOfZLayerSettings.hxx
+OpenGl_Material.hxx
+OpenGl_MaterialState.hxx
 OpenGl_Matrix.hxx
 OpenGl_MatrixState.hxx
 OpenGl_NamedStatus.hxx
index da56cd4..edc9b71 100755 (executable)
@@ -42,8 +42,7 @@ OpenGl_ClippingIterator::OpenGl_ClippingIterator (const OpenGl_Clipping& theClip
 // purpose  :
 // =======================================================================
 OpenGl_Clipping::OpenGl_Clipping ()
-: myEmptyPlaneIds (new NCollection_Shared<Aspect_GenId> (1, 6)),
-  myNbClipping (0),
+: myNbClipping (0),
   myNbCapping  (0),
   myNbDisabled (0)
 {}
@@ -52,7 +51,7 @@ OpenGl_Clipping::OpenGl_Clipping ()
 // function : Init
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
+void OpenGl_Clipping::Init (const Standard_Integer )
 {
   myPlanesGlobal.Nullify();
   myPlanesLocal.Nullify();
@@ -60,7 +59,6 @@ void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
   myNbClipping = 0;
   myNbCapping  = 0;
   myNbDisabled = 0;
-  myEmptyPlaneIds = new NCollection_Shared<Aspect_GenId> (1, theMaxPlanes);
 }
 
 // =======================================================================
@@ -105,7 +103,7 @@ void OpenGl_Clipping::SetLocalPlanes (const Handle(OpenGl_Context)& theGlCtx,
 // function : add
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
+void OpenGl_Clipping::add (const Handle(OpenGl_Context)& ,
                            const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                            const Standard_Integer theStartIndex)
 {
@@ -114,18 +112,6 @@ void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
     return;
   }
 
-#if !defined(GL_ES_VERSION_2_0)
-  const bool toUseFfp = theGlCtx->core11 != NULL
-                     && theGlCtx->caps->ffpEnable;
-  if (toUseFfp)
-  {
-    // Set either identity or pure view matrix.
-    theGlCtx->ApplyWorldViewMatrix();
-  }
-#else
-  (void )theGlCtx;
-#endif
-
   Standard_Integer aPlaneId = theStartIndex;
   for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneId)
   {
@@ -136,14 +122,6 @@ void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
       continue;
     }
 
-  #if !defined(GL_ES_VERSION_2_0)
-    if (toUseFfp && myEmptyPlaneIds->HasFree())
-    {
-      const Standard_Integer anFfpPlaneID = GL_CLIP_PLANE0 + myEmptyPlaneIds->Next();
-      ::glEnable ((GLenum )anFfpPlaneID);
-      theGlCtx->core11->glClipPlane ((GLenum )anFfpPlaneID, aPlane->GetEquation());
-    }
-  #endif
     if (aPlane->IsCapping())
     {
       ++myNbCapping;
@@ -153,21 +131,13 @@ void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
       ++myNbClipping;
     }
   }
-
-#if !defined(GL_ES_VERSION_2_0)
-  // Restore combined model-view matrix.
-  if (toUseFfp)
-  {
-    theGlCtx->ApplyModelViewMatrix();
-  }
-#endif
 }
 
 // =======================================================================
 // function : remove
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
+void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& ,
                               const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
                               const Standard_Integer theStartIndex)
 {
@@ -176,13 +146,6 @@ void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
     return;
   }
 
-#if !defined(GL_ES_VERSION_2_0)
-  const bool toUseFfp = theGlCtx->core11 != NULL
-                     && theGlCtx->caps->ffpEnable;
-#else
-  (void )theGlCtx;
-#endif
-
   Standard_Integer aPlaneIndex = theStartIndex;
   for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneIndex)
   {
@@ -193,18 +156,6 @@ void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
       continue;
     }
 
-  #if !defined(GL_ES_VERSION_2_0)
-    const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
-    if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
-    {
-      if (toUseFfp)
-      {
-        ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
-      }
-      myEmptyPlaneIds->Free (anFfpPlaneID);
-    }
-  #endif
-
     if (aPlane->IsCapping())
     {
       --myNbCapping;
@@ -220,7 +171,7 @@ void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
 // function : SetEnabled
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  theGlCtx,
+Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  ,
                                               const OpenGl_ClippingIterator& thePlane,
                                               const Standard_Boolean         theIsEnabled)
 {
@@ -232,29 +183,6 @@ Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  the
   }
 
   isDisabled = !theIsEnabled;
-
-#if !defined(GL_ES_VERSION_2_0)
-  const bool toUseFfp = theGlCtx->core11 != NULL
-                     && theGlCtx->caps->ffpEnable;
-  if (toUseFfp)
-  {
-    const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
-    if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
-    {
-      if (theIsEnabled)
-      {
-        ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
-      }
-      else
-      {
-        ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
-      }
-    }
-  }
-#else
-  (void )theGlCtx;
-#endif
-
   if (thePlane.Value()->IsCapping())
   {
     myNbCapping += (theIsEnabled ? 1 : -1);
@@ -271,7 +199,7 @@ Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&  the
 // function : RestoreDisabled
 // purpose  :
 // =======================================================================
-void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& )
 {
   if (myNbDisabled == 0)
   {
@@ -279,12 +207,6 @@ void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx)
   }
 
   myNbDisabled = 0;
-#if !defined(GL_ES_VERSION_2_0)
-  const bool toUseFfp = theGlCtx->core11 != NULL
-                     && theGlCtx->caps->ffpEnable;
-#else
-  (void )theGlCtx;
-#endif
   for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
   {
     Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIter.PlaneIndex());
@@ -294,17 +216,6 @@ void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx)
     }
 
     isDisabled = Standard_False;
-  #if !defined(GL_ES_VERSION_2_0)
-    if (toUseFfp)
-    {
-      const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIter.PlaneIndex() - 1;
-      if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
-      {
-        ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
-      }
-    }
-  #endif
-
     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
     if (aPlane->IsCapping())
     {
index 0086887..6e1c5d3 100755 (executable)
@@ -16,7 +16,6 @@
 #ifndef _OpenGl_Clipping_H__
 #define _OpenGl_Clipping_H__
 
-#include <Aspect_GenId.hxx>
 #include <Graphic3d_SequenceOfHClipPlane.hxx>
 #include <NCollection_Vector.hxx>
 #include <Standard_TypeDef.hxx>
@@ -119,7 +118,6 @@ private:
   Handle(Graphic3d_SequenceOfHClipPlane)   myPlanesLocal;    //!< object clipping planes
   NCollection_Vector<Standard_Boolean>     myDisabledPlanes; //!< ids of disabled planes
   NCollection_Vector<Standard_Boolean>     mySkipFilter;     //!< ids of planes that were disabled before calling ::DisableAllExcept()
-  Handle(NCollection_Shared<Aspect_GenId>) myEmptyPlaneIds;  //!< generator of empty ids for FFP clipping planes
   Standard_Integer                         myNbClipping;     //!< number of enabled clipping-only planes (NOT capping)
   Standard_Integer                         myNbCapping;      //!< number of enabled capping  planes
   Standard_Integer                         myNbDisabled;     //!< number of defined but disabled planes
index 23b6337..2585bf6 100644 (file)
@@ -2793,6 +2793,10 @@ Standard_Boolean OpenGl_Context::BindProgram (const Handle(OpenGl_ShaderProgram)
   {
     return Standard_False;
   }
+  else if (myActiveProgram == theProgram)
+  {
+    return Standard_True;
+  }
 
   if (theProgram.IsNull()
   || !theProgram->IsValid())
@@ -2843,56 +2847,100 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O
 // purpose  :
 // =======================================================================
 void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
-                                         const Handle(Graphic3d_PresentationAttributes)& theHighlight)
+                                         const Handle(Graphic3d_PresentationAttributes)& theHighlight,
+                                         const Standard_Boolean theUseDepthWrite,
+                                         Standard_Integer& theRenderingPassFlags)
 {
-  if (!myActiveProgram.IsNull())
+  const Handle(Graphic3d_AspectFillArea3d)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
+                                                      ?  theHighlight->BasicFillAreaAspect()
+                                                      :  theAspect->Aspect();
+
+  const bool toDistinguish = anAspect->Distinguish();
+  const bool toMapTexture  = anAspect->ToMapTexture();
+  const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
+  const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
+                                               ? anAspect->BackMaterial()
+                                               : aMatFrontSrc;
+  const Quantity_Color& aFrontIntColor = anAspect->InteriorColor();
+  const Quantity_Color& aBackIntColor  = toDistinguish
+                                       ? anAspect->BackInteriorColor()
+                                       : aFrontIntColor;
+
+  myMatFront.Init (aMatFrontSrc, aFrontIntColor);
+  if (toDistinguish)
+  {
+    myMatBack.Init (aMatBackSrc, aBackIntColor);
+  }
+  else
   {
-    const Handle(Graphic3d_AspectFillArea3d)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
-                                                       ?  theHighlight->BasicFillAreaAspect()
-                                                       :  theAspect->Aspect();
-    myActiveProgram->SetUniform (this,
-                                 myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
-                                 anAspect->ToMapTexture() ? 1 : 0);
-    myActiveProgram->SetUniform (this,
-                                 myActiveProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
-                                 anAspect->Distinguish() ? 1 : 0);
-
-    OpenGl_Material aParams;
-    for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
-    {
-      const GLint aLoc = myActiveProgram->GetStateLocation (anIndex == 0
-                                                          ? OpenGl_OCCT_FRONT_MATERIAL
-                                                          : OpenGl_OCCT_BACK_MATERIAL);
-      if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
-      {
-        continue;
-      }
+    myMatBack = myMatFront;
+  }
 
-      if (anIndex == 0 || !anAspect->Distinguish())
-      {
-        const Graphic3d_MaterialAspect& aSrcMat      = anAspect->FrontMaterial();
-        const Quantity_Color&           aSrcIntColor = anAspect->InteriorColor();
-        aParams.Init (aSrcMat, aSrcIntColor);
-        aParams.Diffuse.a() = 1.0f - (float )aSrcMat.Transparency();
-      }
-      else
-      {
-        const Graphic3d_MaterialAspect& aSrcMat      = anAspect->BackMaterial();
-        const Quantity_Color&           aSrcIntColor = anAspect->BackInteriorColor();
-        aParams.Init (aSrcMat, aSrcIntColor);
-        aParams.Diffuse.a() = 1.0f - (float )aSrcMat.Transparency();
-      }
-      if (!theHighlight.IsNull()
-        && theHighlight->BasicFillAreaAspect().IsNull())
-      {
-        aParams.SetColor (theHighlight->ColorRGBA());
-        aParams.Diffuse.a() = theHighlight->ColorRGBA().Alpha();
-      }
+  // handling transparency
+  float aTranspFront = (float )aMatFrontSrc.Transparency();
+  float aTranspBack  = (float )aMatBackSrc .Transparency();
+  if (!theHighlight.IsNull()
+    && theHighlight->BasicFillAreaAspect().IsNull())
+  {
+    myMatFront.SetColor (theHighlight->ColorRGBA());
+    myMatBack .SetColor (theHighlight->ColorRGBA());
+    aTranspFront = theHighlight->Transparency();
+    aTranspBack  = theHighlight->Transparency();
+  }
+  if ((theRenderingPassFlags & OPENGL_NS_2NDPASSDO) != 0)
+  {
+    // second pass
+    myMatFront.Diffuse.a() = aMatFrontSrc.EnvReflexion();
+    myMatBack .Diffuse.a() = aMatBackSrc .EnvReflexion();
+  }
+  else
+  {
+    if (aMatFrontSrc.EnvReflexion() != 0.0f
+     || aMatBackSrc .EnvReflexion() != 0.0f)
+    {
+      // if the material reflects the environment scene, the second pass is needed
+      theRenderingPassFlags |= OPENGL_NS_2NDPASSNEED;
+    }
 
-      myActiveProgram->SetUniform (this, aLoc, OpenGl_Material::NbOfVec4(),
-                                   aParams.Packed());
+    GLboolean aDepthMask = GL_TRUE;
+    if (aTranspFront != 0.0f
+     || aTranspBack  != 0.0f)
+    {
+      // render transparent
+      myMatFront.Diffuse.a() = 1.0f - aTranspFront;
+      myMatBack .Diffuse.a() = 1.0f - aTranspBack;
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glEnable (GL_BLEND);
+      aDepthMask = GL_FALSE;
+    }
+    else
+    {
+      // render opaque
+      glBlendFunc (GL_ONE, GL_ZERO);
+      glDisable (GL_BLEND);
+    }
+    if (theUseDepthWrite)
+    {
+      glDepthMask (aDepthMask);
     }
   }
+
+  // do not update material properties in case of zero reflection mode,
+  // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
+  if (theAspect->IsNoLighting())
+  {
+    return;
+  }
+
+  if (myMatFront    == myShaderManager->MaterialState().FrontMaterial()
+   && myMatBack     == myShaderManager->MaterialState().BackMaterial()
+   && toDistinguish == myShaderManager->MaterialState().ToDistinguish()
+   && toMapTexture  == myShaderManager->MaterialState().ToMapTexture())
+  {
+    return;
+  }
+
+  myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, toDistinguish, toMapTexture);
 }
 
 // =======================================================================
@@ -3206,15 +3254,7 @@ Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_Ha
 // =======================================================================
 void OpenGl_Context::ApplyModelWorldMatrix()
 {
-#if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
-  {
-    core11->glMatrixMode (GL_MODELVIEW);
-    core11->glLoadMatrixf (ModelWorldState.Current());
-  }
-#endif
-
-  if (!myShaderManager->IsEmpty())
+  if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
   {
     myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
   }
@@ -3226,17 +3266,12 @@ void OpenGl_Context::ApplyModelWorldMatrix()
 // =======================================================================
 void OpenGl_Context::ApplyWorldViewMatrix()
 {
-#if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
+  if (myShaderManager->ModelWorldState().ModelWorldMatrix() != THE_IDENTITY_MATRIX)
   {
-    core11->glMatrixMode (GL_MODELVIEW);
-    core11->glLoadMatrixf (WorldViewState.Current());
+    myShaderManager->UpdateModelWorldStateTo (THE_IDENTITY_MATRIX);
   }
-#endif
-
-  if (!myShaderManager->IsEmpty())
+  if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
   {
-    myShaderManager->UpdateModelWorldStateTo (THE_IDENTITY_MATRIX);
     myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current());
   }
 }
@@ -3247,19 +3282,13 @@ void OpenGl_Context::ApplyWorldViewMatrix()
 // =======================================================================
 void OpenGl_Context::ApplyModelViewMatrix()
 {
-#if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
+  if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
   {
-    OpenGl_Mat4 aModelView = WorldViewState.Current() * ModelWorldState.Current();
-    core11->glMatrixMode (GL_MODELVIEW);
-    core11->glLoadMatrixf (aModelView.GetData());
+    myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
   }
-#endif
-
-  if (!myShaderManager->IsEmpty())
+  if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
   {
-    myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
-    myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current());
+    myShaderManager->UpdateWorldViewStateTo  (WorldViewState.Current());
   }
 }
 
@@ -3269,21 +3298,12 @@ void OpenGl_Context::ApplyModelViewMatrix()
 // =======================================================================
 void OpenGl_Context::ApplyProjectionMatrix()
 {
-#if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
-  {
-    core11->glMatrixMode (GL_PROJECTION);
-    core11->glLoadMatrixf (ProjectionState.Current().GetData());
-  }
-#endif
-
-  if (!myShaderManager->IsEmpty())
+  if (myShaderManager->ProjectionState().ProjectionMatrix() != ProjectionState.Current())
   {
     myShaderManager->UpdateProjectionStateTo (ProjectionState.Current());
   }
 }
 
-
 // =======================================================================
 // function : EnableFeatures
 // purpose  :
index d74c2fc..e5bddc0 100644 (file)
@@ -30,6 +30,7 @@
 #include <Message.hxx>
 #include <OpenGl_Caps.hxx>
 #include <OpenGl_LineAttributes.hxx>
+#include <OpenGl_Material.hxx>
 #include <OpenGl_MatrixState.hxx>
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_Resource.hxx>
@@ -184,6 +185,8 @@ DEFINE_STANDARD_HANDLE(OpenGl_Context, Standard_Transient)
 //! For this reason OpenGl_Context should be initialized and used for each GL context independently.
 class OpenGl_Context : public Standard_Transient
 {
+  DEFINE_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
+  friend class OpenGl_Window;
 public:
 
   //! Function for getting power of to number larger or equal to input number.
@@ -624,7 +627,9 @@ public: //! @name methods to alter or retrieve current state
 
   //! Setup current shading material.
   Standard_EXPORT void SetShadingMaterial (const OpenGl_AspectFace* theAspect,
-                                           const Handle(Graphic3d_PresentationAttributes)& theHighlight = Handle(Graphic3d_PresentationAttributes)());
+                                           const Handle(Graphic3d_PresentationAttributes)& theHighlight,
+                                           const Standard_Boolean theUseDepthWrite,
+                                           Standard_Integer& theRenderingPassFlags);
 
   //! Setup current color.
   Standard_EXPORT void SetColor4fv (const OpenGl_Vec4& theColor);
@@ -739,6 +744,12 @@ public: //! @name extensions
   Standard_Boolean       atiMem;         //!< GL_ATI_meminfo
   Standard_Boolean       nvxMem;         //!< GL_NVX_gpu_memory_info
 
+public: //! @name public properties tracking current state
+
+  OpenGl_MatrixState<Standard_ShortReal> ModelWorldState; //!< state of orientation matrix
+  OpenGl_MatrixState<Standard_ShortReal> WorldViewState;  //!< state of orientation matrix
+  OpenGl_MatrixState<Standard_ShortReal> ProjectionState; //!< state of projection  matrix
+
 private: // system-dependent fields
 
 #if defined(HAVE_EGL)
@@ -812,13 +823,9 @@ private: //! @name fields tracking current state
   TCollection_AsciiString       myVendor;          //!< Graphics Driver's vendor
   TColStd_PackedMapOfInteger    myFilters[6];      //!< messages suppressing filter (for sources from GL_DEBUG_SOURCE_API_ARB to GL_DEBUG_SOURCE_OTHER_ARB)
   Standard_ShortReal            myResolutionRatio; //!< scaling factor for parameters like text size
-                                                  //!< to be properly displayed on device (screen / printer)
-
-public:
-
-  OpenGl_MatrixState<Standard_ShortReal> ModelWorldState; //!< state of orientation matrix
-  OpenGl_MatrixState<Standard_ShortReal> WorldViewState;  //!< state of orientation matrix
-  OpenGl_MatrixState<Standard_ShortReal> ProjectionState; //!< state of projection  matrix
+                                                   //!< to be properly displayed on device (screen / printer)
+  OpenGl_Material               myMatFront;        //!< current front material state (cached to reduce GL context updates)
+  OpenGl_Material               myMatBack;         //!< current back  material state
 
 private:
 
@@ -826,12 +833,6 @@ private:
   OpenGl_Context            (const OpenGl_Context& );
   OpenGl_Context& operator= (const OpenGl_Context& );
 
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient) // Type definition
-
-  friend class OpenGl_Window;
-
 };
 
 #endif // _OpenGl_Context_H__
diff --git a/src/OpenGl/OpenGl_Material.hxx b/src/OpenGl/OpenGl_Material.hxx
new file mode 100644 (file)
index 0000000..928f5a9
--- /dev/null
@@ -0,0 +1,77 @@
+// Created on: 2011-09-20
+// Created by: Sergey ZERCHANINOV
+// Copyright (c) 2011-2013 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _OpenGl_Material_Header
+#define _OpenGl_Material_Header
+
+#include <Graphic3d_MaterialAspect.hxx>
+#include <OpenGl_Vec.hxx>
+
+//! OpenGL material definition
+struct OpenGl_Material
+{
+
+  OpenGl_Vec4 Ambient;  //!< ambient reflection coefficient
+  OpenGl_Vec4 Diffuse;  //!< diffuse reflection coefficient
+  OpenGl_Vec4 Specular; //!< glossy  reflection coefficient
+  OpenGl_Vec4 Emission; //!< material emission
+  OpenGl_Vec4 Params;   //!< extra packed parameters
+
+  float  Shine()        const { return Params.x(); }
+  float& ChangeShine()        { return Params.x(); }
+
+  float  Transparency() const { return Params.y(); }
+  float& ChangeTransparency() { return Params.y(); }
+
+  //! Set material color.
+  void SetColor (const OpenGl_Vec4& theColor)
+  {
+    // apply the same formula as in Graphic3d_MaterialAspect::SetColor()
+    Ambient.xyz() = theColor.rgb() * 0.25f;
+    Diffuse.xyz() = theColor.rgb();
+  }
+
+  //! Initialize material
+  void Init (const Graphic3d_MaterialAspect& theProp,
+             const Quantity_Color&           theInteriorColor);
+
+  //! Returns packed (serialized) representation of material properties
+  const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
+  static Standard_Integer NbOfVec4() { return 5; }
+
+  //! Check this material for equality with another material (without tolerance!).
+  bool IsEqual (const OpenGl_Material& theOther) const
+  {
+    return std::memcmp (this, &theOther, sizeof(OpenGl_Material)) == 0;
+  }
+
+  //! Check this material for equality with another material (without tolerance!).
+  bool operator== (const OpenGl_Material& theOther)       { return IsEqual (theOther); }
+  bool operator== (const OpenGl_Material& theOther) const { return IsEqual (theOther); }
+
+  //! Check this material for non-equality with another material (without tolerance!).
+  bool operator!= (const OpenGl_Material& theOther)       { return !IsEqual (theOther); }
+  bool operator!= (const OpenGl_Material& theOther) const { return !IsEqual (theOther); }
+
+};
+
+//! Material flag
+enum OpenGl_MaterialFlag
+{
+  OpenGl_MaterialFlag_Front, //!< material for front faces
+  OpenGl_MaterialFlag_Back   //!< material for back  faces
+};
+
+#endif // _OpenGl_Material_Header
diff --git a/src/OpenGl/OpenGl_MaterialState.hxx b/src/OpenGl/OpenGl_MaterialState.hxx
new file mode 100644 (file)
index 0000000..3781995
--- /dev/null
@@ -0,0 +1,63 @@
+// Created on: 2013-10-02
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _OpenGl_MaterialState_HeaderFile
+#define _OpenGl_MaterialState_HeaderFile
+
+#include <OpenGl_ShaderStates.hxx>
+#include <OpenGl_Material.hxx>
+
+//! Defines generic state of material properties.
+class OpenGl_MaterialState : public OpenGl_StateInterface
+{
+public:
+
+  //! Creates new material state.
+  OpenGl_MaterialState() : myToDistinguish (false), myToMapTexture (false) {}
+
+  //! Sets new material aspect.
+  void Set (const OpenGl_Material& theFrontMat,
+            const OpenGl_Material& theBackMat,
+            const bool theToDistinguish,
+            const bool theToMapTexture)
+  {
+    myMatFront      = theFrontMat;
+    myMatBack       = theBackMat;
+    myToDistinguish = theToDistinguish;
+    myToMapTexture  = theToMapTexture;
+  }
+
+  //! Return front material.
+  const OpenGl_Material& FrontMaterial() const { return myMatFront; }
+
+  //! Return back material.
+  const OpenGl_Material& BackMaterial()  const { return myMatBack; }
+
+  //! Distinguish front/back flag.
+  bool ToDistinguish() const { return myToDistinguish; }
+
+  //! Flag for mapping a texture.
+  bool ToMapTexture()  const { return myToMapTexture; }
+
+private:
+
+  OpenGl_Material myMatFront;      //!< front material
+  OpenGl_Material myMatBack;       //!< back  material
+  bool            myToDistinguish; //!< distinguish front/back flag
+  bool            myToMapTexture;  //!< flag for mapping a texture
+
+};
+
+#endif // _OpenGl_MaterialState_HeaderFile
index 120c80c..ae1b1da 100644 (file)
 #define _OpenGl_NamedStatus_Header
 
 // Dynamic fields
-#define OPENGL_NS_RESMAT       (1<<2)
-#define OPENGL_NS_TEXTURE      (1<<4)
 #define OPENGL_NS_2NDPASSNEED  (1<<6)
 #define OPENGL_NS_2NDPASSDO    (1<<7)
-#define OPENGL_NS_WHITEBACK    (1<<8)
 
 #endif //_OpenGl_NamedStatus_Header
index b19a62c..47c789c 100644 (file)
@@ -360,9 +360,6 @@ void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorksp
                                        const Graphic3d_Vec4*           theFaceColors,
                                        const Standard_Boolean          theHasVertColor) const
 {
-  const Handle(OpenGl_Context)& aGlContext  = theWorkspace->GetGlContext();
-  const bool                    toHilight   = theWorkspace->ToHighlight();
-  bool                          hasVColors  = theHasVertColor && !toHilight;
   if (myVboAttribs.IsNull())
   {
   #if !defined(GL_ES_VERSION_2_0)
@@ -375,6 +372,8 @@ void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorksp
     return;
   }
 
+  const Handle(OpenGl_Context)& aGlContext  = theWorkspace->GetGlContext();
+  const bool                    toHilight   = theWorkspace->ToHighlight();
   myVboAttribs->BindAllAttributes (aGlContext);
   if (theHasVertColor && toHilight)
   {
@@ -429,11 +428,6 @@ void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorksp
 
   // bind with 0
   myVboAttribs->UnbindAllAttributes (aGlContext);
-
-  if (hasVColors)
-  {
-    theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
-  }
 }
 
 // =======================================================================
@@ -721,20 +715,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
   const Standard_Boolean isLightOn = !anAspectFace->IsNoLighting()
                                   && !myVboAttribs.IsNull()
                                   &&  myVboAttribs->HasNormalAttribute();
-#if !defined(GL_ES_VERSION_2_0)
-  // manage FFP lighting
-  if (aCtx->core11 != NULL)
-  {
-    if (!isLightOn)
-    {
-      glDisable (GL_LIGHTING);
-    }
-    else
-    {
-      glEnable (GL_LIGHTING);
-    }
-  }
-#endif
+
   // Temporarily disable environment mapping
   Handle(OpenGl_Texture) aTextureBack;
   bool toDrawArray = true;
@@ -759,60 +740,67 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
   {
     const bool             toHilight    = theWorkspace->ToHighlight();
     const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
-    if (aCtx->core20fwd != NULL)
+    switch (myDrawMode)
     {
-      switch (myDrawMode)
+      case GL_POINTS:
       {
-        case GL_POINTS:
+        const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
+        if (!aSpriteNorm.IsNull()
+         && !aSpriteNorm->IsDisplayList())
         {
-          const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
-          if (!aSpriteNorm.IsNull()
-           && !aSpriteNorm->IsDisplayList())
-          {
-            const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
-                                                      ? anAspectMarker->SpriteHighlightRes (aCtx)
-                                                      : aSpriteNorm;
-            theWorkspace->EnableTexture (aSprite);
-            aCtx->ShaderManager()->BindMarkerProgram (aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
-          }
-          else
-          {
-            aCtx->ShaderManager()->BindMarkerProgram (NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
-          }
-          break;
+          const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
+                                                    ? anAspectMarker->SpriteHighlightRes (aCtx)
+                                                    : aSpriteNorm;
+          theWorkspace->EnableTexture (aSprite);
+          aCtx->ShaderManager()->BindMarkerProgram (aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
         }
-        case GL_LINES:
-        case GL_LINE_STRIP:
+        else
         {
-          aCtx->ShaderManager()->BindLineProgram (NULL,
-                                                  anAspectLine->Aspect()->Type() != Aspect_TOL_SOLID,
-                                                  isLightOn,
-                                                  hasVertColor,
-                                                  anAspectLine->ShaderProgramRes (aCtx));
-          break;
-        }
-        default:
-        {
-          const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
-          const Standard_Boolean isLightOnFace = isLightOn
-                                              && (aTexture.IsNull()
-                                               || aTexture->GetParams()->IsModulate());
-          const Standard_Boolean toEnableEnvMap = (!aTexture.IsNull() && (aTexture == theWorkspace->EnvironmentTexture()));
-          aCtx->ShaderManager()->BindFaceProgram (aTexture,
-                                                  isLightOnFace,
-                                                  hasVertColor,
-                                                  toEnableEnvMap,
-                                                  anAspectFace->ShaderProgramRes (aCtx));
-          break;
+          aCtx->ShaderManager()->BindMarkerProgram (NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
         }
+        break;
+      }
+      case GL_LINES:
+      case GL_LINE_STRIP:
+      {
+        aCtx->ShaderManager()->BindLineProgram (NULL,
+                                                anAspectLine->Aspect()->Type() != Aspect_TOL_SOLID,
+                                                isLightOn,
+                                                hasVertColor,
+                                                anAspectLine->ShaderProgramRes (aCtx));
+        break;
+      }
+      default:
+      {
+        const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
+        const Standard_Boolean isLightOnFace = isLightOn
+                                            && (aTexture.IsNull()
+                                             || aTexture->GetParams()->IsModulate());
+        const Standard_Boolean toEnableEnvMap = (!aTexture.IsNull() && (aTexture == theWorkspace->EnvironmentTexture()));
+        aCtx->ShaderManager()->BindFaceProgram (aTexture,
+                                                isLightOnFace,
+                                                hasVertColor,
+                                                toEnableEnvMap,
+                                                anAspectFace->ShaderProgramRes (aCtx));
+        break;
       }
     }
 
-    // All primitives should gather material properties from the AspectFace in shading mode
-    if (isLightOn)
+  #if !defined(GL_ES_VERSION_2_0)
+    // manage FFP lighting
+    if (aCtx->ActiveProgram().IsNull()
+     && aCtx->core11 != NULL)
     {
-      aCtx->SetShadingMaterial (anAspectFace, theWorkspace->HighlightStyle());
+      if (!isLightOn)
+      {
+        glDisable (GL_LIGHTING);
+      }
+      else
+      {
+        glEnable (GL_LIGHTING);
+      }
     }
+  #endif
 
     if (!theWorkspace->ActiveTexture().IsNull()
      && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
@@ -894,8 +882,6 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
     #endif
     }
   }
-
-  aCtx->BindProgram (NULL);
 }
 
 // =======================================================================
index 26a63ff..991824c 100644 (file)
@@ -249,6 +249,88 @@ const char THE_FRAG_CLIP_PLANES_2[] =
   EOL"    discard;"
   EOL"  }";
 
+#if !defined(GL_ES_VERSION_2_0)
+
+  static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
+  static const GLfloat THE_DEFAULT_SPOT_DIR[3]   = { 0.0f, 0.0f, -1.0f };
+  static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
+  static const GLfloat THE_DEFAULT_SPOT_CUTOFF   = 180.0f;
+
+  //! Bind FFP light source.
+  static void bindLight (const OpenGl_Light& theLight,
+                         const GLenum        theLightGlId,
+                         const OpenGl_Mat4&  theModelView,
+                         OpenGl_Context*     theCtx)
+  {
+    // the light is a headlight?
+    if (theLight.IsHeadlight)
+    {
+      theCtx->core11->glMatrixMode (GL_MODELVIEW);
+      theCtx->core11->glLoadIdentity();
+    }
+
+    // setup light type
+    switch (theLight.Type)
+    {
+      case Graphic3d_TOLS_AMBIENT    : break; // handled by separate if-clause at beginning of method
+      case Graphic3d_TOLS_DIRECTIONAL:
+      {
+        // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
+        const OpenGl_Vec4 anInfDir = -theLight.Direction;
+
+        // to create a realistic effect,  set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
+        theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
+        theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_POSITION,              anInfDir.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
+        break;
+      }
+      case Graphic3d_TOLS_POSITIONAL:
+      {
+        // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
+        const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
+        theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
+        theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_POSITION,              aPosition.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
+        theCtx->core11->glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
+        theCtx->core11->glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
+        theCtx->core11->glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
+        break;
+      }
+      case Graphic3d_TOLS_SPOT:
+      {
+        const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
+        theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
+        theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_POSITION,              aPosition.GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.Direction.GetData());
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_EXPONENT,         theLight.Concentration() * 128.0f);
+        theCtx->core11->glLightf  (theLightGlId, GL_SPOT_CUTOFF,          (theLight.Angle() * 180.0f) / GLfloat(M_PI));
+        theCtx->core11->glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
+        theCtx->core11->glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
+        theCtx->core11->glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
+        break;
+      }
+    }
+
+    // restore matrix in case of headlight
+    if (theLight.IsHeadlight)
+    {
+      theCtx->core11->glLoadMatrixf (theModelView.GetData());
+    }
+
+    glEnable (theLightGlId);
+  }
+#endif
+
 }
 
 // =======================================================================
@@ -256,7 +338,8 @@ const char THE_FRAG_CLIP_PLANES_2[] =
 // purpose  : Creates new empty shader manager
 // =======================================================================
 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
-: myShadingModel (Graphic3d_TOSM_VERTEX),
+: myFfpProgram (new OpenGl_ShaderProgramFFP()),
+  myShadingModel (Graphic3d_TOSM_VERTEX),
   myContext  (theContext),
   myHasLocalOrigin (Standard_False),
   myLastView (NULL)
@@ -481,50 +564,68 @@ void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldVi
 }
 
 // =======================================================================
-// function : LightSourceState
-// purpose  : Returns current state of OCCT light sources
-// =======================================================================
-const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
-{
-  return myLightSourceState;
-}
-
-// =======================================================================
-// function : ProjectionState
-// purpose  : Returns current state of OCCT projection transform
-// =======================================================================
-const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
-{
-  return myProjectionState;
-}
-
-// =======================================================================
-// function : ModelWorldState
-// purpose  : Returns current state of OCCT model-world transform
-// =======================================================================
-const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
-{
-  return myModelWorldState;
-}
-
-// =======================================================================
-// function : WorldViewState
-// purpose  : Returns current state of OCCT world-view transform
-// =======================================================================
-const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
-{
-  return myWorldViewState;
-}
-
-// =======================================================================
 // function : PushLightSourceState
 // purpose  : Pushes state of OCCT light sources to the program
 // =======================================================================
 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
 {
-  if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
-   || !theProgram->IsValid())
+  if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
+  {
+    return;
+  }
+
+  theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
+  if (theProgram == myFfpProgram)
   {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 == NULL)
+    {
+      return;
+    }
+
+    if (myContext->core11 != NULL)
+    {
+      GLenum aLightGlId = GL_LIGHT0;
+      OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
+      const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
+      for (OpenGl_ListOfLight::Iterator aLightIt (*myLightSourceState.LightSources()); aLightIt.More(); aLightIt.Next())
+      {
+        const OpenGl_Light& aLight = aLightIt.Value();
+        if (aLight.Type == Graphic3d_TOLS_AMBIENT)
+        {
+          anAmbient += aLight.Color;
+          continue;
+        }
+        else if (aLightGlId > GL_LIGHT7) // OpenGLMaxLights - only 8 lights in OpenGL...
+        {
+          continue;
+        }
+
+        bindLight (aLightIt.Value(), aLightGlId, aModelView, myContext);
+        ++aLightGlId;
+      }
+
+      // apply accumulated ambient color
+      anAmbient.a() = 1.0f;
+      myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
+
+      // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
+      // therefore managing the state here does not have any effect - do it just for consistency.
+      if (aLightGlId != GL_LIGHT0)
+      {
+        ::glEnable (GL_LIGHTING);
+      }
+      else
+      {
+        ::glDisable (GL_LIGHTING);
+      }
+      // switch off unused lights
+      for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
+      {
+        ::glDisable (aLightGlId);
+      }
+    }
+  #endif
     return;
   }
 
@@ -546,7 +647,6 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
                             OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
                             myLightTypeArray[0].Packed());
-    theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
     return;
   }
 
@@ -615,8 +715,6 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
                             aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
                             myLightParamsArray[0].Packed());
   }
-
-  theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
 }
 
 // =======================================================================
@@ -630,6 +728,19 @@ void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgra
     return;
   }
 
+  theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
+  if (theProgram == myFfpProgram)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 != NULL)
+    {
+      myContext->core11->glMatrixMode (GL_PROJECTION);
+      myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
+    }
+  #endif
+    return;
+  }
+
   theProgram->SetUniform (myContext,
                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
                           myProjectionState.ProjectionMatrix());
@@ -649,8 +760,6 @@ void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgra
   {
     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
   }
-
-  theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
 }
 
 // =======================================================================
@@ -664,6 +773,21 @@ void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgra
     return;
   }
 
+  theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
+  if (theProgram == myFfpProgram)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 != NULL)
+    {
+      const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
+      myContext->core11->glMatrixMode (GL_MODELVIEW);
+      myContext->core11->glLoadMatrixf (aModelView.GetData());
+      theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
+    }
+  #endif
+    return;
+  }
+
   theProgram->SetUniform (myContext,
                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
                           myModelWorldState.ModelWorldMatrix());
@@ -683,8 +807,6 @@ void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgra
   {
     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
   }
-
-  theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
 }
 
 // =======================================================================
@@ -698,6 +820,21 @@ void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram
     return;
   }
 
+  theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
+  if (theProgram == myFfpProgram)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 != NULL)
+    {
+      const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
+      myContext->core11->glMatrixMode (GL_MODELVIEW);
+      myContext->core11->glLoadMatrixf (aModelView.GetData());
+      theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
+    }
+  #endif
+    return;
+  }
+
   theProgram->SetUniform (myContext,
                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
                           myWorldViewState.WorldViewMatrix());
@@ -717,8 +854,6 @@ void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram
   {
     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
   }
-
-  theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
 }
 
 // =======================================================================
@@ -751,6 +886,77 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
   }
 
   theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
+  if (theProgram == myFfpProgram)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 == NULL)
+    {
+      return;
+    }
+
+    const Standard_Integer aNbMaxPlanes = Min (myContext->MaxClipPlanes(), THE_MAX_CLIP_PLANES);
+    OpenGl_Vec4d anEquations[THE_MAX_CLIP_PLANES];
+    Standard_Integer aPlaneId = 0;
+    Standard_Boolean toRestoreModelView = Standard_False;
+    for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
+    {
+      const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
+      if (aPlaneIter.IsDisabled())
+      {
+        continue;
+      }
+      else if (aPlaneId >= aNbMaxPlanes)
+      {
+        myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                                GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
+                                TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
+        break;
+      }
+
+      const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
+      OpenGl_Vec4d& aPlaneEq = anEquations[aPlaneId];
+      aPlaneEq.x() = anEquation.x();
+      aPlaneEq.y() = anEquation.y();
+      aPlaneEq.z() = anEquation.z();
+      aPlaneEq.w() = anEquation.w();
+      if (myHasLocalOrigin)
+      {
+        const gp_XYZ        aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
+        const Standard_Real aD   = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
+        aPlaneEq.w() = aD;
+      }
+
+      const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
+      if (anFfpPlaneID == GL_CLIP_PLANE0)
+      {
+        // set either identity or pure view matrix
+        toRestoreModelView = Standard_True;
+        myContext->core11->glMatrixMode (GL_MODELVIEW);
+        myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
+      }
+
+      ::glEnable (anFfpPlaneID);
+      myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
+
+      ++aPlaneId;
+    }
+
+    // switch off unused lights
+    for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
+    {
+      ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
+    }
+
+    // restore combined model-view matrix
+    if (toRestoreModelView)
+    {
+      const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
+      myContext->core11->glLoadMatrixf (aModelView.GetData());
+    }
+  #endif
+    return;
+  }
+
   const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
   if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
   {
@@ -802,16 +1008,80 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
 }
 
 // =======================================================================
+// function : PushMaterialState
+// purpose  :
+// =======================================================================
+void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
+{
+  if (myMaterialState.Index() == theProgram->ActiveState (OpenGl_MATERIAL_STATE))
+  {
+    return;
+  }
+
+  const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
+  const OpenGl_Material& aBackMat  = myMaterialState.BackMaterial();
+  theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
+  if (theProgram == myFfpProgram)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->core11 == NULL)
+    {
+      return;
+    }
+
+    const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
+    myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT,   aFrontMat.Ambient.GetData());
+    myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE,   aFrontMat.Diffuse.GetData());
+    myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR,  aFrontMat.Specular.GetData());
+    myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION,  aFrontMat.Emission.GetData());
+    myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
+    if (myMaterialState.ToDistinguish())
+    {
+      myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT,   aBackMat.Ambient.GetData());
+      myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE,   aBackMat.Diffuse.GetData());
+      myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR,  aBackMat.Specular.GetData());
+      myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION,  aBackMat.Emission.GetData());
+      myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
+    }
+  #endif
+    return;
+  }
+
+  theProgram->SetUniform (myContext,
+                          theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
+                          myMaterialState.ToMapTexture()  ? 1 : 0);
+  theProgram->SetUniform (myContext,
+                          theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
+                          myMaterialState.ToDistinguish() ? 1 : 0);
+
+  const GLint aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL);
+  if (aLocFront != OpenGl_ShaderProgram::INVALID_LOCATION)
+  {
+    theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
+                            aFrontMat.Packed());
+  }
+
+  const GLint aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL);
+  if (aLocBack != OpenGl_ShaderProgram::INVALID_LOCATION)
+  {
+    theProgram->SetUniform (myContext, aLocBack,  OpenGl_Material::NbOfVec4(),
+                            aBackMat.Packed());
+  }
+}
+
+// =======================================================================
 // function : PushState
 // purpose  : Pushes state of OCCT graphics parameters to the program
 // =======================================================================
 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
 {
-  PushClippingState    (theProgram);
-  PushWorldViewState   (theProgram);
-  PushModelWorldState  (theProgram);
-  PushProjectionState  (theProgram);
-  PushLightSourceState (theProgram);
+  const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
+  PushClippingState    (aProgram);
+  PushWorldViewState   (aProgram);
+  PushModelWorldState  (aProgram);
+  PushProjectionState  (aProgram);
+  PushLightSourceState (aProgram);
+  PushMaterialState    (aProgram);
 }
 
 // =======================================================================
@@ -1776,12 +2046,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
 // =======================================================================
 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
 {
-  if (!myContext->BindProgram (theProgram))
+  const Standard_Boolean isBound = myContext->BindProgram (theProgram);
+  if (isBound
+  && !theProgram.IsNull())
   {
-    return Standard_False;
+    theProgram->ApplyVariables (myContext);
   }
-  theProgram->ApplyVariables (myContext);
-
   PushState (theProgram);
-  return Standard_True;
+  return isBound;
 }
index fb0b9f5..ce503a6 100644 (file)
 #include <OpenGl_AspectLine.hxx>
 #include <OpenGl_AspectText.hxx>
 #include <OpenGl_AspectMarker.hxx>
+#include <OpenGl_MaterialState.hxx>
 #include <OpenGl_Texture.hxx>
 
-
 class OpenGl_View;
 
 //! List of shader programs.
 typedef NCollection_Sequence<Handle(OpenGl_ShaderProgram)> OpenGl_ShaderProgramList;
 
-class OpenGl_ShaderManager;
-DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient)
-
 //! This class is responsible for managing shader programs.
 class OpenGl_ShaderManager : public Standard_Transient
 {
+  DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
   friend class OpenGl_ShaderProgram;
-
 public:
 
   //! Creates new empty shader manager.
@@ -191,7 +188,7 @@ public:
 public:
 
   //! Returns current state of OCCT light sources.
-  Standard_EXPORT const OpenGl_LightSourceState& LightSourceState() const;
+  const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
 
   //! Updates state of OCCT light sources.
   Standard_EXPORT void UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights);
@@ -205,7 +202,7 @@ public:
 public:
 
   //! Returns current state of OCCT projection transform.
-  Standard_EXPORT const OpenGl_ProjectionState& ProjectionState() const;
+  const OpenGl_ProjectionState& ProjectionState() const { return myProjectionState; }
 
   //! Updates state of OCCT projection transform.
   Standard_EXPORT void UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix);
@@ -216,7 +213,7 @@ public:
 public:
 
   //! Returns current state of OCCT model-world transform.
-  Standard_EXPORT const OpenGl_ModelWorldState& ModelWorldState() const;
+  const OpenGl_ModelWorldState& ModelWorldState() const { return myModelWorldState; }
 
   //! Updates state of OCCT model-world transform.
   Standard_EXPORT void UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix);
@@ -227,7 +224,7 @@ public:
 public:
 
   //! Returns current state of OCCT world-view transform.
-  Standard_EXPORT const OpenGl_WorldViewState& WorldViewState() const;
+  const OpenGl_WorldViewState& WorldViewState() const { return myWorldViewState; }
 
   //! Updates state of OCCT world-view transform.
   Standard_EXPORT void UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix);
@@ -248,6 +245,30 @@ public:
 
 public:
 
+  //! Returns current state of material.
+  const OpenGl_MaterialState& MaterialState() const { return myMaterialState; }
+
+  //! Updates state of material.
+  void UpdateMaterialStateTo (const OpenGl_Material& theFrontMat,
+                              const OpenGl_Material& theBackMat,
+                              const bool theToDistinguish,
+                              const bool theToMapTexture)
+  {
+    myMaterialState.Set (theFrontMat, theBackMat, theToDistinguish, theToMapTexture);
+    myMaterialState.Update();
+  }
+
+  //! Updates state of material.
+  void UpdateMaterialState()
+  {
+    myMaterialState.Update();
+  }
+
+  //! Pushes current state of material to specified program.
+  void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
+
+public:
+
   //! Pushes current state of OCCT graphics parameters to specified program.
   Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
 
@@ -418,8 +439,19 @@ protected:
     static Standard_Integer NbOfVec2i() { return 1; }
   };
 
+  //! Fake OpenGL program for tracking FFP state in the way consistent to programmable pipeline.
+  class OpenGl_ShaderProgramFFP : public OpenGl_ShaderProgram
+  {
+    DEFINE_STANDARD_RTTI_INLINE(OpenGl_ShaderProgramFFP, OpenGl_ShaderProgram)
+    friend class OpenGl_ShaderManager;
+  protected:
+    OpenGl_ShaderProgramFFP() {}
+  };
+
 protected:
 
+  Handle(OpenGl_ShaderProgramFFP)    myFfpProgram;
+
   Graphic3d_TypeOfShadingModel       myShadingModel;       //!< lighting shading model
   OpenGl_ShaderProgramList           myProgramList;        //!< The list of shader programs
   Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
@@ -439,6 +471,8 @@ protected:
   OpenGl_WorldViewState              myWorldViewState;     //!< State of OCCT world-view  transformation
   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
+  OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
+
   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
 
@@ -449,9 +483,8 @@ private:
 
   const OpenGl_View*                 myLastView;           //!< Pointer to the last view shader manager used with
 
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
 };
 
+DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient)
+
 #endif // _OpenGl_ShaderManager_HeaderFile
index 126b1e0..d792b16 100755 (executable)
@@ -478,32 +478,6 @@ Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Contex
 }
 
 // =======================================================================
-// 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
 // =======================================================================
index 8cde617..f38506f 100755 (executable)
@@ -122,13 +122,11 @@ enum OpenGl_UniformStateType
   OpenGl_MODEL_WORLD_STATE,
   OpenGl_WORLD_VIEW_STATE,
   OpenGl_PROJECTION_STATE,
-  OpenGl_MATERIALS_STATE,
-  OpenGl_SURF_DETAIL_STATE
+  OpenGl_MATERIAL_STATE,
+  OpenGl_SURF_DETAIL_STATE,
+  OpenGl_UniformStateType_NB
 };
 
-//! Total number of state types.
-const int MaxStateTypes = 6;
-
 //! Wrapper for OpenGL program object.
 class OpenGl_ShaderProgram : public OpenGl_Resource
 {
@@ -210,11 +208,22 @@ public:
 private:
 
   //! Returns index of last modification of variables of specified state type.
-  Standard_EXPORT Standard_Size ActiveState (const OpenGl_UniformStateType theType) const;
+  Standard_Size ActiveState (const OpenGl_UniformStateType theType) const
+  {
+    return theType < OpenGl_UniformStateType_NB
+         ? myCurrentState[theType]
+         : 0;
+  }
 
   //! Updates index of last modification of variables of specified state type.
-  Standard_EXPORT void UpdateState (const OpenGl_UniformStateType theType,
-                                    const Standard_Size           theIndex);
+  void UpdateState (const OpenGl_UniformStateType theType,
+                    const Standard_Size           theIndex)
+  {
+    if (theType < OpenGl_UniformStateType_NB)
+    {
+      myCurrentState[theType] = theIndex;
+    }
+  }
 
 public:
 
@@ -540,7 +549,7 @@ protected:
 
 protected:
 
-  Standard_Size myCurrentState[MaxStateTypes];  //!< defines last modification for variables of each state type
+  Standard_Size myCurrentState[OpenGl_UniformStateType_NB]; //!< defines last modification for variables of each state type
 
   //! Stores locations of OCCT state uniform variables.
   GLint myStateLocations[OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES];
index 0439246..fa75066 100755 (executable)
@@ -15,8 +15,6 @@
 
 #include <OpenGl_ShaderStates.hxx>
 
-#include <NCollection_Mat4.hxx>
-
 // =======================================================================
 // function : OpenGl_StateInterface
 // purpose  :
@@ -191,34 +189,6 @@ const OpenGl_ListOfLight* OpenGl_LightSourceState::LightSources() const
 }
 
 // =======================================================================
-// function : OpenGl_MaterialState
-// purpose  : Creates uninitialized material state
-// =======================================================================
-OpenGl_MaterialState::OpenGl_MaterialState (const OpenGl_Element* theAspect)
-: myAspect (theAspect)
-{
-  //
-}
-
-// =======================================================================
-// function : Set
-// purpose  : Sets new material aspect
-// =======================================================================
-void OpenGl_MaterialState::Set (const OpenGl_Element* theAspect)
-{
-  myAspect = theAspect;
-}
-
-// =======================================================================
-// function : Aspect
-// purpose  : Returns material aspect
-// =======================================================================
-const OpenGl_Element* OpenGl_MaterialState::Aspect() const
-{
-  return myAspect;
-}
-
-// =======================================================================
 // function : OpenGl_ClippingState
 // purpose  : Creates new clipping state
 // =======================================================================
index 7ec45cd..9888412 100755 (executable)
@@ -136,26 +136,6 @@ private:
 
 };
 
-//! Defines generic state of OCCT material properties.
-class OpenGl_MaterialState : public OpenGl_StateInterface
-{
-public:
-
-  //! Creates new material state.
-  OpenGl_MaterialState (const OpenGl_Element* theAspect = NULL);
-
-  //! Sets new material aspect.
-  void Set (const OpenGl_Element* theAspect);
-
-  //! Returns material aspect.
-  const OpenGl_Element* Aspect() const;
-
-private:
-
-  const OpenGl_Element* myAspect; //!< OCCT material aspect
-
-};
-
 //! Defines generic state of OCCT clipping state.
 class OpenGl_ClippingState
 {
index 4c08752..4bd9db9 100644 (file)
@@ -70,6 +70,9 @@ public:
     // Apply line aspect
     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
 
+    theWorkspace->GetGlContext()->BindProgram (Handle(OpenGl_ShaderProgram)());
+    theWorkspace->GetGlContext()->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
+
     glDisable (GL_LIGHTING);
 
     // Use highlight colors
index 0f6b591..5a3a37c 100644 (file)
@@ -429,10 +429,7 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 #endif
 
   // Bind custom shader program or generate default version
-  if (aCtx->core20fwd != NULL)
-  {
-    aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
-  }
+  aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
 
   myOrientationMatrix = theWorkspace->View()->Camera()->OrientationMatrix();
   myProjMatrix.Convert (aCtx->ProjectionState.Current());
@@ -444,8 +441,6 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
           theWorkspace->TextSubtitleColor(),
           theWorkspace->View()->RenderingParams().Resolution);
 
-  aCtx->BindProgram (NULL);
-
   // restore aspects
   if (!aPrevTexture.IsNull())
   {
@@ -569,11 +564,8 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx,
     theCtx->ApplyProjectionMatrix();
   }
 
-  if (!theCtx->ActiveProgram().IsNull())
-  {
-    // Upload updated state to shader program
-    theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
-  }
+  // Upload updated state to shader program
+  theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
 }
 
 // =======================================================================
@@ -728,11 +720,9 @@ void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx,
     myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData());
   }
 
-  if (theCtx->core20fwd != NULL)
-  {
-    // bind flat program
-    theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_Texture)(), Standard_False, Standard_False, Standard_False, Handle(OpenGl_ShaderProgram)());
-  }
+  // bind flat program
+  theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_Texture)(), Standard_False, Standard_False, Standard_False, Handle(OpenGl_ShaderProgram)());
+
 #if !defined(GL_ES_VERSION_2_0)
   if (theCtx->core11 != NULL
    && theCtx->ActiveProgram().IsNull())
index 0934c39..6bb3ca4 100644 (file)
@@ -15,9 +15,9 @@
 #include <OpenGl_VertexBuffer.hxx>
 
 #include <OpenGl_Context.hxx>
+#include <OpenGl_ShaderManager.hxx>
 #include <Standard_Assert.hxx>
 
-
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBuffer,OpenGl_Resource)
 
 // =======================================================================
@@ -235,3 +235,18 @@ bool OpenGl_VertexBuffer::HasNormalAttribute() const
 {
   return false;
 }
+
+#if !defined(GL_ES_VERSION_2_0)
+// =======================================================================
+// function : unbindFixedColor
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::unbindFixedColor (const Handle(OpenGl_Context)& theCtx)
+{
+  theCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
+  theCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
+
+  // invalidate FFP material state after GL_COLOR_MATERIAL has modified it (took values from the vertex color)
+  theCtx->ShaderManager()->UpdateMaterialState();
+}
+#endif
index decacec..c898ecf 100644 (file)
@@ -298,6 +298,10 @@ private:
   //! Disable FFP array pointer.
   static void unbindFixed (const Handle(OpenGl_Context)&   theGlCtx,
                            const Graphic3d_TypeOfAttribute theMode);
+
+  //! Disable FFP color array pointer.
+  static void unbindFixedColor (const Handle(OpenGl_Context)& theCtx);
+
 #endif
 public: //! @name methods for interleaved attributes array
 
index 5545c4a..acd5c73 100644 (file)
@@ -120,12 +120,7 @@ inline void OpenGl_VertexBuffer::unbindFixed (const Handle(OpenGl_Context)&   th
     case Graphic3d_TOA_POS:   theCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);        return;
     case Graphic3d_TOA_NORM:  theCtx->core11->glDisableClientState (GL_NORMAL_ARRAY);        return;
     case Graphic3d_TOA_UV:    theCtx->core11->glDisableClientState (GL_TEXTURE_COORD_ARRAY); return;
-    case Graphic3d_TOA_COLOR:
-    {
-      theCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
-      theCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
-      return;
-    }
+    case Graphic3d_TOA_COLOR: unbindFixedColor (theCtx); return;
     case Graphic3d_TOA_CUSTOM:
     {
       return;
index 2a93c68..7835b4f 100644 (file)
 #include <OpenGl_Structure.hxx>
 #include <OpenGl_ArbFBO.hxx>
 
-#define EPSI 0.0001
-
-namespace
-{
-  static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
-  static const GLfloat THE_DEFAULT_SPOT_DIR[3]   = { 0.0f, 0.0f, -1.0f };
-  static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
-  static const GLfloat THE_DEFAULT_SPOT_CUTOFF   = 180.0f;
-}
-
-extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
-
-#if !defined(GL_ES_VERSION_2_0)
-
-//=======================================================================
-//function : bindLight
-//purpose  :
-//=======================================================================
-static void bindLight (const OpenGl_Light&             theLight,
-                       GLenum&                         theLightGlId,
-                       Graphic3d_Vec4&                 theAmbientColor,
-                       const Handle(OpenGl_Workspace)& theWorkspace)
-{
-  // Only 8 lights in OpenGL...
-  if (theLightGlId > GL_LIGHT7)
-  {
-    return;
-  }
-
-  if (theLight.Type == Graphic3d_TOLS_AMBIENT)
-  {
-    // add RGBA intensity of the ambient light
-    theAmbientColor += theLight.Color;
-    return;
-  }
-
-  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
-
-  // the light is a headlight?
-  if (theLight.IsHeadlight)
-  {
-    aContext->WorldViewState.Push();
-    aContext->WorldViewState.SetIdentity();
-
-    aContext->ApplyWorldViewMatrix();
-  }
-
-  // setup light type
-  switch (theLight.Type)
-  {
-    case Graphic3d_TOLS_AMBIENT    : break; // handled by separate if-clause at beginning of method
-    case Graphic3d_TOLS_DIRECTIONAL:
-    {
-      // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
-      const OpenGl_Vec4 anInfDir = -theLight.Direction;
-
-      // to create a realistic effect,  set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
-      glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
-      glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_POSITION,              anInfDir.GetData());
-      glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
-      glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
-      glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
-      break;
-    }
-    case Graphic3d_TOLS_POSITIONAL:
-    {
-      // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
-      const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
-      glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
-      glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_POSITION,              aPosition.GetData());
-      glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
-      glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
-      glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
-      glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
-      glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
-      glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
-      break;
-    }
-    case Graphic3d_TOLS_SPOT:
-    {
-      const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
-      glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
-      glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
-      glLightfv (theLightGlId, GL_POSITION,              aPosition.GetData());
-      glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.Direction.GetData());
-      glLightf  (theLightGlId, GL_SPOT_EXPONENT,         theLight.Concentration() * 128.0f);
-      glLightf  (theLightGlId, GL_SPOT_CUTOFF,          (theLight.Angle() * 180.0f) / GLfloat(M_PI));
-      glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
-      glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
-      glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
-      break;
-    }
-  }
-
-  // restore matrix in case of headlight
-  if (theLight.IsHeadlight)
-  {
-    aContext->WorldViewState.Pop();
-  }
-
-  glEnable (theLightGlId++);
-}
-#endif
-
 //=======================================================================
 //function : drawBackground
 //purpose  :
@@ -155,9 +46,8 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
 {
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-  if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background
-    || (!myBgTextureArray->IsDefined()                       // no texture
-     && !myBgGradientArray->IsDefined()))                    // no gradient
+  if (!myBgTextureArray->IsDefined()   // no texture
+   && !myBgGradientArray->IsDefined()) // no gradient
   {
     return;
   }
@@ -457,6 +347,10 @@ void OpenGl_View::Redraw()
     Redraw();
   }
 
+  // reset state for safety
+  aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
+  aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
+
   // Swap the buffers
   if (toSwap)
   {
@@ -603,6 +497,10 @@ void OpenGl_View::RedrawImmediate()
   // bind default FBO
   bindDefaultFbo();
 
+  // reset state for safety
+  aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
+  aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
+
   if (toSwap && !aCtx->caps->buffersNoSwap)
   {
     aCtx->SwapBuffers();
@@ -634,7 +532,8 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, Open
   }
 
   // request reset of material
-  myWorkspace->NamedStatus    |= OPENGL_NS_RESMAT;
+  aCtx->ShaderManager()->UpdateMaterialState();
+
   myWorkspace->UseZBuffer()    = Standard_True;
   myWorkspace->UseDepthWrite() = Standard_True;
   GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
@@ -648,16 +547,8 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, Open
   glClearDepthf (1.0f);
 #endif
 
-  if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK)
-  {
-    // set background to white
-    glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
-  }
-  else
-  {
-    const OpenGl_Vec4& aBgColor = myBgColor;
-    glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f);
-  }
+  const OpenGl_Vec4& aBgColor = myBgColor;
+  glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f);
 
   glClear (toClear);
 
@@ -874,12 +765,6 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
   // before drawing auxiliary stuff (trihedrons, overlayer)
   myWorkspace->ResetAppliedAspect();
 
-
-  // We need to disable (unbind) all shaders programs to ensure
-  // that all objects without specified aspect will be drawn
-  // correctly (such as background)
-  aContext->BindProgram (NULL);
-
   // Render trihedron
   if (!theToDrawImmediate)
   {
@@ -898,6 +783,10 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
     }
   }
 
+  // reset FFP state for safety
+  aContext->BindProgram (Handle(OpenGl_ShaderProgram)());
+  aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
+
   // ==============================================================
   //      Step 6: Keep shader manager informed about last View
   // ==============================================================
@@ -1049,39 +938,6 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
     aContext->ShaderManager()->UpdateClippingState();
   }
 
-#if !defined(GL_ES_VERSION_2_0)
-  // Apply Lights
-  if (aContext->core11 != NULL)
-  {
-    // setup lights
-    Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
-                                   THE_DEFAULT_AMBIENT[1],
-                                   THE_DEFAULT_AMBIENT[2],
-                                   THE_DEFAULT_AMBIENT[3]);
-    GLenum aLightGlId = GL_LIGHT0;
-
-    OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? myNoShadingLight : myLights);
-    for (; aLightIt.More(); aLightIt.Next())
-    {
-      bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace);
-    }
-
-    // apply accumulated ambient color
-    anAmbientColor.a() = 1.0f;
-    glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
-
-    if (aLightGlId != GL_LIGHT0)
-    {
-      glEnable (GL_LIGHTING);
-    }
-    // switch off unused lights
-    for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
-    {
-      glDisable (aLightGlId);
-    }
-  }
-#endif
-
   // Clear status bitfields
   myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
 
@@ -1565,9 +1421,11 @@ void OpenGl_View::copyBackToFront()
 
   OpenGl_Mat4 aProjectMat;
   Graphic3d_TransformUtils::Ortho2D (aProjectMat,
-    0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height()));
+                                     0.0f, static_cast<GLfloat> (myWindow->Width()),
+                                     0.0f, static_cast<GLfloat> (myWindow->Height()));
+
+  const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
 
-  Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
   aCtx->WorldViewState.Push();
   aCtx->ProjectionState.Push();
 
@@ -1577,6 +1435,9 @@ void OpenGl_View::copyBackToFront()
   aCtx->ApplyProjectionMatrix();
   aCtx->ApplyWorldViewMatrix();
 
+  // synchronize FFP state before copying pixels
+  aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
+  aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
   aCtx->DisableFeatures();
 
   switch (aCtx->DrawBuffer())
index b195bde..f059750 100644 (file)
@@ -27,6 +27,7 @@
 #include <OpenGl_SceneGeometry.hxx>
 #include <OpenGl_Structure.hxx>
 #include <OpenGl_Sampler.hxx>
+#include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_Texture.hxx>
 #include <OpenGl_View.hxx>
 #include <OpenGl_Window.hxx>
@@ -140,7 +141,6 @@ OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Wi
   myAspectFaceSet (&myDefaultAspectFace),
   myAspectMarkerSet (&myDefaultAspectMarker),
   myAspectTextSet (&myDefaultAspectText),
-  myAspectFaceAppliedWithHL (false),
   //
   ViewMatrix_applied (&myDefaultMatrix),
   StructureMatrix_applied (&myDefaultMatrix),
@@ -193,6 +193,13 @@ Standard_Boolean OpenGl_Workspace::Activate()
 
   ResetAppliedAspect();
 
+  // reset state for safety
+  myGlContext->BindProgram (Handle(OpenGl_ShaderProgram)());
+  if (myGlContext->core20fwd != NULL)
+  {
+    myGlContext->core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
+  }
+  myGlContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
   return Standard_True;
 }
 
@@ -204,7 +211,7 @@ void OpenGl_Workspace::ResetAppliedAspect()
 {
   myGlContext->BindDefaultVao();
 
-  NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
+  NamedStatus           = 0;
   myHighlightStyle.Nullify();
   myToAllowFaceCulling  = false;
   myAspectLineSet       = &myDefaultAspectLine;
@@ -564,163 +571,6 @@ Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Text
 }
 
 // =======================================================================
-// function : updateMaterial
-// purpose  :
-// =======================================================================
-void OpenGl_Workspace::updateMaterial (const int theFlag)
-{
-  // Case of hidden line
-  if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
-  {
-    // copy all values including line edge aspect
-    *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect();
-    myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
-    myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
-    myAspectFaceHl.SetNoLighting (true);
-    myAspectFaceSet = &myAspectFaceHl;
-    return;
-  }
-
-  const Graphic3d_MaterialAspect* aSrcMat      = &myAspectFaceSet->Aspect()->FrontMaterial();
-  const Quantity_Color*           aSrcIntColor = &myAspectFaceSet->Aspect()->InteriorColor();
-  GLenum aFace = GL_FRONT_AND_BACK;
-  if (theFlag == TEL_BACK_MATERIAL)
-  {
-    aFace        = GL_BACK;
-    aSrcMat      = &myAspectFaceSet->Aspect()->BackMaterial();
-    aSrcIntColor = &myAspectFaceSet->Aspect()->BackInteriorColor();
-  }
-  else if (myAspectFaceSet->Aspect()->Distinguish()
-        && !(NamedStatus & OPENGL_NS_RESMAT))
-  {
-    aFace = GL_FRONT;
-  }
-
-  myMatTmp.Init (*aSrcMat, *aSrcIntColor);
-  if (!myHighlightStyle.IsNull())
-  {
-    myMatTmp.SetColor (myHighlightStyle->ColorRGBA());
-  }
-
-  // handling transparency
-  if (NamedStatus & OPENGL_NS_2NDPASSDO)
-  {
-    // second pass
-    myMatTmp.Diffuse.a() = aSrcMat->EnvReflexion();
-  }
-  else
-  {
-    if (aSrcMat->EnvReflexion() != 0.0f)
-    {
-      // if the material reflects the environment scene, the second pass is needed
-      NamedStatus |= OPENGL_NS_2NDPASSNEED;
-    }
-
-    const float aTransp = (float )aSrcMat->Transparency();
-    if (aTransp != 0.0f)
-    {
-      // render transparent
-      myMatTmp.Diffuse.a() = 1.0f - aTransp;
-      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-      glEnable    (GL_BLEND);
-      if (myUseDepthWrite)
-      {
-        glDepthMask (GL_FALSE);
-      }
-    }
-    else
-    {
-      // render opaque
-      glBlendFunc (GL_ONE, GL_ZERO);
-      glDisable   (GL_BLEND);
-      if (myUseDepthWrite)
-      {
-        glDepthMask (GL_TRUE);
-      }
-    }
-  }
-
-  // do not update material properties in case of zero reflection mode,
-  // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
-  if (myAspectFaceSet->IsNoLighting())
-  {
-    return;
-  }
-
-  // reset material
-  if (NamedStatus & OPENGL_NS_RESMAT)
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    if (myGlContext->core11 != NULL)
-    {
-      myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
-      myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
-      myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
-      myGlContext->core11->glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
-      myGlContext->core11->glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
-    }
-  #endif
-
-    if (theFlag == TEL_FRONT_MATERIAL)
-    {
-      myMatFront = myMatTmp;
-      myMatBack  = myMatTmp;
-    }
-    else
-    {
-      myMatBack = myMatTmp;
-    }
-
-    NamedStatus &= ~OPENGL_NS_RESMAT;
-    return;
-  }
-
-  // reduce updates
-  OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
-                         ? myMatFront
-                         : myMatBack;
-#if !defined(GL_ES_VERSION_2_0)
-  if (myGlContext->core11 != NULL)
-  {
-    if (myMatTmp.Ambient.r() != anOld.Ambient.r()
-     || myMatTmp.Ambient.g() != anOld.Ambient.g()
-     || myMatTmp.Ambient.b() != anOld.Ambient.b())
-    {
-      myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
-    }
-    if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
-     || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
-     || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
-     || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
-    {
-      myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
-    }
-    if (myMatTmp.Specular.r() != anOld.Specular.r()
-     || myMatTmp.Specular.g() != anOld.Specular.g()
-     || myMatTmp.Specular.b() != anOld.Specular.b())
-    {
-      myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
-    }
-    if (myMatTmp.Emission.r() != anOld.Emission.r()
-     || myMatTmp.Emission.g() != anOld.Emission.g()
-     || myMatTmp.Emission.b() != anOld.Emission.b())
-    {
-      myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
-    }
-    if (myMatTmp.Shine() != anOld.Shine())
-    {
-      myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
-    }
-  }
-#endif
-  anOld = myMatTmp;
-  if (aFace == GL_FRONT_AND_BACK)
-  {
-    myMatBack = myMatTmp;
-  }
-}
-
-// =======================================================================
 // function : SetAspectLine
 // purpose  :
 // =======================================================================
@@ -796,11 +646,11 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
   }
 
   if (myAspectFaceSet->Aspect() == myAspectFaceApplied
-  && !myHighlightStyle.IsNull() == myAspectFaceAppliedWithHL)
+   && myHighlightStyle == myAspectFaceAppliedWithHL)
   {
     return myAspectFaceSet;
   }
-  myAspectFaceAppliedWithHL = !myHighlightStyle.IsNull();
+  myAspectFaceAppliedWithHL = myHighlightStyle;
 
 #if !defined(GL_ES_VERSION_2_0)
   const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle();
@@ -853,10 +703,19 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
     }
   }
 
-  updateMaterial (TEL_FRONT_MATERIAL);
-  if (myAspectFaceSet->Aspect()->Distinguish())
+  // Case of hidden line
+  if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
+  {
+    // copy all values including line edge aspect
+    *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect();
+    myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
+    myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
+    myAspectFaceHl.SetNoLighting (true);
+    myAspectFaceSet = &myAspectFaceHl;
+  }
+  else
   {
-    updateMaterial (TEL_BACK_MATERIAL);
+    myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle, myUseDepthWrite, NamedStatus);
   }
 
   if (myAspectFaceSet->Aspect()->ToMapTexture())
index 58ef055..0723828 100644 (file)
@@ -21,6 +21,7 @@
 #include <OpenGl_AspectFace.hxx>
 #include <OpenGl_CappingAlgo.hxx>
 #include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_Material.hxx>
 #include <OpenGl_Matrix.hxx>
 #include <OpenGl_NamedStatus.hxx>
 #include <OpenGl_RenderFilter.hxx>
 class OpenGl_View;
 class Image_PixMap;
 
-//! OpenGL material definition
-struct OpenGl_Material
-{
-
-  OpenGl_Vec4 Ambient;  //!< ambient reflection coefficient
-  OpenGl_Vec4 Diffuse;  //!< diffuse reflection coefficient
-  OpenGl_Vec4 Specular; //!< glossy  reflection coefficient
-  OpenGl_Vec4 Emission; //!< material emission
-  OpenGl_Vec4 Params;   //!< extra packed parameters
-
-  Standard_ShortReal  Shine()              const { return Params.x(); }
-  Standard_ShortReal& ChangeShine()              { return Params.x(); }
-
-  Standard_ShortReal  Transparency()       const { return Params.y(); }
-  Standard_ShortReal& ChangeTransparency()       { return Params.y(); }
-
-  //! Set material color.
-  void SetColor (const OpenGl_Vec4& theColor)
-  {
-    // apply the same formula as in Graphic3d_MaterialAspect::SetColor()
-    Ambient.xyz() = theColor.rgb() * 0.25f;
-    Diffuse.xyz() = theColor.rgb();
-  }
-
-  //! Initialize material
-  void Init (const Graphic3d_MaterialAspect& theProp,
-             const Quantity_Color&           theInteriorColor);
-
-  //! Returns packed (serialized) representation of material properties
-  const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
-  static Standard_Integer NbOfVec4() { return 5; }
-
-};
-
 class OpenGl_RaytraceFilter;
 DEFINE_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter)
 
@@ -335,14 +302,6 @@ public:
 
 protected:
 
-  enum
-  {
-    TEL_FRONT_MATERIAL = 1,
-    TEL_BACK_MATERIAL  = 2
-  };
-
-  void updateMaterial (const int theFlag);
-
   void setTextureParams (Handle(OpenGl_Texture)&                theTexture,
                          const Handle(Graphic3d_TextureParams)& theParams);
 
@@ -367,14 +326,11 @@ protected: //! @name fields related to status
   const OpenGl_AspectMarker* myAspectMarkerSet;
   Handle(Graphic3d_AspectMarker3d) myAspectMarkerApplied;
   const OpenGl_AspectText*   myAspectTextSet;
-  bool                       myAspectFaceAppliedWithHL;
+  Handle(Graphic3d_PresentationAttributes) myAspectFaceAppliedWithHL;
 
   const OpenGl_Matrix* ViewMatrix_applied;
   const OpenGl_Matrix* StructureMatrix_applied;
 
-  OpenGl_Material myMatFront;    //!< current front material state (cached to reduce GL context updates)
-  OpenGl_Material myMatBack;     //!< current back  material state
-  OpenGl_Material myMatTmp;      //!< temporary variable
   bool            myToAllowFaceCulling; //!< allow back face culling
   Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //!< active highlight style
 
index ff48003..20fa754 100644 (file)
@@ -30,6 +30,7 @@
 #include <OpenGl_Element.hxx>
 #include <OpenGl_GlCore20.hxx>
 #include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_Workspace.hxx>
 #include <OSD_Environment.hxx>
 #include <OSD_File.hxx>
@@ -156,7 +157,8 @@ void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
 {
   // this sample does not use GLSL programs - make sure it is disabled
   Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
-  aCtx->BindProgram (NULL);
+  aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
+  aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
 
   // To test linking against OpenGl_Workspace and all aspect classes
   const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker();