0032591: Visualization, V3d_View - improve corner gradient
authorachesnok <achesnok@opencascade.com>
Sat, 2 Oct 2021 13:33:48 +0000 (16:33 +0300)
committersmoskvin <smoskvin@opencascade.com>
Fri, 8 Oct 2021 17:22:22 +0000 (20:22 +0300)
- Added new shader for correct Aspect_GradientFillMethod_Corner mode shading.

src/Graphic3d/Graphic3d_ShaderManager.cxx
src/Graphic3d/Graphic3d_ShaderManager.hxx
src/OpenGl/OpenGl_BackgroundArray.cxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx

index b9ee57e..d6dfb37 100644 (file)
@@ -2093,3 +2093,37 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getBgCubeMapProgram() c
   aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
   return aProgSrc;
 }
+
+// =======================================================================
+// function : getColoredQuadProgram
+// purpose  :
+// =======================================================================
+Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getColoredQuadProgram() const
+{
+  Handle(Graphic3d_ShaderProgram) aProgSrc = new Graphic3d_ShaderProgram();
+
+  Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
+  aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
+  aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 uColor1", Graphic3d_TOS_FRAGMENT));
+  aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 uColor2", Graphic3d_TOS_FRAGMENT));
+
+  TCollection_AsciiString aSrcVert = TCollection_AsciiString()
+  + EOL"void main()"
+    EOL"{"
+    EOL"  TexCoord    = occTexCoord.st;"
+    EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
+    EOL"}";
+
+  TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
+  + EOL"void main()"
+    EOL"{"
+    EOL"  vec3 c1 = mix (uColor1, uColor2, TexCoord.x);"
+    EOL"  occSetFragColor (vec4 (mix (uColor2, c1, TexCoord.y), 1.0));"
+    EOL"}";
+
+  defaultGlslVersion (aProgSrc, "colored_quad", 0);
+  aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX,   aUniforms, aStageInOuts));
+  aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
+
+  return aProgSrc;
+}
index 5a4731a..0619ea1 100644 (file)
@@ -142,6 +142,9 @@ protected:
   //! Generates shader program to render environment cubemap as background.
   Standard_EXPORT Handle(Graphic3d_ShaderProgram) getBgCubeMapProgram() const;
 
+  //! Generates shader program to render correctly colored quad.
+  Standard_EXPORT Handle(Graphic3d_ShaderProgram) getColoredQuadProgram() const;
+
   //! Prepare GLSL source for IBL generation used in PBR pipeline.
   Standard_EXPORT Handle(Graphic3d_ShaderProgram) getPBREnvBakingProgram (Standard_Integer theIndex) const;
 
index cceff8f..90dac50 100644 (file)
@@ -209,13 +209,22 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray (const Handle(OpenG
   {
     return Standard_False;
   }
+  if (!myIndices->Init<unsigned short>(6))
+  {
+    return Standard_False;
+  }
+  const unsigned short THE_FS_QUAD_TRIS[6] = {0, 1, 3, 1, 2, 3};
+  for (unsigned int aVertIter = 0; aVertIter < 6; ++aVertIter)
+  {
+    myIndices->SetIndex (aVertIter, THE_FS_QUAD_TRIS[aVertIter]);
+  }
 
   OpenGl_Vec2 aVertices[4] =
   {
     OpenGl_Vec2(float(myViewWidth), 0.0f),
     OpenGl_Vec2(float(myViewWidth), float(myViewHeight)),
-    OpenGl_Vec2(0.0f,               0.0f),
-    OpenGl_Vec2(0.0f,               float(myViewHeight))
+    OpenGl_Vec2(0.0f,               float(myViewHeight)),
+    OpenGl_Vec2(0.0f,               0.0f)
   };
 
   float* aCorners[4]     = {};
@@ -236,73 +245,65 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray (const Handle(OpenG
     {
       aCorners[0] = myGradientParams.color2.ChangeData();
       aCorners[1] = myGradientParams.color1.ChangeData();
-      aCorners[2] = myGradientParams.color2.ChangeData();
-      aCorners[3] = myGradientParams.color1.ChangeData();
+      aCorners[2] = myGradientParams.color1.ChangeData();
+      aCorners[3] = myGradientParams.color2.ChangeData();
       break;
     }
     case Aspect_GradientFillMethod_Diagonal1:
     {
       aCorners[0] = myGradientParams.color2.ChangeData();
-      aCorners[3] = myGradientParams.color1.ChangeData();
-      aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[3][0]);
-      aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[3][1]);
-      aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[3][2]);
+      aCorners[2] = myGradientParams.color1.ChangeData();
+      aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[2][0]);
+      aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[2][1]);
+      aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[2][2]);
       aCorners[1] = aDiagCorner1;
