0028306: Visualization - viewer crashes if style for shaded display is set to HATCH
[occt.git] / src / OpenGl / OpenGl_Context.cxx
index cd27177..43ae9fa 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,52 +2847,100 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O
 // purpose  :
 // =======================================================================
 void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
-                                         const OpenGl_Vec4* theHighlightColor)
+                                         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
   {
-    myActiveProgram->SetUniform (this,
-                                 myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
-                                 theAspect->Aspect()->ToMapTexture() ? 1 : 0);
-    myActiveProgram->SetUniform (this,
-                                 myActiveProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
-                                 theAspect->Aspect()->Distinguish() ? 1 : 0);
+    myMatBack = myMatFront;
+  }
 
-    OpenGl_Material aParams;
-    for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
+  // 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)
     {
-      const GLint aLoc = myActiveProgram->GetStateLocation (anIndex == 0
-                                                          ? OpenGl_OCCT_FRONT_MATERIAL
-                                                          : OpenGl_OCCT_BACK_MATERIAL);
-      if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
-      {
-        continue;
-      }
-
-      if (anIndex == 0 || !theAspect->Aspect()->Distinguish())
-      {
-        const Graphic3d_MaterialAspect& aSrcMat      = theAspect->Aspect()->FrontMaterial();
-        const Quantity_Color&           aSrcIntColor = theAspect->Aspect()->InteriorColor();
-        aParams.Init (aSrcMat, aSrcIntColor);
-        aParams.Diffuse.a() = 1.0f - (float )aSrcMat.Transparency();
-      }
-      else
-      {
-        const Graphic3d_MaterialAspect& aSrcMat      = theAspect->Aspect()->BackMaterial();
-        const Quantity_Color&           aSrcIntColor = theAspect->Aspect()->BackInteriorColor();
-        aParams.Init (aSrcMat, aSrcIntColor);
-        aParams.Diffuse.a() = 1.0f - (float )aSrcMat.Transparency();
-      }
-      if (theHighlightColor != NULL)
-      {
-        aParams.SetColor (*theHighlightColor);
-        aParams.Diffuse.a() = theHighlightColor->a();
-      }
+      // 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);
 }
 
 // =======================================================================
@@ -3179,6 +3231,11 @@ bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
 // =======================================================================
 Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle)
 {
+  if (theStyle.IsNull())
+  {
+    return 0;
+  }
+
   if (myHatchStyles.IsNull())
   {
     if (!GetResource ("OpenGl_LineAttributes", myHatchStyles))
@@ -3202,15 +3259,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());
   }
@@ -3222,17 +3271,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());
   }
 }
@@ -3243,19 +3287,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());
   }
 }
 
@@ -3265,21 +3303,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  :