-      aCorners[2] = aDiagCorner2;
+      aCorners[3] = aDiagCorner2;
       break;
     }
     case Aspect_GradientFillMethod_Diagonal2:
     {
       aCorners[1] = myGradientParams.color1.ChangeData();
-      aCorners[2] = myGradientParams.color2.ChangeData();
-      aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[2][0]);
-      aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[2][1]);
-      aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[2][2]);
+      aCorners[3] = myGradientParams.color2.ChangeData();
+      aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[3][0]);
+      aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[3][1]);
+      aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[3][2]);
       aCorners[0] = aDiagCorner1;
-      aCorners[3] = aDiagCorner2;
+      aCorners[2] = aDiagCorner2;
       break;
     }
     case Aspect_GradientFillMethod_Corner1:
-    {
-      aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight));
-      aVertices[1] = OpenGl_Vec2(0.0f,               float(myViewHeight));
-      aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
-      aVertices[3] = OpenGl_Vec2(0.0f,               0.0f);
-
-      aCorners[0] = myGradientParams.color2.ChangeData();
-      aCorners[1] = myGradientParams.color1.ChangeData();
-      aCorners[2] = myGradientParams.color2.ChangeData();
-      aCorners[3] = myGradientParams.color2.ChangeData();
-      break;
-    }
     case Aspect_GradientFillMethod_Corner2:
-    {
-      aCorners[0] = myGradientParams.color2.ChangeData();
-      aCorners[1] = myGradientParams.color1.ChangeData();
-      aCorners[2] = myGradientParams.color2.ChangeData();
-      aCorners[3] = myGradientParams.color2.ChangeData();
-      break;
-    }
     case Aspect_GradientFillMethod_Corner3:
-    {
-      aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight));
-      aVertices[1] = OpenGl_Vec2(0.0f,               float(myViewHeight));
-      aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
-      aVertices[3] = OpenGl_Vec2(0.0f,               0.0f);
-
-      aCorners[0] = myGradientParams.color2.ChangeData();
-      aCorners[1] = myGradientParams.color2.ChangeData();
-      aCorners[2] = myGradientParams.color1.ChangeData();
-      aCorners[3] = myGradientParams.color2.ChangeData();
-      break;
-    }
     case Aspect_GradientFillMethod_Corner4:
     {
-      aCorners[0] = myGradientParams.color2.ChangeData();
-      aCorners[1] = myGradientParams.color2.ChangeData();
-      aCorners[2] = myGradientParams.color1.ChangeData();
-      aCorners[3] = myGradientParams.color2.ChangeData();
-      break;
+      Graphic3d_Attribute aCornerAttribInfo[] =
+      {
+        { Graphic3d_TOA_POS,   Graphic3d_TOD_VEC2 },
+        { Graphic3d_TOA_UV,    Graphic3d_TOD_VEC2 }
+      };
+
+      OpenGl_Vec2 anUVs[4] =
+      {
+        OpenGl_Vec2 (1.0f, 0.0f),
+        OpenGl_Vec2 (1.0f, 1.0f),
+        OpenGl_Vec2 (0.0f, 1.0f),
+        OpenGl_Vec2 (0.0f, 0.0f)
+      };
+
+      if (!myAttribs->Init (4, aCornerAttribInfo, 2))
+      {
+        return Standard_False;
+      }
+      for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
+      {
+        OpenGl_Vec2* aVertData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue (anIt));
+        *aVertData = aVertices[anIt];
+
+        OpenGl_Vec2* anUvData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1));
+        // cyclically move highlighted corner depending on myGradientParams.type
+        *anUvData = anUVs[(anIt + myGradientParams.type - Aspect_GradientFillMethod_Corner1) % 4];
+      }
+      return Standard_True;
     }
     case Aspect_GradientFillMethod_Elliptical:
     {
@@ -365,15 +366,6 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray (const Handle(OpenG
     *aColorData = theCtx->Vec4FromQuantityColor (OpenGl_Vec4(aCorners[anIt][0], aCorners[anIt][1], aCorners[anIt][2], 1.0f)).rgb();
   }
 
-  if (!myIndices->Init<unsigned short>(6))
-  {
-    return Standard_False;
-  }
-  const unsigned short THE_FS_QUAD_TRIS[6] = {0, 1, 2, 1, 3, 2};
-  for (unsigned int aVertIter = 0; aVertIter < 6; ++aVertIter)
-  {
-    myIndices->SetIndex (aVertIter, THE_FS_QUAD_TRIS[aVertIter]);
-  }
   return Standard_True;
 }
 
index 4abc046..04efdf9 100644 (file)
@@ -1397,6 +1397,19 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram
   return myBgCubeMapProgram;
 }
 
+// =======================================================================
+// function : GetColoredQuadProgram
+// purpose  :
+// =======================================================================
+const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetColoredQuadProgram ()
+{
+  if (myColoredQuadProgram.IsNull())
+  {
+    myColoredQuadProgram = getColoredQuadProgram();
+  }
+  return myColoredQuadProgram;
+}
+
 // =======================================================================
 // function : bindProgramWithState
 // purpose  :
index 464323e..44d07b4 100644 (file)
@@ -228,7 +228,10 @@ public:
   }
 
   //! Generates shader program to render environment cubemap as background.
-  Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram ();
+  Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram();
+
+  //! Generates shader program to render correctly colored quad.
+  Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetColoredQuadProgram();
 
   //! Resets PBR shading models to corresponding non-PBR ones if PBR is not allowed.
   static Graphic3d_TypeOfShadingModel PBRShadingModelFallback (Graphic3d_TypeOfShadingModel theShadingModel,
@@ -769,7 +772,8 @@ protected:
   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
 
   Handle(OpenGl_ShaderProgram)       myPBREnvBakingProgram[3]; //!< programs for IBL maps generation used in PBR pipeline (0 for Diffuse; 1 for Specular; 2 for fallback)
-  Handle(Graphic3d_ShaderProgram)    myBgCubeMapProgram;   //!< program for background cubemap rendering
+  Handle(Graphic3d_ShaderProgram)    myBgCubeMapProgram;       //!< program for background cubemap rendering
+  Handle(Graphic3d_ShaderProgram)    myColoredQuadProgram;     //!< program for correct quad rendering
 
   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
 
index 2bca09c..a2d17ad 100644 (file)
@@ -127,10 +127,11 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
   myTransientDrawToFront (Standard_True),
   myBackBufferRestored   (Standard_False),
   myIsImmediateDrawn     (Standard_False),
-  myTextureParams   (new OpenGl_Aspects()),
-  myCubeMapParams   (new OpenGl_Aspects()),
-  myPBREnvState     (OpenGl_PBREnvState_NONEXISTENT),
-  myPBREnvRequest   (Standard_False),
+  myTextureParams     (new OpenGl_Aspects()),
+  myCubeMapParams     (new OpenGl_Aspects()),
+  myColoredQuadParams (new OpenGl_Aspects()),
+  myPBREnvState       (OpenGl_PBREnvState_NONEXISTENT),
+  myPBREnvRequest     (Standard_False),
   // ray-tracing fields initialization
   myRaytraceInitStatus     (OpenGl_RT_NONE),
   myIsRaytraceDataValid    (Standard_False),
@@ -192,6 +193,7 @@ OpenGl_View::~OpenGl_View()
 
   OpenGl_Element::Destroy (NULL, myTextureParams);
   OpenGl_Element::Destroy (NULL, myCubeMapParams);
+  OpenGl_Element::Destroy (NULL, myColoredQuadParams);
 }
 
 // =======================================================================
@@ -541,7 +543,16 @@ void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBac
   Quantity_Color aColor1, aColor2;
   theBackground.Colors (aColor1, aColor2);
   myBackgrounds[Graphic3d_TOB_GRADIENT]->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
-
+  if (theBackground.BgGradientFillMethod() >= Aspect_GradientFillMethod_Corner1
+   && theBackground.BgGradientFillMethod() <= Aspect_GradientFillMethod_Corner4)
+  {
+    if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext())
+    {
+      myColoredQuadParams->Aspect()->SetShaderProgram(aCtx->ShaderManager()->GetColoredQuadProgram());
+      myColoredQuadParams->Aspect()->ShaderProgram()->PushVariableVec3 ("uColor1", aColor1.Rgb());
+      myColoredQuadParams->Aspect()->ShaderProgram()->PushVariableVec3 ("uColor2", aColor2.Rgb());
+    }
+  }
   myBackgroundType = Graphic3d_TOB_GRADIENT;
 }
 
@@ -1007,7 +1018,19 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace,
         || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_CENTERED
         || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_NONE))
     {
-      myBackgrounds[Graphic3d_TOB_GRADIENT]->Render(theWorkspace, theProjection);
+      if (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod() >= Aspect_GradientFillMethod_Corner1
+       && myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod() <= Aspect_GradientFillMethod_Corner4)
+      {
+        const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myColoredQuadParams);
+
+        myBackgrounds[Graphic3d_TOB_GRADIENT]->Render (theWorkspace, theProjection);
+
+        theWorkspace->SetAspects (anOldAspectFace);
+      }
+      else
+      {
+        myBackgrounds[Graphic3d_TOB_GRADIENT]->Render (theWorkspace, theProjection);
+      }
     }
 
     // Drawing background image if it is defined
index eec11de..e64fdc0 100644 (file)
@@ -507,6 +507,7 @@ protected: //! @name Background parameters
 
   OpenGl_Aspects*            myTextureParams;                     //!< Stores texture and its parameters for textured background
   OpenGl_Aspects*            myCubeMapParams;                     //!< Stores cubemap and its parameters for cubemap background
+  OpenGl_Aspects*            myColoredQuadParams;                 //!< Stores parameters for gradient (corner mode) background
   OpenGl_BackgroundArray*    myBackgrounds[Graphic3d_TypeOfBackground_NB]; //!< Array of primitive arrays of different background types
   Handle(OpenGl_TextureSet)  myTextureEnv;