0028912: Visualization, TKOpenGl - multi-texture support
authorkgv <kgv@opencascade.com>
Mon, 10 Jul 2017 12:43:25 +0000 (15:43 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 21 Jul 2017 09:10:41 +0000 (12:10 +0300)
Graphic3d_AspectFillArea3d now stores array of textures.
Graphic3d_TextureParams stores texture unit for mapping texture.

OpenGl_Context::BindTextures() - context now manages the set of active textures.
Related code has been removed from OpenGl_Workspace.

OpenGl_Sampler has been extended to hold texture parameters structure.
OpenGl_Texture now holds OpenGl_Sampler instance as class field.
OpenGl_Texture inherits new class OpenGl_NamedResource and holds
texture identifier used for sharing resource in OpenGl_Context.

OpenGl_RaytraceGeometry now creates bindless textures taking
Sampler object directly from OpenGl_Texture.
OpenGl_Context::BindTextures() automatically recreates immutable
Sampler Object on texture parameters change.

Declared new structure OpenGl_ArbSamplerObject for platform-neutral
usage of related functionality.
Related functions are now loaded within OpenGL ES 3.0+.

Declarations.glsl - occActiveSampler has been renamed to occSampler0
with aliases occSamplerBaseColor (main) and occActiveSampler (for compatibility).
Additional texture samplers should be declared explicitly
within specific GLSL program as occSampler1, occSampler2, etc.

AIS_Shape and AIS_ColoredShape now computes Shaded presentation
with UV coordinates if texture mapping is enabled in Drawer.

vshaderprog now accepts Shader source code as parameter.

59 files changed:
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_AspectFillArea3d.cxx
src/Graphic3d/Graphic3d_AspectFillArea3d.hxx
src/Graphic3d/Graphic3d_ClipPlane.cxx
src/Graphic3d/Graphic3d_ClipPlane.hxx
src/Graphic3d/Graphic3d_TextureParams.cxx
src/Graphic3d/Graphic3d_TextureParams.hxx
src/Graphic3d/Graphic3d_TextureRoot.hxx
src/Graphic3d/Graphic3d_TextureSet.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_TextureSet.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_TextureUnit.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_TypeOfLimit.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_ArbSamplerObject.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_AspectFace.cxx
src/OpenGl/OpenGl_AspectFace.hxx
src/OpenGl/OpenGl_AspectMarker.cxx
src/OpenGl/OpenGl_AspectMarker.hxx
src/OpenGl/OpenGl_BackgroundArray.cxx
src/OpenGl/OpenGl_CappingPlaneResource.cxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_Font.cxx
src/OpenGl/OpenGl_GlFunctions.hxx
src/OpenGl/OpenGl_GraphicDriver.cxx
src/OpenGl/OpenGl_Layer.cxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_NamedResource.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_PointSprite.cxx
src/OpenGl/OpenGl_PointSprite.hxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_Resource.cxx
src/OpenGl/OpenGl_Sampler.cxx
src/OpenGl/OpenGl_Sampler.hxx
src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_Texture.cxx
src/OpenGl/OpenGl_Texture.hxx
src/OpenGl/OpenGl_TextureBufferArb.cxx
src/OpenGl/OpenGl_TextureBufferArb.hxx
src/OpenGl/OpenGl_TextureSet.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_TextureSet.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/Shaders/Declarations.glsl
src/Shaders/Shaders_Declarations_glsl.pxx
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx
tests/v3d/glsl/texture_multi1 [new file with mode: 0644]

index a8570d8..334dcdf 100755 (executable)
@@ -130,6 +130,9 @@ Graphic3d_TextureParams.cxx
 Graphic3d_TextureParams.hxx
 Graphic3d_TextureRoot.cxx
 Graphic3d_TextureRoot.hxx
+Graphic3d_TextureUnit.hxx
+Graphic3d_TextureSet.cxx
+Graphic3d_TextureSet.hxx
 Graphic3d_ToneMappingMethod.hxx
 Graphic3d_TransformError.hxx
 Graphic3d_TransformPers.hxx
index d8c395c..2e65f35 100644 (file)
@@ -67,3 +67,18 @@ Graphic3d_AspectFillArea3d::Graphic3d_AspectFillArea3d (const Aspect_InteriorSty
     throw Aspect_AspectFillAreaDefinitionError("Bad value for EdgeLineWidth");
   }
 }
+
+// =======================================================================
+// function : Graphic3d_AspectFillArea3d
+// purpose  :
+// =======================================================================
+void Graphic3d_AspectFillArea3d::SetTextureMap (const Handle(Graphic3d_TextureMap)& theTexture)
+{
+  if (theTexture.IsNull())
+  {
+    myTextureSet.Nullify();
+    return;
+  }
+
+  myTextureSet = new Graphic3d_TextureSet (theTexture);
+}
index 44c8f00..1cd298d 100644 (file)
@@ -26,6 +26,7 @@
 #include <Graphic3d_PolygonOffset.hxx>
 #include <Graphic3d_ShaderProgram.hxx>
 #include <Graphic3d_TextureMap.hxx>
+#include <Graphic3d_TextureSet.hxx>
 #include <Standard.hxx>
 #include <Standard_Boolean.hxx>
 #include <Standard_Integer.hxx>
@@ -153,12 +154,25 @@ public:
   //! Sets up OpenGL/GLSL shader program.
   void SetShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProgram) { myProgram = theProgram; }
 
+  //! Return texture array to be mapped.
+  const Handle(Graphic3d_TextureSet)& TextureSet() const { return myTextureSet; }
+
+  //! Setup texture array to be mapped.
+  void SetTextureSet (const Handle(Graphic3d_TextureSet)& theTextures) { myTextureSet = theTextures; }
+
   //! Return texture to be mapped.
-  const Handle(Graphic3d_TextureMap)& TextureMap() const { return myTextureMap; }
+  //Standard_DEPRECATED("Deprecated method, TextureSet() should be used instead")
+  Handle(Graphic3d_TextureMap) TextureMap() const
+  {
+    return !myTextureSet.IsNull() && !myTextureSet->IsEmpty()
+          ? myTextureSet->First()
+          : Handle(Graphic3d_TextureMap)();
+  }
 
   //! Assign texture to be mapped.
-  //! See also SetTextureMap() to actually activate texture mapping.
-  void SetTextureMap (const Handle(Graphic3d_TextureMap)& theTexture) { myTextureMap = theTexture; }
+  //! See also SetTextureMapOn() to actually activate texture mapping.
+  //Standard_DEPRECATED("Deprecated method, SetTextureSet() should be used instead")
+  Standard_EXPORT void SetTextureMap (const Handle(Graphic3d_TextureMap)& theTexture);
 
   //! Return true if texture mapping is enabled (false by default).
   bool ToMapTexture() const { return myToMapTexture; }
@@ -166,6 +180,9 @@ public:
   //! Return true if texture mapping is enabled (false by default).
   bool TextureMapState() const { return myToMapTexture; }
 
+  //! Enable or disable texture mapping (has no effect if texture is not set).
+  void SetTextureMapOn (bool theToMap) { myToMapTexture = theToMap; }
+
   //! Enable texture mapping (has no effect if texture is not set).
   void SetTextureMapOn() { myToMapTexture = true; }
 
@@ -312,7 +329,7 @@ public:
 protected:
 
   Handle(Graphic3d_ShaderProgram) myProgram;
-  Handle(Graphic3d_TextureMap)    myTextureMap;
+  Handle(Graphic3d_TextureSet)    myTextureSet;
   Graphic3d_MaterialAspect        myFrontMaterial;
   Graphic3d_MaterialAspect        myBackMaterial;
 
index 6c6d7e7..1524c94 100755 (executable)
@@ -178,14 +178,24 @@ void Graphic3d_ClipPlane::SetCappingMaterial (const Graphic3d_MaterialAspect& th
 // =======================================================================
 void Graphic3d_ClipPlane::SetCappingTexture (const Handle(Graphic3d_TextureMap)& theTexture)
 {
-  myAspect->SetTextureMap (theTexture);
   if (!theTexture.IsNull())
   {
     myAspect->SetTextureMapOn();
+    Handle(Graphic3d_TextureSet) aTextureSet = myAspect->TextureSet();
+    if (aTextureSet.IsNull() || aTextureSet->Size() != 1)
+    {
+      aTextureSet = new Graphic3d_TextureSet (theTexture);
+    }
+    else
+    {
+      aTextureSet->SetFirst (theTexture);
+    }
+    myAspect->SetTextureSet (aTextureSet);
   }
   else
   {
     myAspect->SetTextureMapOff();
+    myAspect->SetTextureSet (Handle(Graphic3d_TextureSet)());
   }
   ++myAspectMod;
 }
index 08f33ae..11058e3 100755 (executable)
@@ -137,7 +137,9 @@ public: // @name user-defined graphical attributes
   Standard_EXPORT void SetCappingTexture (const Handle(Graphic3d_TextureMap)& theTexture);
 
   //! @return capping texture map.
-  const Handle(Graphic3d_TextureMap)& CappingTexture() const { return myAspect->TextureMap(); }
+  Handle(Graphic3d_TextureMap) CappingTexture() const { return !myAspect->TextureSet().IsNull() && !myAspect->TextureSet()->IsEmpty()
+                                                              ? myAspect->TextureSet()->First()
+                                                              : Handle(Graphic3d_TextureMap)(); }
 
   //! Set hatch style (stipple) and turn hatching on.
   //! @param theStyle [in] the hatch style.
index 178f39b..1eacf67 100644 (file)
@@ -11,9 +11,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-
 #include <Graphic3d_TextureParams.hxx>
-#include <Standard_Type.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_TextureParams,Standard_Transient)
 
@@ -22,39 +20,32 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_TextureParams,Standard_Transient)
 // purpose  :
 // =======================================================================
 Graphic3d_TextureParams::Graphic3d_TextureParams()
-: myToModulate (Standard_False),
-  myToRepeat   (Standard_False),
-  myFilter     (Graphic3d_TOTF_NEAREST),
-  myAnisoLevel (Graphic3d_LOTA_OFF),
-  myRotAngle   (0.0f),
+: myGenPlaneS  (0.0f, 0.0f, 0.0f, 0.0f),
+  myGenPlaneT  (0.0f, 0.0f, 0.0f, 0.0f),
   myScale      (1.0f, 1.0f),
   myTranslation(0.0f, 0.0f),
+  mySamplerRevision (0),
+  myTextureUnit(Graphic3d_TextureUnit_BaseColor),
+  myFilter     (Graphic3d_TOTF_NEAREST),
+  myAnisoLevel (Graphic3d_LOTA_OFF),
   myGenMode    (Graphic3d_TOTM_MANUAL),
-  myGenPlaneS  (0.0f, 0.0f, 0.0f, 0.0f),
-  myGenPlaneT  (0.0f, 0.0f, 0.0f, 0.0f)
+  myRotAngle   (0.0f),
+  myToModulate (Standard_False),
+  myToRepeat   (Standard_False)
 {
   //
 }
 
 // =======================================================================
-// function : Destroy
+// function : ~Graphic3d_TextureParams
 // purpose  :
 // =======================================================================
-void Graphic3d_TextureParams::Destroy() const
+Graphic3d_TextureParams::~Graphic3d_TextureParams()
 {
   //
 }
 
 // =======================================================================
-// function : IsModulate
-// purpose  :
-// =======================================================================
-Standard_Boolean Graphic3d_TextureParams::IsModulate() const
-{
-  return myToModulate;
-}
-
-// =======================================================================
 // function : SetModulate
 // purpose  :
 // =======================================================================
@@ -64,30 +55,16 @@ void Graphic3d_TextureParams::SetModulate (const Standard_Boolean theToModulate)
 }
 
 // =======================================================================
-// function : IsRepeat
-// purpose  :
-// =======================================================================
-Standard_Boolean Graphic3d_TextureParams::IsRepeat() const
-{
-  return myToRepeat;
-}
-
-// =======================================================================
 // function : SetRepeat
 // purpose  :
 // =======================================================================
 void Graphic3d_TextureParams::SetRepeat (const Standard_Boolean theToRepeat)
 {
-  myToRepeat = theToRepeat;
-}
-
-// =======================================================================
-// function : Filter
-// purpose  :
-// =======================================================================
-Graphic3d_TypeOfTextureFilter Graphic3d_TextureParams::Filter() const
-{
-  return myFilter;
+  if (myToRepeat != theToRepeat)
+  {
+    myToRepeat = theToRepeat;
+    updateSamplerRevision();
+  }
 }
 
 // =======================================================================
@@ -96,16 +73,11 @@ Graphic3d_TypeOfTextureFilter Graphic3d_TextureParams::Filter() const
 // =======================================================================
 void Graphic3d_TextureParams::SetFilter (const Graphic3d_TypeOfTextureFilter theFilter)
 {
-  myFilter = theFilter;
-}
-
-// =======================================================================
-// function : AnisoFilter
-// purpose  :
-// =======================================================================
-Graphic3d_LevelOfTextureAnisotropy Graphic3d_TextureParams::AnisoFilter() const
-{
-  return myAnisoLevel;
+  if (myFilter != theFilter)
+  {
+    myFilter = theFilter;
+    updateSamplerRevision();
+  }
 }
 
 // =======================================================================
@@ -114,16 +86,11 @@ Graphic3d_LevelOfTextureAnisotropy Graphic3d_TextureParams::AnisoFilter() const
 // =======================================================================
 void Graphic3d_TextureParams::SetAnisoFilter (const Graphic3d_LevelOfTextureAnisotropy theLevel)
 {
-  myAnisoLevel = theLevel;
-}
-
-// =======================================================================
-// function : Rotation
-// purpose  :
-// =======================================================================
-Standard_ShortReal Graphic3d_TextureParams::Rotation() const
-{
-  return myRotAngle;
+  if (myAnisoLevel != theLevel)
+  {
+    myAnisoLevel = theLevel;
+    updateSamplerRevision();
+  }
 }
 
 // =======================================================================
@@ -136,15 +103,6 @@ void Graphic3d_TextureParams::SetRotation (const Standard_ShortReal theAngleDegr
 }
 
 // =======================================================================
-// function : Scale
-// purpose  :
-// =======================================================================
-const Graphic3d_Vec2& Graphic3d_TextureParams::Scale() const
-{
-  return myScale;
-}
-
-// =======================================================================
 // function : SetScale
 // purpose  :
 // =======================================================================
@@ -154,15 +112,6 @@ void Graphic3d_TextureParams::SetScale (const Graphic3d_Vec2 theScale)
 }
 
 // =======================================================================
-// function : Translation
-// purpose  :
-// =======================================================================
-const Graphic3d_Vec2& Graphic3d_TextureParams::Translation() const
-{
-  return myTranslation;
-}
-
-// =======================================================================
 // function : SetTranslation
 // purpose  :
 // =======================================================================
@@ -172,33 +121,6 @@ void Graphic3d_TextureParams::SetTranslation (const Graphic3d_Vec2 theVec)
 }
 
 // =======================================================================
-// function : GenMode
-// purpose  :
-// =======================================================================
-Graphic3d_TypeOfTextureMode Graphic3d_TextureParams::GenMode() const
-{
-  return myGenMode;
-}
-
-// =======================================================================
-// function : GenPlaneS
-// purpose  :
-// =======================================================================
-const Graphic3d_Vec4& Graphic3d_TextureParams::GenPlaneS() const
-{
-  return myGenPlaneS;
-}
-
-// =======================================================================
-// function : GenPlaneT
-// purpose  :
-// =======================================================================
-const Graphic3d_Vec4& Graphic3d_TextureParams::GenPlaneT() const
-{
-  return myGenPlaneT;
-}
-
-// =======================================================================
 // function : SetGenMode
 // purpose  :
 // =======================================================================
index 2215f13..06fd0f1 100644 (file)
 #ifndef _Graphic3d_TextureParams_HeaderFile
 #define _Graphic3d_TextureParams_HeaderFile
 
-#include <Standard.hxx>
-#include <Standard_Type.hxx>
-
-#include <Standard_Boolean.hxx>
-#include <Graphic3d_TypeOfTextureFilter.hxx>
 #include <Graphic3d_LevelOfTextureAnisotropy.hxx>
-#include <Standard_ShortReal.hxx>
 #include <Graphic3d_Vec2.hxx>
-#include <Graphic3d_TypeOfTextureMode.hxx>
 #include <Graphic3d_Vec4.hxx>
+#include <Graphic3d_TextureUnit.hxx>
+#include <Graphic3d_TypeOfTextureFilter.hxx>
+#include <Graphic3d_TypeOfTextureMode.hxx>
+#include <Standard.hxx>
+#include <Standard_Boolean.hxx>
+#include <Standard_ShortReal.hxx>
+#include <Standard_Type.hxx>
 #include <Standard_Transient.hxx>
 
-
-class Graphic3d_TextureParams;
-DEFINE_STANDARD_HANDLE(Graphic3d_TextureParams, Standard_Transient)
-
 //! This class describes texture parameters.
 class Graphic3d_TextureParams : public Standard_Transient
 {
-
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_TextureParams, Standard_Transient)
 public:
 
-  
   //! Default constructor.
   Standard_EXPORT Graphic3d_TextureParams();
-  
-  Standard_EXPORT void Destroy() const;
-~Graphic3d_TextureParams()
-{
-  Destroy();
-}
-  
+
+  //! Destructor.
+  Standard_EXPORT virtual ~Graphic3d_TextureParams();
+
+  //! Default texture unit to be used, default is Graphic3d_TextureUnit_BaseColor.
+  Graphic3d_TextureUnit TextureUnit() const { return myTextureUnit; }
+
+  //! Setup default texture unit.
+  void SetTextureUnit (Graphic3d_TextureUnit theUnit) { myTextureUnit = theUnit; }
+
   //! @return TRUE if the texture is modulate.
   //! Default value is FALSE.
-  Standard_EXPORT Standard_Boolean IsModulate() const;
+  Standard_Boolean IsModulate() const { return myToModulate; }
   
   //! @param theToModulate turn modulation on/off.
   Standard_EXPORT void SetModulate (const Standard_Boolean theToModulate);
   
   //! @return TRUE if the texture repeat is enabled.
   //! Default value is FALSE.
-  Standard_EXPORT Standard_Boolean IsRepeat() const;
+  Standard_Boolean IsRepeat() const { return myToRepeat; }
   
   //! @param theToRepeat turn texture repeat mode ON or OFF (clamping).
   Standard_EXPORT void SetRepeat (const Standard_Boolean theToRepeat);
   
   //! @return texture interpolation filter.
   //! Default value is Graphic3d_TOTF_NEAREST.
-  Standard_EXPORT Graphic3d_TypeOfTextureFilter Filter() const;
+  Graphic3d_TypeOfTextureFilter Filter() const { return myFilter; }
   
   //! @param theFilter texture interpolation filter.
   Standard_EXPORT void SetFilter (const Graphic3d_TypeOfTextureFilter theFilter);
   
   //! @return level of anisontropy texture filter.
   //! Default value is Graphic3d_LOTA_OFF.
-  Standard_EXPORT Graphic3d_LevelOfTextureAnisotropy AnisoFilter() const;
+  Graphic3d_LevelOfTextureAnisotropy AnisoFilter() const { return myAnisoLevel; }
   
   //! @param theLevel level of anisontropy texture filter.
   Standard_EXPORT void SetAnisoFilter (const Graphic3d_LevelOfTextureAnisotropy theLevel);
   
   //! @return rotation angle in degrees
   //! Default value is 0.
-  Standard_EXPORT Standard_ShortReal Rotation() const;
+  Standard_ShortReal Rotation() const { return myRotAngle; }
   
   //! @param theAngleDegrees rotation angle.
   Standard_EXPORT void SetRotation (const Standard_ShortReal theAngleDegrees);
   
   //! @return scale factor
   //! Default value is no scaling (1.0; 1.0).
-  Standard_EXPORT const Graphic3d_Vec2& Scale() const;
+  const Graphic3d_Vec2& Scale() const { return myScale; }
   
   //! @param theScale scale factor.
   Standard_EXPORT void SetScale (const Graphic3d_Vec2 theScale);
   
   //! @return translation vector
   //! Default value is no translation (0.0; 0.0).
-  Standard_EXPORT const Graphic3d_Vec2& Translation() const;
+  const Graphic3d_Vec2& Translation() const { return myTranslation; }
   
   //! @param theVec translation vector.
   Standard_EXPORT void SetTranslation (const Graphic3d_Vec2 theVec);
   
   //! @return texture coordinates generation mode.
   //! Default value is Graphic3d_TOTM_MANUAL.
-  Standard_EXPORT Graphic3d_TypeOfTextureMode GenMode() const;
+  Graphic3d_TypeOfTextureMode GenMode() const { return myGenMode; }
   
   //! @return texture coordinates generation plane S.
-  Standard_EXPORT const Graphic3d_Vec4& GenPlaneS() const;
+  const Graphic3d_Vec4& GenPlaneS() const { return myGenPlaneS; }
   
   //! @return texture coordinates generation plane T.
-  Standard_EXPORT const Graphic3d_Vec4& GenPlaneT() const;
+  const Graphic3d_Vec4& GenPlaneT() const { return myGenPlaneT; }
   
   //! Setup texture coordinates generation mode.
   Standard_EXPORT void SetGenMode (const Graphic3d_TypeOfTextureMode theMode, const Graphic3d_Vec4 thePlaneS, const Graphic3d_Vec4 thePlaneT);
 
-
-
-  DEFINE_STANDARD_RTTIEXT(Graphic3d_TextureParams,Standard_Transient)
-
-protected:
-
-
-
+  //! Return modification counter of parameters related to sampler state.
+  unsigned int SamplerRevision() const { return mySamplerRevision; }
 
 private:
 
+  //! Increment revision.
+  void updateSamplerRevision() { ++mySamplerRevision; }
 
-  Standard_Boolean myToModulate;
-  Standard_Boolean myToRepeat;
-  Graphic3d_TypeOfTextureFilter myFilter;
-  Graphic3d_LevelOfTextureAnisotropy myAnisoLevel;
-  Standard_ShortReal myRotAngle;
-  Graphic3d_Vec2 myScale;
-  Graphic3d_Vec2 myTranslation;
-  Graphic3d_TypeOfTextureMode myGenMode;
-  Graphic3d_Vec4 myGenPlaneS;
-  Graphic3d_Vec4 myGenPlaneT;
+private:
 
+  Graphic3d_Vec4                     myGenPlaneS;       //!< texture coordinates generation plane S
+  Graphic3d_Vec4                     myGenPlaneT;       //!< texture coordinates generation plane T
+  Graphic3d_Vec2                     myScale;           //!< texture coordinates scale factor vector; (1,1) by default
+  Graphic3d_Vec2                     myTranslation;     //!< texture coordinates translation vector;  (0,0) by default
+  unsigned int                       mySamplerRevision; //!< modification counter of parameters related to sampler state
+  Graphic3d_TextureUnit              myTextureUnit;     //!< default texture unit to bind texture; Graphic3d_TextureUnit_BaseColor by default
+  Graphic3d_TypeOfTextureFilter      myFilter;          //!< texture filter, Graphic3d_TOTF_NEAREST by default
+  Graphic3d_LevelOfTextureAnisotropy myAnisoLevel;      //!< level of anisotropy filter, Graphic3d_LOTA_OFF by default
+  Graphic3d_TypeOfTextureMode        myGenMode;         //!< texture coordinates generation mode, Graphic3d_TOTM_MANUAL by default
+  Standard_ShortReal                 myRotAngle;        //!< texture coordinates rotation angle in degrees, 0 by default
+  Standard_Boolean                   myToModulate;      //!< flag to modulate texture with material color, FALSE by default
+  Standard_Boolean                   myToRepeat;        //!< flag to repeat (true) or wrap (false) texture coordinates out of [0,1] range
 
 };
 
-
-
-
-
-
+DEFINE_STANDARD_HANDLE(Graphic3d_TextureParams, Standard_Transient)
 
 #endif // _Graphic3d_TextureParams_HeaderFile
index f9e1139..90cb639 100644 (file)
@@ -55,15 +55,17 @@ public:
 
   //! This ID will be used to manage resource in graphic driver.
   //!
-  //! Default implementation generates unique ID although inheritors may re-initialize it.
+  //! Default implementation generates unique ID within constructor;
+  //! inheritors may re-initialize it within their constructor,
+  //! but should never modify it afterwards.
   //!
   //! Multiple Graphic3d_TextureRoot instances with same ID
   //! will be treated as single texture with different parameters
   //! to optimize memory usage though this will be more natural
   //! to use same instance of Graphic3d_TextureRoot when possible.
   //!
-  //! Notice that inheritor may set this ID to empty string.
-  //! In this case independent graphical resource will be created
+  //! If this ID is set to empty string by inheritor,
+  //! then independent graphical resource will be created
   //! for each instance of Graphic3d_AspectFillArea3d where texture will be used.
   //!
   //! @return texture identifier.
@@ -74,7 +76,7 @@ public:
 
   //! Update image revision.
   //! Can be used for signaling changes in the texture source (e.g. file update, pixmap update)
-  //! without re-creating texture source itself (e.g. preserving the unique id).
+  //! without re-creating texture source itself (since unique id should be never modified).
   void UpdateRevision() { ++myRevision; }
 
   //! This method will be called by graphic driver each time when texture resource should be created.
@@ -101,13 +103,13 @@ protected:
   //! to be in Bottom-Up order (see Image_PixMap::IsTopDown()).
   Standard_EXPORT Graphic3d_TextureRoot(const Handle(Image_PixMap)& thePixmap, const Graphic3d_TypeOfTexture theType);
 
-  //! Unconditionally generate new texture id.
+  //! Unconditionally generate new texture id. Should be called only within constructor.
   Standard_EXPORT void generateId();
 
 protected:
 
   Handle(Graphic3d_TextureParams) myParams;   //!< associated texture parameters
-  TCollection_AsciiString         myTexId;    //!< unique identifier of this resource (for sharing)
+  TCollection_AsciiString         myTexId;    //!< unique identifier of this resource (for sharing graphic resource); should never be modified outside constructor
   Handle(Image_PixMap)            myPixMap;   //!< image pixmap - as one of the ways for defining the texture source
   OSD_Path                        myPath;     //!< image file path - as one of the ways for defining the texture source
   Standard_Size                   myRevision; //!< image revision - for signaling changes in the texture source (e.g. file update, pixmap update)
diff --git a/src/Graphic3d/Graphic3d_TextureSet.cxx b/src/Graphic3d/Graphic3d_TextureSet.cxx
new file mode 100644 (file)
index 0000000..518b8df
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright (c) 2017 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.
+
+#include <Graphic3d_TextureSet.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_TextureSet, Standard_Transient)
diff --git a/src/Graphic3d/Graphic3d_TextureSet.hxx b/src/Graphic3d/Graphic3d_TextureSet.hxx
new file mode 100644 (file)
index 0000000..7b0d5bc
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (c) 2017 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 _Graphic3d_TextureSet_HeaderFile
+#define _Graphic3d_TextureSet_HeaderFile
+
+#include <Graphic3d_TextureMap.hxx>
+#include <NCollection_Array1.hxx>
+
+//! Class holding array of textures to be mapped as a set.
+class Graphic3d_TextureSet : public Standard_Transient
+{
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_TextureSet, Standard_Transient)
+public:
+
+  //! Class for iterating texture set.
+  class Iterator : public NCollection_Array1<Handle(Graphic3d_TextureMap)>::Iterator
+  {
+  public:
+    //! Empty constructor.
+    Iterator() {}
+
+    //! Constructor.
+    Iterator (const Handle(Graphic3d_TextureSet)& theSet)
+    {
+      if (!theSet.IsNull())
+      {
+        NCollection_Array1<Handle(Graphic3d_TextureMap)>::Iterator::Init (theSet->myTextures);
+      }
+    }
+  };
+
+public:
+
+  //! Empty constructor.
+  Graphic3d_TextureSet() {}
+
+  //! Constructor.
+  Graphic3d_TextureSet (Standard_Integer theNbTextures)
+  : myTextures (0, theNbTextures - 1) {}
+
+  //! Constructor for a single texture.
+  Graphic3d_TextureSet (const Handle(Graphic3d_TextureMap)& theTexture)
+  : myTextures (0, 0)
+  {
+    myTextures.ChangeFirst() = theTexture;
+  }
+
+  //! Return TRUE if texture array is empty.
+  Standard_Boolean IsEmpty() const { return myTextures.IsEmpty(); }
+
+  //! Return number of textures.
+  Standard_Integer Size() const { return myTextures.Size(); }
+
+  //! Return the lower index in texture set.
+  Standard_Integer Lower() const { return myTextures.Lower(); }
+
+  //! Return the upper index in texture set.
+  Standard_Integer Upper() const { return myTextures.Upper(); }
+
+  //! Return the first texture.
+  const Handle(Graphic3d_TextureMap)& First() const { return myTextures.First(); }
+
+  //! Return the first texture.
+  void SetFirst (const Handle(Graphic3d_TextureMap)& theTexture) { myTextures.ChangeFirst() = theTexture; }
+
+  //! Return the texture at specified position within [0, Size()) range.
+  const Handle(Graphic3d_TextureMap)& Value (Standard_Integer theIndex) const { return myTextures.Value (theIndex); }
+
+  //! Return the texture at specified position within [0, Size()) range.
+  void SetValue (Standard_Integer theIndex,
+                 const Handle(Graphic3d_TextureMap)& theTexture) { myTextures.SetValue (theIndex, theTexture); }
+
+protected:
+
+  NCollection_Array1<Handle(Graphic3d_TextureMap)> myTextures;
+
+};
+
+#endif // _Graphic3d_TextureSet_HeaderFile
diff --git a/src/Graphic3d/Graphic3d_TextureUnit.hxx b/src/Graphic3d/Graphic3d_TextureUnit.hxx
new file mode 100644 (file)
index 0000000..c587f68
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (c) 2017 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 _Graphic3d_TextureUnit_HeaderFile
+#define _Graphic3d_TextureUnit_HeaderFile
+
+//! Texture unit.
+enum Graphic3d_TextureUnit
+{
+  // value as index number
+  Graphic3d_TextureUnit_0,
+  Graphic3d_TextureUnit_1,
+  Graphic3d_TextureUnit_2,
+  Graphic3d_TextureUnit_3,
+  Graphic3d_TextureUnit_4,
+  Graphic3d_TextureUnit_5,
+  Graphic3d_TextureUnit_6,
+  Graphic3d_TextureUnit_7,
+  Graphic3d_TextureUnit_8,
+  Graphic3d_TextureUnit_9,
+  Graphic3d_TextureUnit_10,
+  Graphic3d_TextureUnit_11,
+  Graphic3d_TextureUnit_12,
+  Graphic3d_TextureUnit_13,
+  Graphic3d_TextureUnit_14,
+  Graphic3d_TextureUnit_15,
+
+  Graphic3d_TextureUnit_BaseColor         = Graphic3d_TextureUnit_0, //!< base color of the material
+  //Graphic3d_TextureUnit_Normal            = Graphic3d_TextureUnit_1, //!< tangent space normal map
+  //Graphic3d_TextureUnit_MetallicRoughness = Graphic3d_TextureUnit_2, //!< metalness+roughness of the material
+  //Graphic3d_TextureUnit_Emissive          = Graphic3d_TextureUnit_3, //!< emissive map controls the color and intensity of the light being emitted by the material
+  //Graphic3d_TextureUnit_Occlusion         = Graphic3d_TextureUnit_4, //!< occlusion map indicating areas of indirect lighting
+};
+enum
+{
+  Graphic3d_TextureUnit_NB = Graphic3d_TextureUnit_15 + 1
+};
+
+#endif // _Graphic3d_TextureUnit_HeaderFile
index 9a8de15..e27984a 100644 (file)
@@ -21,6 +21,7 @@ enum Graphic3d_TypeOfLimit
   Graphic3d_TypeOfLimit_MaxNbClipPlanes,                //!< maximum number of active clipping planes
   Graphic3d_TypeOfLimit_MaxNbViews,                     //!< maximum number of views
   Graphic3d_TypeOfLimit_MaxTextureSize,                 //!< maximum size of texture
+  Graphic3d_TypeOfLimit_MaxCombinedTextureUnits,        //!< maximum number of combined texture units for multitexturing
   Graphic3d_TypeOfLimit_MaxMsaa,                        //!< maximum number of MSAA samples
   Graphic3d_TypeOfLimit_HasRayTracing,                  //!< indicates whether ray tracing is supported
   Graphic3d_TypeOfLimit_HasRayTracingTextures,          //!< indicates whether ray tracing textures are supported
index 7c3eab0..6159780 100755 (executable)
@@ -2,6 +2,7 @@ glext.h
 OpenGl_ArbDbg.hxx
 OpenGl_ArbFBO.hxx
 OpenGl_ArbIns.hxx
+OpenGl_ArbSamplerObject.hxx
 OpenGl_ArbTBO.hxx
 OpenGl_ArbTexBindless.hxx
 OpenGl_AspectFace.cxx
@@ -50,8 +51,11 @@ OpenGl_FrameBuffer.hxx
 OpenGl_FrameBuffer.cxx
 OpenGl_Texture.cxx
 OpenGl_Texture.hxx
+OpenGl_TextureSet.cxx
+OpenGl_TextureSet.hxx
 OpenGl_Resource.hxx
 OpenGl_Resource.cxx
+OpenGl_NamedResource.hxx
 OpenGl_Font.hxx
 OpenGl_Font.cxx
 OpenGl_BackgroundArray.cxx
diff --git a/src/OpenGl/OpenGl_ArbSamplerObject.hxx b/src/OpenGl/OpenGl_ArbSamplerObject.hxx
new file mode 100644 (file)
index 0000000..654fdc2
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright (c) 2017 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_ArbSamplerObject_Header
+#define _OpenGl_ArbSamplerObject_Header
+
+#include <OpenGl_GlFunctions.hxx>
+
+//! Provide Sampler Object functionality (texture parameters stored independently from texture itself).
+//! Available since OpenGL 3.3+ (GL_ARB_sampler_objects extension) and OpenGL ES 3.0+.
+struct OpenGl_ArbSamplerObject : protected OpenGl_GlFunctions
+{
+  using OpenGl_GlFunctions::glGenSamplers;
+  using OpenGl_GlFunctions::glDeleteSamplers;
+  using OpenGl_GlFunctions::glIsSampler;
+  using OpenGl_GlFunctions::glBindSampler;
+  using OpenGl_GlFunctions::glSamplerParameteri;
+  using OpenGl_GlFunctions::glSamplerParameteriv;
+  using OpenGl_GlFunctions::glSamplerParameterf;
+  using OpenGl_GlFunctions::glSamplerParameterfv;
+  using OpenGl_GlFunctions::glGetSamplerParameteriv;
+  using OpenGl_GlFunctions::glGetSamplerParameterfv;
+
+#if !defined(GL_ES_VERSION_2_0)
+  using OpenGl_GlFunctions::glSamplerParameterIiv;
+  using OpenGl_GlFunctions::glSamplerParameterIuiv;
+  using OpenGl_GlFunctions::glGetSamplerParameterIiv;
+  using OpenGl_GlFunctions::glGetSamplerParameterIuiv;
+#endif
+
+};
+
+#endif // _OpenGl_ArbSamplerObject_Header
index c262d76..2f4fde3 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <OpenGl_AspectFace.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Texture.hxx>
@@ -97,17 +98,7 @@ void OpenGl_AspectFace::SetAspect (const Handle(Graphic3d_AspectFillArea3d)& the
   myAspectEdge.Aspect()->SetWidth (theAspect->EdgeWidth());
 
   // update texture binding
-  const TCollection_AsciiString& aTextureKey = myAspect->TextureMap().IsNull() ? THE_EMPTY_KEY : myAspect->TextureMap()->GetId();
-  if (aTextureKey.IsEmpty() || myResources.TextureId != aTextureKey)
-  {
-    myResources.ResetTextureReadiness();
-  }
-  else if (!myResources.Texture.IsNull()
-        && !myAspect->TextureMap().IsNull()
-        &&  myResources.Texture->Revision() != myAspect->TextureMap()->Revision())
-  {
-    myResources.ResetTextureReadiness();
-  }
+  myResources.UpdateTexturesRediness (myAspect->TextureSet());
 
   // update shader program binding
   const TCollection_AsciiString& aShaderKey = myAspect->ShaderProgram().IsNull() ? THE_EMPTY_KEY : myAspect->ShaderProgram()->GetId();
@@ -132,25 +123,7 @@ void OpenGl_AspectFace::Render (const Handle(OpenGl_Workspace)& theWorkspace) co
 // =======================================================================
 void OpenGl_AspectFace::Release (OpenGl_Context* theContext)
 {
-  if (!myResources.Texture.IsNull())
-  {
-    if (theContext)
-    {
-      if (myResources.TextureId.IsEmpty())
-      {
-        theContext->DelayedRelease (myResources.Texture);
-      }
-      else
-      {
-        myResources.Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
-        theContext->ReleaseResource (myResources.TextureId, Standard_True);
-      }
-    }
-    myResources.Texture.Nullify();
-  }
-  myResources.TextureId.Clear();
-  myResources.ResetTextureReadiness();
-
+  myResources.ReleaseTextures (theContext);
   if (!myResources.ShaderProgram.IsNull()
    && theContext)
   {
@@ -162,56 +135,176 @@ void OpenGl_AspectFace::Release (OpenGl_Context* theContext)
 }
 
 // =======================================================================
-// function : BuildTexture
+// function : ReleaseTextures
 // purpose  :
 // =======================================================================
-void OpenGl_AspectFace::Resources::BuildTexture (const Handle(OpenGl_Context)&       theCtx,
-                                                 const Handle(Graphic3d_TextureMap)& theTexture)
+void OpenGl_AspectFace::Resources::ReleaseTextures (OpenGl_Context* theCtx)
 {
-  // release old texture resource
-  if (!Texture.IsNull())
+  if (myTextures.IsNull())
+  {
+    return;
+  }
+
+  for (OpenGl_TextureSet::Iterator aTextureIter (myTextures); aTextureIter.More(); aTextureIter.Next())
   {
-    if (!theTexture.IsNull()
-     &&  theTexture->GetId()    == TextureId
-     &&  theTexture->Revision() != Texture->Revision())
+    Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue();
+    if (aTextureRes.IsNull())
     {
-      Handle(Image_PixMap) anImage = theTexture->GetImage();
-      if (!anImage.IsNull())
+      continue;
+    }
+
+    if (theCtx != NULL)
+    {
+      if (aTextureRes->ResourceId().IsEmpty())
       {
-        Texture->Init (theCtx, *anImage.operator->(), theTexture->Type());
-        Texture->SetRevision (Texture->Revision());
-        return;
+        theCtx->DelayedRelease (aTextureRes);
       }
+      else
+      {
+        const TCollection_AsciiString aName = aTextureRes->ResourceId();
+        aTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call
+        theCtx->ReleaseResource (aName, Standard_True);
+      }
+    }
+    aTextureRes.Nullify();
+  }
+  myIsTextureReady = Standard_False;
+}
+
+// =======================================================================
+// function : UpdateTexturesRediness
+// purpose  :
+// =======================================================================
+void OpenGl_AspectFace::Resources::UpdateTexturesRediness (const Handle(Graphic3d_TextureSet)& theTextures)
+{
+  const Standard_Integer aNbTexturesOld = !myTextures.IsNull()  ? myTextures->Size()  : 0;
+  const Standard_Integer aNbTexturesNew = !theTextures.IsNull() ? theTextures->Size() : 0;
+  if (aNbTexturesOld != aNbTexturesNew)
+  {
+    myIsTextureReady = Standard_False;
+    return;
+  }
+  if (aNbTexturesOld == 0)
+  {
+    return;
+  }
+
+  Graphic3d_TextureSet::Iterator aTextureIter (theTextures);
+  OpenGl_TextureSet::Iterator aResIter (myTextures);
+  for (; aResIter.More(); aResIter.Next(), aTextureIter.Next())
+  {
+    const Handle(OpenGl_Texture)&       aResource = aResIter.Value();
+    const Handle(Graphic3d_TextureMap)& aTexture  = aTextureIter.Value();
+    if (aTexture.IsNull() != aResource.IsNull())
+    {
+      myIsTextureReady = Standard_False;
+      return;
+    }
+    else if (aTexture.IsNull())
+    {
+      continue;
     }
 
-    if (TextureId.IsEmpty())
+    const TCollection_AsciiString& aTextureKey = aTexture->GetId();
+    if (aTextureKey.IsEmpty() || aResource->ResourceId() != aTextureKey)
+    {
+      myIsTextureReady = Standard_False;
+      return;
+    }
+    else if (aResource->Revision() != aTexture->Revision())
     {
-      theCtx->DelayedRelease (Texture);
-      Texture.Nullify();
+      myIsTextureReady = Standard_False;
+      return;
     }
     else
     {
-      Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
-      theCtx->ReleaseResource (TextureId, Standard_True);
+      // just invalidate texture parameters
+      aResource->Sampler()->SetParameters (aTexture->GetParams());
     }
   }
+}
 
-  TextureId = theTexture.IsNull() ? THE_EMPTY_KEY : theTexture->GetId();
+// =======================================================================
+// function : BuildTextures
+// purpose  :
+// =======================================================================
+void OpenGl_AspectFace::Resources::BuildTextures (const Handle(OpenGl_Context)& theCtx,
+                                                  const Handle(Graphic3d_TextureSet)& theTextures)
+{
+  // release old texture resources
+  const Standard_Integer aNbTexturesOld = !myTextures.IsNull()  ? myTextures->Size()  : 0;
+  const Standard_Integer aNbTexturesNew = !theTextures.IsNull() ? theTextures->Size() : 0;
+  if (aNbTexturesOld != aNbTexturesNew)
+  {
+    ReleaseTextures (theCtx.get());
+    if (aNbTexturesNew > 0)
+    {
+      myTextures = new OpenGl_TextureSet (theTextures->Size());
+    }
+    else
+    {
+      myTextures.Nullify();
+    }
+  }
+  if (myTextures.IsNull())
+  {
+    return;
+  }
 
-  if (!theTexture.IsNull())
+  Graphic3d_TextureSet::Iterator aTextureIter (theTextures);
+  OpenGl_TextureSet::Iterator aResIter (myTextures);
+  for (; aResIter.More(); aResIter.Next(), aTextureIter.Next())
   {
-    if (TextureId.IsEmpty() || !theCtx->GetResource<Handle(OpenGl_Texture)> (TextureId, Texture))
+    Handle(OpenGl_Texture)& aResource = aResIter.ChangeValue();
+    const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
+    if (!aResource.IsNull())
+    {
+      if (!aTexture.IsNull()
+       &&  aTexture->GetId()    == aResource->ResourceId()
+       &&  aTexture->Revision() != aResource->Revision())
+      {
+        if (Handle(Image_PixMap) anImage = aTexture->GetImage())
+        {
+          aResource->Sampler()->SetParameters (aTexture->GetParams());
+          aResource->Init (theCtx, *anImage.operator->(), aTexture->Type());
+          aResource->SetRevision (aTexture->Revision());
+          continue;
+        }
+      }
+
+      if (aResource->ResourceId().IsEmpty())
+      {
+        theCtx->DelayedRelease (aResource);
+        aResource.Nullify();
+      }
+      else
+      {
+        const TCollection_AsciiString aTextureKey = aResource->ResourceId();
+        aResource.Nullify(); // we need nullify all handles before ReleaseResource() call
+        theCtx->ReleaseResource (aTextureKey, Standard_True);
+      }
+    }
+
+    if (!aTexture.IsNull())
     {
-      Texture = new OpenGl_Texture (theTexture->GetParams());
-      Handle(Image_PixMap) anImage = theTexture->GetImage();
-      if (!anImage.IsNull())
+      const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId();
+      if (aTextureKeyNew.IsEmpty()
+      || !theCtx->GetResource<Handle(OpenGl_Texture)> (aTextureKeyNew, aResource))
       {
-        Texture->Init (theCtx, *anImage.operator->(), theTexture->Type());
-        Texture->SetRevision (Texture->Revision());
+        aResource = new OpenGl_Texture (aTextureKeyNew, aTexture->GetParams());
+        if (Handle(Image_PixMap) anImage = aTexture->GetImage())
+        {
+          aResource->Init (theCtx, *anImage.operator->(), aTexture->Type());
+          aResource->SetRevision (aTexture->Revision());
+        }
+        if (!aTextureKeyNew.IsEmpty())
+        {
+          theCtx->ShareResource (aTextureKeyNew, aResource);
+        }
       }
-      if (!TextureId.IsEmpty())
+      else
       {
-        theCtx->ShareResource (TextureId, Texture);
+        aResource->Sampler()->SetParameters (aTexture->GetParams());
       }
     }
   }
index dde2e67..e362839 100644 (file)
@@ -17,6 +17,7 @@
 #define _OpenGl_AspectFace_Header
 
 #include <OpenGl_AspectLine.hxx>
+#include <OpenGl_TextureSet.hxx>
 #include <Graphic3d_AspectFillArea3d.hxx>
 #include <Graphic3d_ShaderProgram.hxx>
 #include <Graphic3d_TextureMap.hxx>
@@ -54,22 +55,15 @@ public:
   //! Set if lighting should be disabled or not.
   void SetNoLighting (bool theValue) { myIsNoLighting = theValue; }
 
-  //! @return texture mapping parameters.
-  const Handle(Graphic3d_TextureParams)& TextureParams() const
-  {
-    return myAspect->TextureMap()->GetParams();
-  }
-
-  //! @return texture map.
-  const Handle(OpenGl_Texture)& TextureRes (const Handle(OpenGl_Context)& theCtx) const
+  //! Returne textures map.
+  const Handle(OpenGl_TextureSet)& TextureSet (const Handle(OpenGl_Context)& theCtx) const
   {
     if (!myResources.IsTextureReady())
     {
-      myResources.BuildTexture (theCtx, myAspect->TextureMap());
+      myResources.BuildTextures (theCtx, myAspect->TextureSet());
       myResources.SetTextureReady();
     }
-
-    return myResources.Texture;
+    return myResources.TextureSet();
   }
 
   //! Init and return OpenGl shader program resource.
@@ -94,29 +88,49 @@ protected:
   mutable struct Resources
   {
   public:
+    //! Empty constructor.
     Resources()
-      : myIsTextureReady (Standard_False),
-        myIsShaderReady  (Standard_False) {}
+    : myIsTextureReady (Standard_False),
+      myIsShaderReady  (Standard_False) {}
 
+    //! Return TRUE if texture resource is up-to-date.
     Standard_Boolean IsTextureReady() const { return myIsTextureReady; }
+
+    //! Return TRUE if shader resource is up-to-date.
     Standard_Boolean IsShaderReady () const { return myIsShaderReady;  }
+
+    //! Set texture resource up-to-date state.
     void SetTextureReady() { myIsTextureReady = Standard_True; }
+
+    //! Set shader resource up-to-date state.
     void SetShaderReady () { myIsShaderReady  = Standard_True; }
-    void ResetTextureReadiness() { myIsTextureReady = Standard_False; }
+
+    //! Reset shader resource up-to-date state.
     void ResetShaderReadiness () { myIsShaderReady  = Standard_False; }
 
-    Standard_EXPORT void BuildTexture (const Handle(OpenGl_Context)&          theCtx,
-                                       const Handle(Graphic3d_TextureMap)&    theTexture);
+    //! Return textures array.
+    const Handle(OpenGl_TextureSet)& TextureSet() const { return myTextures; }
+
+    //! Update texture resource up-to-date state.
+    Standard_EXPORT void UpdateTexturesRediness (const Handle(Graphic3d_TextureSet)& theTextures);
+
+    //! Build texture resource.
+    Standard_EXPORT void BuildTextures (const Handle(OpenGl_Context)& theCtx,
+                                        const Handle(Graphic3d_TextureSet)& theTextures);
+
+    //! Build shader resource.
     Standard_EXPORT void BuildShader  (const Handle(OpenGl_Context)&          theCtx,
                                        const Handle(Graphic3d_ShaderProgram)& theShader);
 
-    Handle(OpenGl_Texture)       Texture;
-    TCollection_AsciiString      TextureId;
+    //! Release texture resource.
+    Standard_EXPORT void ReleaseTextures (OpenGl_Context* theCtx);
+
     Handle(OpenGl_ShaderProgram) ShaderProgram;
     TCollection_AsciiString      ShaderProgramId;
 
   private:
 
+    Handle(OpenGl_TextureSet) myTextures;
     Standard_Boolean myIsTextureReady;
     Standard_Boolean myIsShaderReady;
 
index a2899f5..f94d236 100644 (file)
@@ -1484,25 +1484,9 @@ void OpenGl_AspectMarker::SetAspect (const Handle(Graphic3d_AspectMarker3d)& the
 {
   myAspect = theAspect;
 
-  // update sprite resource bindings
-  TCollection_AsciiString aSpriteKey  = THE_EMPTY_KEY;
-  TCollection_AsciiString aSpriteAKey = THE_EMPTY_KEY;
-  myResources.SpriteKeys (theAspect->GetMarkerImage(), theAspect->Type(), theAspect->Scale(), theAspect->ColorRGBA(), aSpriteKey, aSpriteAKey);
-
-  if (aSpriteKey.IsEmpty()  || myResources.SpriteKey  != aSpriteKey
-   || aSpriteAKey.IsEmpty() || myResources.SpriteAKey != aSpriteAKey)
-  {
-    myResources.ResetSpriteReadiness();
-    myMarkerSize = theAspect->Scale();
-  }
-
-  // update shader program resource bindings
-  const TCollection_AsciiString& aShaderKey = myAspect->ShaderProgram().IsNull() ? THE_EMPTY_KEY : myAspect->ShaderProgram()->GetId();
-
-  if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey)
-  {
-    myResources.ResetShaderReadiness();
-  }
+  // update resource bindings
+  myResources.UpdateTexturesRediness (theAspect, myMarkerSize);
+  myResources.UpdateShaderRediness (theAspect);
 }
 
 // =======================================================================
@@ -1520,37 +1504,95 @@ void OpenGl_AspectMarker::Render (const Handle(OpenGl_Workspace)& theWorkspace)
 // =======================================================================
 void OpenGl_AspectMarker::Release (OpenGl_Context* theCtx)
 {
-  if (!myResources.Sprite.IsNull())
+  myResources.ReleaseTextures(theCtx);
+  myResources.ReleaseShaders (theCtx);
+}
+
+// =======================================================================
+// function : ReleaseTextures
+// purpose  :
+// =======================================================================
+void OpenGl_AspectMarker::Resources::ReleaseTextures (OpenGl_Context* theCtx)
+{
+  myIsSpriteReady = Standard_False;
+  if (mySprite.IsNull())
+  {
+    return;
+  }
+
+  if (theCtx != NULL)
   {
-    if (theCtx)
+    if (mySprite->First()->ResourceId().IsEmpty())
+    {
+      theCtx->DelayedRelease (mySprite->ChangeFirst());
+      theCtx->DelayedRelease (mySpriteA->ChangeFirst());
+    }
+    else
     {
-      if (myResources.SpriteKey.IsEmpty())
       {
-        theCtx->DelayedRelease (myResources.Sprite);
-        theCtx->DelayedRelease (myResources.SpriteA);
+        const TCollection_AsciiString aSpriteKey = mySprite->First()->ResourceId();
+        mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call
+        theCtx->ReleaseResource (aSpriteKey,  Standard_True);
       }
-      else
+      if (!mySpriteA.IsNull())
       {
-        myResources.Sprite.Nullify(); // we need nullify all handles before ReleaseResource() call
-        myResources.SpriteA.Nullify();
-        theCtx->ReleaseResource (myResources.SpriteKey,  Standard_True);
-        theCtx->ReleaseResource (myResources.SpriteAKey, Standard_True);
+        const TCollection_AsciiString aSpriteKeyA = mySpriteA->First()->ResourceId();
+        mySpriteA.Nullify();
+        theCtx->ReleaseResource (aSpriteKeyA, Standard_True);
       }
     }
-    myResources.Sprite.Nullify();
-    myResources.SpriteA.Nullify();
   }
-  myResources.SpriteKey.Clear();
-  myResources.SpriteAKey.Clear();
-  myResources.ResetSpriteReadiness();
+  mySprite.Nullify();
+  mySpriteA.Nullify();
+}
+
+// =======================================================================
+// function : ReleaseShaders
+// purpose  :
+// =======================================================================
+void OpenGl_AspectMarker::Resources::ReleaseShaders (OpenGl_Context* theCtx)
+{
+  if (!myShaderProgram.IsNull() && theCtx != NULL)
+  {
+    theCtx->ShaderManager()->Unregister (myShaderProgramId,
+                                         myShaderProgram);
+  }
+  myShaderProgramId.Clear();
+  myIsShaderReady = Standard_False;
+}
 
-  if (!myResources.ShaderProgram.IsNull() && theCtx)
+// =======================================================================
+// function : UpdateTexturesRediness
+// purpose  :
+// =======================================================================
+void OpenGl_AspectMarker::Resources::UpdateTexturesRediness (const Handle(Graphic3d_AspectMarker3d)& theAspect,
+                                                             Standard_ShortReal& theMarkerSize)
+{
+  // update sprite resource bindings
+  TCollection_AsciiString aSpriteKeyNew, aSpriteAKeyNew;
+  spriteKeys (theAspect->GetMarkerImage(), theAspect->Type(), theAspect->Scale(), theAspect->ColorRGBA(), aSpriteKeyNew, aSpriteAKeyNew);
+  const TCollection_AsciiString& aSpriteKeyOld  = !mySprite.IsNull()  ? mySprite ->First()->ResourceId() : THE_EMPTY_KEY;
+  const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->First()->ResourceId() : THE_EMPTY_KEY;
+  if (aSpriteKeyNew.IsEmpty()  || aSpriteKeyOld  != aSpriteKeyNew
+   || aSpriteAKeyNew.IsEmpty() || aSpriteAKeyOld != aSpriteAKeyNew)
   {
-    theCtx->ShaderManager()->Unregister (myResources.ShaderProgramId,
-                                         myResources.ShaderProgram);
+    myIsSpriteReady = Standard_False;
+    theMarkerSize = theAspect->Scale();
+  }
+}
+
+// =======================================================================
+// function : UpdateShaderRediness
+// purpose  :
+// =======================================================================
+void OpenGl_AspectMarker::Resources::UpdateShaderRediness (const Handle(Graphic3d_AspectMarker3d)& theAspect)
+{
+  // update shader program resource bindings
+  const TCollection_AsciiString& aShaderKey = theAspect->ShaderProgram().IsNull() ? THE_EMPTY_KEY : theAspect->ShaderProgram()->GetId();
+  if (aShaderKey.IsEmpty() || myShaderProgramId != aShaderKey)
+  {
+    myIsShaderReady = Standard_False;
   }
-  myResources.ShaderProgramId.Clear();
-  myResources.ResetShaderReadiness();
 }
 
 // =======================================================================
@@ -1565,52 +1607,56 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Context)&
                                                    Standard_ShortReal& theMarkerSize)
 {
   // generate key for shared resource
-  TCollection_AsciiString aNewKey  = THE_EMPTY_KEY;
-  TCollection_AsciiString aNewKeyA = THE_EMPTY_KEY;
-  SpriteKeys (theMarkerImage, theType, theScale, theColor, aNewKey, aNewKeyA);
+  TCollection_AsciiString aNewKey, aNewKeyA;
+  spriteKeys (theMarkerImage, theType, theScale, theColor, aNewKey, aNewKeyA);
+
+  const TCollection_AsciiString& aSpriteKeyOld  = !mySprite.IsNull()  ? mySprite ->First()->ResourceId() : THE_EMPTY_KEY;
+  const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->First()->ResourceId() : THE_EMPTY_KEY;
 
   // release old shared resources
-  const Standard_Boolean aNewResource = aNewKey.IsEmpty() || SpriteKey != aNewKey;
+  const Standard_Boolean aNewResource = aNewKey.IsEmpty()
+                                     || aSpriteKeyOld != aNewKey;
   if (aNewResource)
   {
-    if (!Sprite.IsNull())
+    if (!mySprite.IsNull())
     {
-      if (SpriteKey.IsEmpty())
+      if (mySprite->First()->ResourceId().IsEmpty())
       {
-        theCtx->DelayedRelease (Sprite);
-        Sprite.Nullify();
+        theCtx->DelayedRelease (mySprite->ChangeFirst());
+        mySprite.Nullify();
       }
       else
       {
-        Sprite.Nullify(); // we need nullify all handles before ReleaseResource() call
-        theCtx->ReleaseResource (SpriteKey, Standard_True);
+        const TCollection_AsciiString anOldKey = mySprite->First()->ResourceId();
+        mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call
+        theCtx->ReleaseResource (anOldKey, Standard_True);
       }
     }
-    SpriteKey = aNewKey;
   }
-  if (aNewKeyA.IsEmpty() || SpriteAKey != aNewKeyA)
+  if (aNewKeyA.IsEmpty() || aSpriteAKeyOld != aNewKeyA)
   {
-    if (!SpriteA.IsNull())
+    if (!mySpriteA.IsNull())
     {
-      if (SpriteAKey.IsEmpty())
+      if (mySpriteA->First()->ResourceId().IsEmpty())
       {
-        theCtx->DelayedRelease (SpriteA);
-        SpriteA.Nullify();
+        theCtx->DelayedRelease (mySpriteA->ChangeFirst());
+        mySpriteA.Nullify();
       }
       else
       {
-        SpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call
-        theCtx->ReleaseResource (SpriteAKey, Standard_True);
+        const TCollection_AsciiString anOldKey = mySprite->First()->ResourceId();
+        mySpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call
+        theCtx->ReleaseResource (anOldKey, Standard_True);
       }
     }
-    SpriteAKey = aNewKeyA;
   }
 
   if (!aNewResource)
   {
-    if (!Sprite->IsDisplayList())
+    const OpenGl_PointSprite* aSprite = dynamic_cast<OpenGl_PointSprite*> (mySprite->First().get());
+    if (!aSprite->IsDisplayList())
     {
-      theMarkerSize = Standard_ShortReal (Max (Sprite->SizeX(), Sprite->SizeY()));
+      theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY()));
     }
     return;
   }
@@ -1622,30 +1668,41 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Context)&
     return;
   }
 
+  if (mySprite.IsNull())
+  {
+    mySprite  = new OpenGl_TextureSet (1);
+    mySpriteA = new OpenGl_TextureSet (1);
+  }
+
+  Handle(OpenGl_PointSprite) aSprite, aSpriteA;
   if (!aNewKey.IsEmpty()
-   && theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKeyA, SpriteA) // alpha sprite could be shared
-   && theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKey,  Sprite))
+   && theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKeyA, aSpriteA) // alpha sprite could be shared
+   && theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKey,  aSprite))
   {
     // reuse shared resource
-    if (!Sprite->IsDisplayList())
+    if (!aSprite->IsDisplayList())
     {
-      theMarkerSize = Standard_ShortReal (Max (Sprite->SizeX(), Sprite->SizeY()));
+      theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY()));
     }
+    mySprite ->ChangeFirst() = aSprite;
+    mySpriteA->ChangeFirst() = aSpriteA;
     return;
   }
 
-  const bool hadAlreadyAlpha = !SpriteA.IsNull();
+  const bool hadAlreadyAlpha = !aSpriteA.IsNull();
   if (!hadAlreadyAlpha)
   {
-    SpriteA = new OpenGl_PointSprite();
+    aSpriteA = new OpenGl_PointSprite (aNewKeyA);
   }
-  Sprite  = new OpenGl_PointSprite();
+  aSprite = new OpenGl_PointSprite (aNewKey);
+  mySprite ->ChangeFirst() = aSprite;
+  mySpriteA->ChangeFirst() = aSpriteA;
   if (!aNewKey.IsEmpty())
   {
-    theCtx->ShareResource (aNewKey,  Sprite);
+    theCtx->ShareResource (aNewKey, aSprite);
     if (!hadAlreadyAlpha)
     {
-      theCtx->ShareResource (aNewKeyA, SpriteA);
+      theCtx->ShareResource (aNewKeyA, aSpriteA);
     }
   }
 
@@ -1770,18 +1827,18 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Context)&
 
     theMarkerSize = Max ((Standard_ShortReal )anImage->Width(),(Standard_ShortReal )anImage->Height());
 
-    Sprite->Init (theCtx, *anImage.operator->(), Graphic3d_TOT_2D);
+    aSprite->Init (theCtx, *anImage.operator->(), Graphic3d_TOT_2D);
     if (!hadAlreadyAlpha)
     {
       if (anImageA.IsNull()
-       && Sprite->GetFormat() != GL_ALPHA
+       && aSprite->GetFormat() != GL_ALPHA
        && !aNewMarkerImage.IsNull())
       {
         anImageA = aNewMarkerImage->GetImageAlpha();
       }
       if (!anImageA.IsNull())
       {
-        SpriteA->Init (theCtx, *anImageA.operator->(), Graphic3d_TOT_2D);
+        aSpriteA->Init (theCtx, *anImageA.operator->(), Graphic3d_TOT_2D);
       }
     }
   }
@@ -1790,7 +1847,7 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Context)&
   #if !defined(GL_ES_VERSION_2_0)
     // Creating list with bitmap for using it in compatibility mode
     GLuint aBitmapList = glGenLists (1);
-    Sprite->SetDisplayList (theCtx, aBitmapList);
+    aSprite->SetDisplayList (theCtx, aBitmapList);
 
     Standard_Integer aWidth, aHeight, anOffset, aNumOfBytes;
     if (theType == Aspect_TOM_USERDEFINED && !theMarkerImage.IsNull())
@@ -1923,25 +1980,25 @@ void OpenGl_AspectMarker::Resources::BuildShader (const Handle(OpenGl_Context)&
   }
 
   // release old shader program resources
-  if (!ShaderProgram.IsNull())
+  if (!myShaderProgram.IsNull())
   {
-    theCtx->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
-    ShaderProgramId.Clear();
-    ShaderProgram.Nullify();
+    theCtx->ShaderManager()->Unregister (myShaderProgramId, myShaderProgram);
+    myShaderProgramId.Clear();
+    myShaderProgram.Nullify();
   }
   if (theShader.IsNull())
   {
     return;
   }
 
-  theCtx->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
+  theCtx->ShaderManager()->Create (theShader, myShaderProgramId, myShaderProgram);
 }
 
 // =======================================================================
-// function : resourceKeys
+// function : spriteKeys
 // purpose  :
 // =======================================================================
-void OpenGl_AspectMarker::Resources::SpriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage,
+void OpenGl_AspectMarker::Resources::spriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage,
                                                  const Aspect_TypeOfMarker theType,
                                                  const Standard_ShortReal theScale,
                                                  const Graphic3d_Vec4& theColor,
index 02ae41f..2f83701 100644 (file)
@@ -21,6 +21,7 @@
 #include <TCollection_AsciiString.hxx>
 
 #include <OpenGl_Element.hxx>
+#include <OpenGl_TextureSet.hxx>
 
 class OpenGl_PointSprite;
 class OpenGl_ShaderProgram;
@@ -47,7 +48,7 @@ public:
 
   //! Init and return OpenGl point sprite resource.
   //! @return point sprite texture.
-  const Handle(OpenGl_PointSprite)& SpriteRes (const Handle(OpenGl_Context)& theCtx) const
+  const Handle(OpenGl_TextureSet)& SpriteRes (const Handle(OpenGl_Context)& theCtx) const
   {
     if (!myResources.IsSpriteReady())
     {
@@ -60,12 +61,12 @@ public:
       myResources.SetSpriteReady();
     }
 
-    return myResources.Sprite;
+    return myResources.Sprite();
   }
 
   //! Init and return OpenGl highlight point sprite resource.
   //! @return point sprite texture for highlight.
-  const Handle(OpenGl_PointSprite)& SpriteHighlightRes (const Handle(OpenGl_Context)& theCtx) const
+  const Handle(OpenGl_TextureSet)& SpriteHighlightRes (const Handle(OpenGl_Context)& theCtx) const
   {
     if (!myResources.IsSpriteReady())
     {
@@ -78,7 +79,7 @@ public:
       myResources.SetSpriteReady();
     }
 
-    return myResources.SpriteA;
+    return myResources.SpriteA();
   }
 
   //! Init and return OpenGl shader program resource.
@@ -91,7 +92,7 @@ public:
       myResources.SetShaderReady();
     }
 
-    return myResources.ShaderProgram;
+    return myResources.ShaderProgram();
   }
 
   Standard_EXPORT virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const;
@@ -104,19 +105,34 @@ protected:
   {
   public:
 
-    Resources() :
-        SpriteKey (""),
-        SpriteAKey (""),
-        myIsSpriteReady (Standard_False),
-        myIsShaderReady (Standard_False) {}
+    //! Empty constructor.
+    Resources()
+    : myIsSpriteReady (Standard_False),
+      myIsShaderReady (Standard_False) {}
+
+    const Handle(OpenGl_TextureSet)&    Sprite()  const { return mySprite; }
+    const Handle(OpenGl_TextureSet)&    SpriteA() const { return mySpriteA; }
+    const Handle(OpenGl_ShaderProgram)& ShaderProgram() const { return myShaderProgram; }
 
     Standard_Boolean IsSpriteReady() const { return myIsSpriteReady; }
     Standard_Boolean IsShaderReady() const { return myIsShaderReady; }
     void SetSpriteReady() { myIsSpriteReady = Standard_True; }
     void SetShaderReady() { myIsShaderReady = Standard_True; }
-    void ResetSpriteReadiness() { myIsSpriteReady = Standard_False; }
-    void ResetShaderReadiness() { myIsShaderReady = Standard_False; }
 
+    //! Update texture resource up-to-date state.
+    Standard_EXPORT void UpdateTexturesRediness (const Handle(Graphic3d_AspectMarker3d)& theAspect,
+                                                 Standard_ShortReal& theMarkerSize);
+
+    //! Update shader resource up-to-date state.
+    Standard_EXPORT void UpdateShaderRediness (const Handle(Graphic3d_AspectMarker3d)& theAspect);
+
+    //! Release texture resource.
+    Standard_EXPORT void ReleaseTextures (OpenGl_Context* theCtx);
+
+    //! Release shader resource.
+    Standard_EXPORT void ReleaseShaders (OpenGl_Context* theCtx);
+
+    //! Build texture resources.
     Standard_EXPORT void BuildSprites (const Handle(OpenGl_Context)&        theCtx,
                                        const Handle(Graphic3d_MarkerImage)& theMarkerImage,
                                        const Aspect_TypeOfMarker            theType,
@@ -124,29 +140,28 @@ protected:
                                        const Graphic3d_Vec4&                theColor,
                                        Standard_ShortReal&                  theMarkerSize);
 
+    //! Build shader resources.
     Standard_EXPORT void BuildShader (const Handle(OpenGl_Context)&          theCtx,
                                       const Handle(Graphic3d_ShaderProgram)& theShader);
 
-    Standard_EXPORT void SpriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage,
-                                     const Aspect_TypeOfMarker            theType,
-                                     const Standard_ShortReal             theScale,
-                                     const Graphic3d_Vec4&                theColor,
-                                     TCollection_AsciiString&             theKey,
-                                     TCollection_AsciiString&             theKeyA);
-
-    Handle(OpenGl_PointSprite)   Sprite;
-    TCollection_AsciiString      SpriteKey;
-
-    Handle(OpenGl_PointSprite)   SpriteA;
-    TCollection_AsciiString      SpriteAKey;
+  private:
 
-    Handle(OpenGl_ShaderProgram) ShaderProgram;
-    TCollection_AsciiString      ShaderProgramId;
+    //! Generate resource keys for a sprite.
+    static void spriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage,
+                            const Aspect_TypeOfMarker            theType,
+                            const Standard_ShortReal             theScale,
+                            const Graphic3d_Vec4&                theColor,
+                            TCollection_AsciiString&             theKey,
+                            TCollection_AsciiString&             theKeyA);
 
   private:
 
-    Standard_Boolean myIsSpriteReady;
-    Standard_Boolean myIsShaderReady;
+    Handle(OpenGl_TextureSet)      mySprite;
+    Handle(OpenGl_TextureSet)      mySpriteA;
+    Handle(OpenGl_ShaderProgram)   myShaderProgram;
+    TCollection_AsciiString        myShaderProgramId;
+    Standard_Boolean               myIsSpriteReady;
+    Standard_Boolean               myIsShaderReady;
 
   } myResources;
 
index b49b4d9..0f5723b 100644 (file)
@@ -338,8 +338,8 @@ Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl
   // Get texture parameters
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
   const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace();
-  GLfloat aTextureWidth  = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeX();
-  GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeY();
+  GLfloat aTextureWidth  = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeX();
+  GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeY();
 
   if (myFillMethod == Aspect_FM_CENTERED)
   {
index dd032d9..a4b7793 100755 (executable)
@@ -157,9 +157,9 @@ void OpenGl_CappingPlaneResource::updateAspect (const Handle(Graphic3d_AspectFil
   }
   if (myPlaneRoot->ToUseObjectTexture())
   {
+    myFillAreaAspect->SetTextureSet (theObjAspect->TextureSet());
     if (theObjAspect->ToMapTexture())
     {
-      myFillAreaAspect->SetTextureMap (theObjAspect->TextureMap());
       myFillAreaAspect->SetTextureMapOn();
     }
     else
index 0a7d396..52f9a16 100644 (file)
@@ -24,6 +24,7 @@
 #include <OpenGl_ArbDbg.hxx>
 #include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_ExtGS.hxx>
+#include <OpenGl_ArbSamplerObject.hxx>
 #include <OpenGl_ArbTexBindless.hxx>
 #include <OpenGl_GlCore44.hxx>
 #include <OpenGl_FrameBuffer.hxx>
@@ -133,6 +134,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   arbNPTW  (Standard_False),
   arbTexRG (Standard_False),
   arbTexFloat (Standard_False),
+  arbSamplerObject (NULL),
   arbTexBindless (NULL),
   arbTBO (NULL),
   arbTboRGB32 (Standard_False),
@@ -159,6 +161,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myAnisoMax   (1),
   myTexClamp   (GL_CLAMP_TO_EDGE),
   myMaxTexDim  (1024),
+  myMaxTexCombined (1),
   myMaxClipPlanes (6),
   myMaxMsaaSamples(0),
   myMaxDrawBuffers (1),
@@ -287,12 +290,6 @@ OpenGl_Context::~OpenGl_Context()
   mySharedResources.Nullify();
   myDelayed.Nullify();
 
-  // release sampler object
-  if (!myTexSampler.IsNull())
-  {
-    myTexSampler->Release (this);
-  }
-
   if (arbDbg != NULL
    && myIsGlDebugCtx
    && IsValid())
@@ -1281,6 +1278,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   extGS      = NULL;
   myDefaultVao = 0;
 
+  //! Make record shorter to retrieve function pointer using variable with same name
+  #define FindProcShort(theFunc) FindProc(#theFunc, myFuncs->theFunc)
+
 #if defined(GL_ES_VERSION_2_0)
 
   hasTexRGBA8 = IsGlGreaterEqual (3, 0)
@@ -1308,10 +1308,28 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
     arbFBO    = (OpenGl_ArbFBO*      )(&(*myFuncs));
   }
   if (IsGlGreaterEqual (3, 0)
-   && FindProc ("glBlitFramebuffer", myFuncs->glBlitFramebuffer))
+   && FindProcShort (glBlitFramebuffer))
   {
     arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
   }
+  if (IsGlGreaterEqual (3, 0)
+   && FindProcShort (glGenSamplers)
+   && FindProcShort (glDeleteSamplers)
+   && FindProcShort (glIsSampler)
+   && FindProcShort (glBindSampler)
+   && FindProcShort (glSamplerParameteri)
+   && FindProcShort (glSamplerParameteriv)
+   && FindProcShort (glSamplerParameterf)
+   && FindProcShort (glSamplerParameterfv)
+   && FindProcShort (glGetSamplerParameteriv)
+   && FindProcShort (glGetSamplerParameterfv))
+   //&& FindProcShort (glSamplerParameterIiv) // only on Desktop or with extensions GL_OES_texture_border_clamp/GL_EXT_texture_border_clamp
+   //&& FindProcShort (glSamplerParameterIuiv)
+   //&& FindProcShort (glGetSamplerParameterIiv)
+   //&& FindProcShort (glGetSamplerParameterIuiv))
+  {
+    arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
+  }
   extFragDepth = !IsGlGreaterEqual(3, 0)
                && CheckExtension ("GL_EXT_frag_depth");
   if (IsGlGreaterEqual (3, 1)
@@ -1440,6 +1458,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   }
 
   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
+  if (IsGlGreaterEqual (1, 5))
+  {
+    glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
+  }
 
   if (extAnis)
   {
@@ -1466,9 +1488,6 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   bool has43 = false;
   bool has44 = false;
 
-  //! Make record shorter to retrieve function pointer using variable with same name
-  #define FindProcShort(theFunc) FindProc(#theFunc, myFuncs->theFunc)
-
   // retrieve platform-dependent extensions
 #if defined(HAVE_EGL)
   //
@@ -1917,6 +1936,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
        && FindProcShort (glGetSamplerParameterIiv)
        && FindProcShort (glGetSamplerParameterfv)
        && FindProcShort (glGetSamplerParameterIuiv);
+  if (hasSamplerObjects)
+  {
+    arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
+  }
 
   // load GL_ARB_timer_query (added to OpenGL 3.3 core)
   const bool hasTimerQuery = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_timer_query"))
@@ -2507,10 +2530,6 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
     core33back = (OpenGl_GlCore33Back* )(&(*myFuncs));
   }
 
-  // initialize sampler object
-  myTexSampler = new OpenGl_Sampler();
-  myTexSampler->Init (*this);
-
   if (!has40)
   {
     checkWrongVersion (4, 0);
@@ -2807,6 +2826,7 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
   if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0)
   {
     addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim));
+    addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined));
     addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples));
   }
 
@@ -2954,6 +2974,111 @@ void OpenGl_Context::ReleaseDelayed()
 }
 
 // =======================================================================
+// function : BindTextures
+// purpose  :
+// =======================================================================
+Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures)
+{
+  if (myActiveTextures == theTextures)
+  {
+    return myActiveTextures;
+  }
+
+  Handle(OpenGl_Context) aThisCtx (this);
+  OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures);
+  for (;;)
+  {
+    if (!aTextureIterNew.More())
+    {
+      for (; aTextureIterOld.More(); aTextureIterOld.Next())
+      {
+        if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value())
+        {
+        #if !defined(GL_ES_VERSION_2_0)
+          if (core11 != NULL)
+          {
+            OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
+          }
+        #endif
+          aTextureOld->Unbind (aThisCtx);
+        }
+      }
+      break;
+    }
+
+    const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value();
+    if (aTextureIterOld.More())
+    {
+      const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value();
+      if (aTextureNew == aTextureOld)
+      {
+        aTextureIterNew.Next();
+        aTextureIterOld.Next();
+        continue;
+      }
+      else if (aTextureNew.IsNull()
+           || !aTextureNew->IsValid())
+      {
+        if (!aTextureOld.IsNull())
+        {
+        #if !defined(GL_ES_VERSION_2_0)
+          if (core11 != NULL)
+          {
+            OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
+          }
+        #endif
+          aTextureOld->Unbind (aThisCtx);
+        }
+
+        aTextureIterNew.Next();
+        aTextureIterOld.Next();
+        continue;
+      }
+
+      aTextureIterOld.Next();
+    }
+    if (aTextureNew.IsNull())
+    {
+      aTextureIterNew.Next();
+      continue;
+    }
+
+    const Graphic3d_TextureUnit aTexUnit = aTextureNew->Sampler()->Parameters()->TextureUnit();
+    if (aTexUnit >= myMaxTexCombined)
+    {
+      PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                   TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
+      aTextureIterNew.Next();
+      continue;
+    }
+
+    aTextureNew->Bind (aThisCtx);
+    if (aTextureNew->Sampler()->ToUpdateParameters())
+    {
+      if (aTextureNew->Sampler()->IsImmutable())
+      {
+        aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
+      }
+      else
+      {
+        OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps());
+      }
+    }
+  #if !defined(GL_ES_VERSION_2_0)
+    if (core11 != NULL)
+    {
+      OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
+    }
+  #endif
+    aTextureIterNew.Next();
+  }
+
+  Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
+  myActiveTextures = theTextures;
+  return anOldTextures;
+}
+
+// =======================================================================
 // function : BindProgram
 // purpose  :
 // =======================================================================
index a6a6599..018fa46 100644 (file)
@@ -24,6 +24,7 @@
 #include <Aspect_TypeOfLine.hxx>
 #include <NCollection_DataMap.hxx>
 #include <Graphic3d_DiagnosticInfo.hxx>
+#include <Graphic3d_TextureUnit.hxx>
 #include <NCollection_Map.hxx>
 #include <NCollection_Handle.hxx>
 #include <NCollection_List.hxx>
 #include <OpenGl_MatrixState.hxx>
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_Resource.hxx>
+#include <OpenGl_TextureSet.hxx>
 #include <Standard_Transient.hxx>
 #include <TColStd_IndexedDataMapOfStringString.hxx>
 #include <TColStd_PackedMapOfInteger.hxx>
 #include <OpenGl_Clipping.hxx>
 #include <OpenGl_GlCore11.hxx>
-#include <OpenGl_ShaderProgram.hxx>
 
 #include <NCollection_Shared.hxx>
 
@@ -68,8 +69,9 @@ struct OpenGl_ArbIns;
 struct OpenGl_ArbDbg;
 struct OpenGl_ArbFBO;
 struct OpenGl_ArbFBOBlit;
-struct OpenGl_ExtGS;
+struct OpenGl_ArbSamplerObject;
 struct OpenGl_ArbTexBindless;
+struct OpenGl_ExtGS;
 
 template<typename theBaseClass_t> struct OpenGl_TmplCore12;
 typedef OpenGl_TmplCore12<OpenGl_GlCore11>     OpenGl_GlCore12;
@@ -130,11 +132,12 @@ template<typename theBaseClass_t> struct OpenGl_TmplCore44;
 typedef OpenGl_TmplCore44<OpenGl_GlCore43Back> OpenGl_GlCore44Back;
 typedef OpenGl_TmplCore44<OpenGl_GlCore43>     OpenGl_GlCore44;
 
-class OpenGl_ShaderManager;
-class OpenGl_Sampler;
-class OpenGl_FrameBuffer;
-class OpenGl_AspectFace;
 class Graphic3d_PresentationAttributes;
+class OpenGl_AspectFace;
+class OpenGl_FrameBuffer;
+class OpenGl_Sampler;
+class OpenGl_ShaderProgram;
+class OpenGl_ShaderManager;
 
 enum OpenGl_FeatureFlag
 {
@@ -461,6 +464,9 @@ public:
   //! @return value for GL_MAX_TEXTURE_SIZE
   Standard_Integer MaxTextureSize() const { return myMaxTexDim; }
 
+  //! @return value for GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
+  Standard_Integer MaxCombinedTextureUnits() const { return myMaxTexCombined; }
+
   //! @return value for GL_MAX_SAMPLES
   Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; }
 
@@ -631,18 +637,19 @@ public: //! @name methods to alter or retrieve current state
   //! OpenGl state variables has a possibility of being out-of-date.
   Standard_EXPORT void FetchState();
 
+  //! @return active textures
+  const Handle(OpenGl_TextureSet)& ActiveTextures() const { return myActiveTextures; }
+
+  //! Bind specified texture set to current context,
+  //! or unbind previous one when NULL specified.
+  Standard_EXPORT Handle(OpenGl_TextureSet) BindTextures (const Handle(OpenGl_TextureSet)& theTextures);
+
   //! @return active GLSL program
   const Handle(OpenGl_ShaderProgram)& ActiveProgram() const
   {
     return myActiveProgram;
   }
 
-  //! @return OpenGL sampler object used to override default texture parameters
-  const Handle(OpenGl_Sampler)& TextureSampler()
-  {
-    return myTexSampler;
-  }
-
   //! Bind specified program to current context,
   //! or unbind previous one when NULL specified.
   //! @return true if some program is bound to context
@@ -798,6 +805,7 @@ public: //! @name extensions
   Standard_Boolean       arbNPTW;            //!< GL_ARB_texture_non_power_of_two
   Standard_Boolean       arbTexRG;           //!< GL_ARB_texture_rg
   Standard_Boolean       arbTexFloat;        //!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0)
+  OpenGl_ArbSamplerObject* arbSamplerObject; //!< GL_ARB_sampler_objects (on desktop OpenGL - since 3.3 or as extension GL_ARB_sampler_objects; on OpenGL ES - since 3.0)
   OpenGl_ArbTexBindless* arbTexBindless;     //!< GL_ARB_bindless_texture
   OpenGl_ArbTBO*         arbTBO;             //!< GL_ARB_texture_buffer_object
   Standard_Boolean       arbTboRGB32;        //!< GL_ARB_texture_buffer_object_rgb32 (3-component TBO), in core since 4.0
@@ -863,6 +871,7 @@ private: // context info
   Standard_Integer myAnisoMax;             //!< maximum level of anisotropy texture filter
   Standard_Integer myTexClamp;             //!< either GL_CLAMP_TO_EDGE (1.2+) or GL_CLAMP (1.1)
   Standard_Integer myMaxTexDim;            //!< value for GL_MAX_TEXTURE_SIZE
+  Standard_Integer myMaxTexCombined;       //!< value for GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
   Standard_Integer myMaxClipPlanes;        //!< value for GL_MAX_CLIP_PLANES
   Standard_Integer myMaxMsaaSamples;       //!< value for GL_MAX_SAMPLES
   Standard_Integer myMaxDrawBuffers;       //!< value for GL_MAX_DRAW_BUFFERS
@@ -883,7 +892,8 @@ private: // context info
 private: //! @name fields tracking current state
 
   Handle(OpenGl_ShaderProgram)  myActiveProgram;   //!< currently active GLSL program
-  Handle(OpenGl_Sampler)        myTexSampler;      //!< currently active sampler object
+  Handle(OpenGl_TextureSet)     myActiveTextures;  //!< currently bound textures
+                                                   //!< currently active sampler objects
   Handle(OpenGl_FrameBuffer)    myDefaultFbo;      //!< default Frame Buffer Object
   Handle(OpenGl_LineAttributes) myHatchStyles;     //!< resource holding predefined hatch styles patterns
   Standard_Integer              myViewport[4];     //!< current viewport
index f9215e7..8cbd467 100755 (executable)
@@ -129,7 +129,7 @@ bool OpenGl_Font::createTexture (const Handle(OpenGl_Context)& theCtx)
   aParams->SetFilter      (Graphic3d_TOTF_BILINEAR);
   aParams->SetAnisoFilter (Graphic3d_LOTA_OFF);
 
-  myTextures.Append (new OpenGl_Texture (aParams));
+  myTextures.Append (new OpenGl_Texture (myKey + "_texture" + myTextures.Size(), aParams));
   Handle(OpenGl_Texture)& aTexture = myTextures.ChangeLast();
 
   Image_PixMap aBlackImg;
index 880589d..03e3411 100644 (file)
@@ -767,6 +767,36 @@ public: //! @name OpenGL ES 3.0
   typedef void (*glDrawBuffers_t)(GLsizei n, const GLenum* bufs);
   glDrawBuffers_t glDrawBuffers;
 
+  typedef void (*glGenSamplers_t)(GLsizei count, GLuint* samplers);
+  glGenSamplers_t glGenSamplers;
+
+  typedef void (*glDeleteSamplers_t)(GLsizei count, const GLuint* samplers);
+  glDeleteSamplers_t glDeleteSamplers;
+
+  typedef GLboolean (*glIsSampler_t)(GLuint sampler);
+  glIsSampler_t glIsSampler;
+
+  typedef void (*glBindSampler_t)(GLuint unit, GLuint sampler);
+  glBindSampler_t glBindSampler;
+
+  typedef void (*glSamplerParameteri_t)(GLuint sampler, GLenum pname, GLint param);
+  glSamplerParameteri_t glSamplerParameteri;
+
+  typedef void (*glSamplerParameteriv_t)(GLuint sampler, GLenum pname, const GLint* param);
+  glSamplerParameteriv_t glSamplerParameteriv;
+
+  typedef void (*glSamplerParameterf_t)(GLuint sampler, GLenum pname, GLfloat param);
+  glSamplerParameterf_t glSamplerParameterf;
+
+  typedef void (*glSamplerParameterfv_t)(GLuint sampler, GLenum pname, const GLfloat* param);
+  glSamplerParameterfv_t glSamplerParameterfv;
+
+  typedef void (*glGetSamplerParameteriv_t)(GLuint sampler, GLenum pname, GLint* params);
+  glGetSamplerParameteriv_t glGetSamplerParameteriv;
+
+  typedef void (*glGetSamplerParameterfv_t)(GLuint sampler, GLenum pname, GLfloat* params);
+  glGetSamplerParameterfv_t glGetSamplerParameterfv;
+
 public: //! @name OpenGL ES 3.1
 
   typedef void (*glTexStorage2DMultisample_t)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
index 0912755..196837e 100644 (file)
@@ -413,6 +413,8 @@ Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit
       return 10000;
     case Graphic3d_TypeOfLimit_MaxTextureSize:
       return !aCtx.IsNull() ? aCtx->MaxTextureSize() : 1024;
+    case Graphic3d_TypeOfLimit_MaxCombinedTextureUnits:
+      return !aCtx.IsNull() ? aCtx->MaxCombinedTextureUnits() : 1;
     case Graphic3d_TypeOfLimit_MaxMsaa:
       return !aCtx.IsNull() ? aCtx->MaxMsaaSamples() : 0;
     case Graphic3d_TypeOfLimit_HasRayTracing:
index 1c82e6b..d3d8601 100644 (file)
@@ -680,10 +680,10 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)&   theWorkspace,
   }
 
   // save environment texture
-  Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
+  Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
   if (!myLayerSettings.UseEnvironmentTexture())
   {
-    theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
+    theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
   }
 
   // handle depth offset
index d7bf035..6a15b01 100644 (file)
@@ -610,10 +610,10 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theW
       // Bind full screen quad buffer and framebuffer resources.
       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
 
-      const Handle(OpenGl_Texture) aTextureBack = theWorkspace->DisableTexture();
+      const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
 
-      theOitAccumFbo->ColorTexture (0)->Bind (aCtx, GL_TEXTURE0 + 0);
-      theOitAccumFbo->ColorTexture (1)->Bind (aCtx, GL_TEXTURE0 + 1);
+      theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
+      theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
 
       // Draw full screen quad with special shader to compose the buffers.
       aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
@@ -621,13 +621,13 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theW
 
       // Unbind OpenGL texture objects and shader program.
       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
-      theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, GL_TEXTURE0 + 0);
-      theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, GL_TEXTURE0 + 1);
+      theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
+      theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
       aCtx->BindProgram (NULL);
 
       if (!aTextureBack.IsNull())
       {
-        theWorkspace->EnableTexture (aTextureBack);
+        aCtx->BindTextures (aTextureBack);
       }
     }
     else
diff --git a/src/OpenGl/OpenGl_NamedResource.hxx b/src/OpenGl/OpenGl_NamedResource.hxx
new file mode 100644 (file)
index 0000000..e316fe1
--- /dev/null
@@ -0,0 +1,41 @@
+// Created on: 2011-03-18
+// Created by: Anton POLETAEV
+// Copyright (c) 2011-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_NamedResource_HeaderFile
+#define _OpenGl_NamedResource_HeaderFile
+
+#include <OpenGl_Resource.hxx>
+#include <TCollection_AsciiString.hxx>
+
+//! Named resource object.
+class OpenGl_NamedResource : public OpenGl_Resource
+{
+  DEFINE_STANDARD_RTTIEXT(OpenGl_NamedResource, OpenGl_Resource)
+public:
+
+  //! Empty constructor
+  OpenGl_NamedResource (const TCollection_AsciiString& theId)
+  : myResourceId (theId) {}
+
+  //! Return resource name.
+  const TCollection_AsciiString& ResourceId() const { return myResourceId; }
+
+protected:
+
+  TCollection_AsciiString myResourceId; //!< resource name
+
+};
+
+#endif // _OpenGl_NamedResource_HeaderFile
index 57ff6b6..acbe7d1 100755 (executable)
 
 #include <Graphic3d_TextureParams.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <Standard_Assert.hxx>
 #include <Image_PixMap.hxx>
 
-
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_PointSprite,OpenGl_Texture)
 
 // =======================================================================
 // function : OpenGl_PointSprite
 // purpose  :
 // =======================================================================
-OpenGl_PointSprite::OpenGl_PointSprite()
-: OpenGl_Texture (NULL),
+OpenGl_PointSprite::OpenGl_PointSprite (const TCollection_AsciiString& theResourceId)
+: OpenGl_Texture (theResourceId, Handle(Graphic3d_TextureParams)()),
   myBitmapList (0)
 {
-  //myParams->SetFilter (Graphic3d_TOTF_NEAREST);
-  myParams->SetModulate (Standard_False);
-  myParams->SetGenMode (Graphic3d_TOTM_SPRITE,
-                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
-                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
+  //mySampler->Parameters()->SetFilter (Graphic3d_TOTF_NEAREST);
+  mySampler->Parameters()->SetModulate (Standard_False);
+  mySampler->Parameters()->SetGenMode (Graphic3d_TOTM_SPRITE,
+                                       Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
+                                       Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
 }
 
 // =======================================================================
@@ -80,7 +80,6 @@ void OpenGl_PointSprite::SetDisplayList (const Handle(OpenGl_Context)& theCtx,
   myBitmapList = theBitmapList;
 }
 
-
 // =======================================================================
 // function : DrawBitmap
 // purpose  :
index bf550ab..bb8f458 100755 (executable)
@@ -28,7 +28,7 @@ class OpenGl_PointSprite : public OpenGl_Texture
 public:
 
   //! Create uninitialized resource.
-  Standard_EXPORT OpenGl_PointSprite();
+  Standard_EXPORT OpenGl_PointSprite (const TCollection_AsciiString& theResourceId);
 
   //! Destroy object.
   Standard_EXPORT virtual ~OpenGl_PointSprite();
index 811097d..98ee3c2 100644 (file)
@@ -19,6 +19,7 @@
 #include <OpenGl_IndexBuffer.hxx>
 #include <OpenGl_PointSprite.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Structure.hxx>
@@ -529,9 +530,10 @@ void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWork
 {
   const OpenGl_AspectMarker* anAspectMarker     = theWorkspace->ApplyAspectMarker();
   const Handle(OpenGl_Context)&     aCtx        = theWorkspace->GetGlContext();
-  const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
-  if (!aSpriteNorm.IsNull()
-   && !aSpriteNorm->IsDisplayList())
+  const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
+  const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
+  if (aSpriteNorm != NULL
+  && !aSpriteNorm->IsDisplayList())
   {
     // Textured markers will be drawn with the point sprites
     aCtx->SetPointSize (anAspectMarker->MarkerSize());
@@ -568,7 +570,7 @@ void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWork
 #if !defined(GL_ES_VERSION_2_0)
   // Textured markers will be drawn with the glBitmap
   else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT
-       && !aSpriteNorm.IsNull())
+        && aSpriteNorm != NULL)
   {
     /**if (!isHilight && (myPArray->vcolours != NULL))
     {
@@ -700,9 +702,14 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
   if (!myIsVboInit)
   {
     // compatibility - keep data to draw markers using display lists
-    const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
-                                    && !anAspectMarker->SpriteRes (aCtx).IsNull()
-                                    &&  anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
+    Standard_Boolean toKeepData = Standard_False;
+    if (myDrawMode == GL_POINTS)
+    {
+      const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
+      const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
+      toKeepData = aSpriteNorm != NULL
+               &&  aSpriteNorm->IsDisplayList();
+    }
   #if defined (GL_ES_VERSION_2_0)
     processIndices (aCtx);
   #endif
@@ -717,7 +724,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
                                   &&  myVboAttribs->HasNormalAttribute();
 
   // Temporarily disable environment mapping
-  Handle(OpenGl_Texture) aTextureBack;
+  Handle(OpenGl_TextureSet) aTextureBack;
   bool toDrawArray = true;
   if (myDrawMode > GL_LINE_STRIP)
   {
@@ -725,7 +732,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
   }
   else if (myDrawMode <= GL_LINE_STRIP)
   {
-    aTextureBack = theWorkspace->DisableTexture();
+    aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
     if (myDrawMode == GL_POINTS)
     {
       toDrawArray = anAspectMarker->Aspect()->Type() != Aspect_TOM_EMPTY;
@@ -744,19 +751,20 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
     {
       case GL_POINTS:
       {
-        const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
-        if (!aSpriteNorm.IsNull()
-         && !aSpriteNorm->IsDisplayList())
+        const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
+        const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
+        if (aSpriteNorm != NULL
+        && !aSpriteNorm->IsDisplayList())
         {
-          const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
-                                                    ? anAspectMarker->SpriteHighlightRes (aCtx)
-                                                    : aSpriteNorm;
-          theWorkspace->EnableTexture (aSprite);
+          const Handle(OpenGl_TextureSet)& aSprite = toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->First()->IsValid()
+                                                   ? anAspectMarker->SpriteHighlightRes (aCtx)
+                                                   : aSpriteNormRes;
+          aCtx->BindTextures (aSprite);
           aCtx->ShaderManager()->BindMarkerProgram (aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
         }
         else
         {
-          aCtx->ShaderManager()->BindMarkerProgram (NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
+          aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
         }
         break;
       }
@@ -772,12 +780,14 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
       }
       default:
       {
-        const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
+        const Handle(OpenGl_TextureSet)& aTextures = aCtx->ActiveTextures();
         const Standard_Boolean isLightOnFace = isLightOn
-                                            && (aTexture.IsNull()
-                                             || aTexture->GetParams()->IsModulate());
-        const Standard_Boolean toEnableEnvMap = (!aTexture.IsNull() && (aTexture == theWorkspace->EnvironmentTexture()));
-        aCtx->ShaderManager()->BindFaceProgram (aTexture,
+                                            && (aTextures.IsNull()
+                                             || aTextures->IsEmpty()
+                                             || aTextures->First().IsNull()
+                                             || aTextures->First()->Sampler()->Parameters()->IsModulate());
+        const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture()));
+        aCtx->ShaderManager()->BindFaceProgram (aTextures,
                                                 isLightOnFace,
                                                 hasVertColor,
                                                 toEnableEnvMap,
@@ -802,10 +812,12 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
     }
   #endif
 
-    if (!theWorkspace->ActiveTexture().IsNull()
+    if (!aCtx->ActiveTextures().IsNull()
+     && !aCtx->ActiveTextures()->IsEmpty()
+     && !aCtx->ActiveTextures()->First().IsNull()
      && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
     {
-      aCtx->SetTextureMatrix (theWorkspace->ActiveTexture()->GetParams());
+      aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters());
     }
 
     if (myDrawMode <= GL_LINE_STRIP)
@@ -862,7 +874,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
 
   if (myDrawMode <= GL_LINE_STRIP)
   {
-    theWorkspace->EnableTexture (aTextureBack);
+    aCtx->BindTextures (aTextureBack);
   }
   else
   {
index 802af35..4f1c0c3 100644 (file)
 // commercial license or contractual agreement.
 
 #include <OpenGl_Resource.hxx>
+#include <OpenGl_NamedResource.hxx>
 
-
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Resource,Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Resource, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_NamedResource, OpenGl_Resource)
 
 OpenGl_Resource::OpenGl_Resource() {}
 OpenGl_Resource::~OpenGl_Resource() {}
index 0dc8f9b..4ee9e5b 100644 (file)
 // commercial license or contractual agreement.
 
 #include <OpenGl_Sampler.hxx>
-#include <OpenGl_GlCore33.hxx>
-#include <Standard_Assert.hxx>
 
+#include <OpenGl_ArbSamplerObject.hxx>
+#include <OpenGl_Texture.hxx>
+#include <Standard_Assert.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource)
 
@@ -24,10 +25,16 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource)
 // function : OpenGl_Sampler
 // purpose  :
 // =======================================================================
-OpenGl_Sampler::OpenGl_Sampler()
-: mySamplerID (NO_SAMPLER)
+OpenGl_Sampler::OpenGl_Sampler (const Handle(Graphic3d_TextureParams)& theParams)
+: myParams (theParams),
+  mySamplerRevision (0),
+  mySamplerID (NO_SAMPLER),
+  myIsImmutable (false)
 {
-  //
+  if (myParams.IsNull())
+  {
+    myParams = new Graphic3d_TextureParams();
+  }
 }
 
 // =======================================================================
@@ -43,64 +50,86 @@ OpenGl_Sampler::~OpenGl_Sampler()
 // function : Release
 // purpose  :
 // =======================================================================
-void OpenGl_Sampler::Release (OpenGl_Context* theContext)
+void OpenGl_Sampler::Release (OpenGl_Context* theCtx)
 {
-  if (isValidSampler())
+  myIsImmutable = false;
+  mySamplerRevision = myParams->SamplerRevision() - 1;
+  if (!isValidSampler())
   {
-    // application can not handle this case by exception - this is bug in code
-    Standard_ASSERT_RETURN (theContext != NULL,
-      "OpenGl_Sampler destroyed without GL context! Possible GPU memory leakage...",);
+    return;
+  }
 
-    if (theContext->IsValid())
-    {
-    #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
-      theContext->core33->glDeleteSamplers (1, &mySamplerID);
-    #endif
-    }
+  // application can not handle this case by exception - this is bug in code
+  Standard_ASSERT_RETURN (theCtx != NULL,
+    "OpenGl_Sampler destroyed without GL context! Possible GPU memory leakage...",);
 
-    mySamplerID = NO_SAMPLER;
+  if (theCtx->IsValid())
+  {
+    theCtx->arbSamplerObject->glDeleteSamplers (1, &mySamplerID);
   }
+
+  mySamplerID = NO_SAMPLER;
 }
 
 // =======================================================================
-// function : Init
-// purpose  : Initializes sampler object
+// function : Create
+// purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_Sampler::Init (OpenGl_Context& theContext)
+Standard_Boolean OpenGl_Sampler::Create (const Handle(OpenGl_Context)& theCtx)
 {
-  if (theContext.core33 == NULL)
+  if (isValidSampler())
+  {
+    return Standard_True;
+  }
+  else if (theCtx->arbSamplerObject == NULL)
   {
     return Standard_False;
   }
 
+  theCtx->arbSamplerObject->glGenSamplers (1, &mySamplerID);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_Sampler::Init (const Handle(OpenGl_Context)& theCtx,
+                                       const OpenGl_Texture& theTexture)
+{
   if (isValidSampler())
   {
-    Release (&theContext);
+    if (!ToUpdateParameters())
+    {
+      return Standard_True;
+    }
+    else if (!myIsImmutable)
+    {
+      applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.HasMipmaps());
+      return Standard_True;
+    }
+    Release (theCtx.get());
+  }
+
+  if (!Create (theCtx))
+  {
+    return Standard_False;
   }
 
-#if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
-  theContext.core33->glGenSamplers (1, &mySamplerID);
+  applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.HasMipmaps());
   return Standard_True;
-#else
-  return Standard_False;
-#endif
 }
 
 // =======================================================================
 // function : Bind
 // purpose  : Binds sampler object to the given texture unit
 // =======================================================================
-void OpenGl_Sampler::Bind (OpenGl_Context& theContext,
-                           const GLuint    theUnit)
+void OpenGl_Sampler::Bind (const Handle(OpenGl_Context)& theCtx,
+                           const Graphic3d_TextureUnit   theUnit)
 {
   if (isValidSampler())
   {
-  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
-    theContext.core33->glBindSampler (theUnit, mySamplerID);
-  #else
-    (void )theContext;
-    (void )theUnit;
-  #endif
+    theCtx->arbSamplerObject->glBindSampler (theUnit, mySamplerID);
   }
 }
 
@@ -108,36 +137,295 @@ void OpenGl_Sampler::Bind (OpenGl_Context& theContext,
 // function : Unbind
 // purpose  : Unbinds sampler object from the given texture unit
 // =======================================================================
-void OpenGl_Sampler::Unbind (OpenGl_Context& theContext,
-                             const GLuint    theUnit)
+void OpenGl_Sampler::Unbind (const Handle(OpenGl_Context)& theCtx,
+                             const Graphic3d_TextureUnit   theUnit)
 {
   if (isValidSampler())
   {
-  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
-    theContext.core33->glBindSampler (theUnit, NO_SAMPLER);
-  #else
-    (void )theContext;
-    (void )theUnit;
-  #endif
+    theCtx->arbSamplerObject->glBindSampler (theUnit, NO_SAMPLER);
   }
 }
 
 // =======================================================================
-// function : SetParameter
-// purpose  : Sets sampler parameters
+// function : setParameter
+// purpose  :
 // =======================================================================
-void OpenGl_Sampler::SetParameter (OpenGl_Context& theContext,
-                                   const GLenum    theParam,
-                                   const GLint     theValue)
+void OpenGl_Sampler::setParameter (const Handle(OpenGl_Context)& theCtx,
+                                   OpenGl_Sampler* theSampler,
+                                   GLenum theTarget,
+                                   GLenum theParam,
+                                   GLint  theValue)
 {
-  if (isValidSampler())
+  if (theSampler != NULL && theSampler->isValidSampler())
+  {
+    theCtx->arbSamplerObject->glSamplerParameteri (theSampler->mySamplerID, theParam, theValue);
+  }
+  else
+  {
+    theCtx->core11fwd->glTexParameteri (theTarget, theParam, theValue);
+  }
+}
+
+// =======================================================================
+// function : SetParameters
+// purpose  :
+// =======================================================================
+void OpenGl_Sampler::SetParameters (const Handle(Graphic3d_TextureParams)& theParams)
+{
+  if (myParams != theParams)
+  {
+    myParams = theParams;
+    mySamplerRevision = myParams->SamplerRevision() - 1;
+  }
+}
+
+// =======================================================================
+// function : applySamplerParams
+// purpose  :
+// =======================================================================
+void OpenGl_Sampler::applySamplerParams (const Handle(OpenGl_Context)& theCtx,
+                                         const Handle(Graphic3d_TextureParams)& theParams,
+                                         OpenGl_Sampler* theSampler,
+                                         const GLenum theTarget,
+                                         const bool theHasMipMaps)
+{
+  if (theSampler != NULL && theSampler->Parameters() == theParams)
+  {
+    theSampler->mySamplerRevision = theParams->SamplerRevision();
+  }
+
+  // setup texture filtering
+  const GLenum aFilter = (theParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
+  GLenum aFilterMin = aFilter;
+  if (theHasMipMaps)
+  {
+    aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
+    if (theParams->Filter() == Graphic3d_TOTF_BILINEAR)
+    {
+      aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
+    }
+    else if (theParams->Filter() == Graphic3d_TOTF_TRILINEAR)
+    {
+      aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
+    }
+  }
+
+  setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MIN_FILTER, aFilterMin);
+  setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAG_FILTER, aFilter);
+
+  // setup texture wrapping
+  const GLenum aWrapMode = theParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
+  setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_S, aWrapMode);
+#if !defined(GL_ES_VERSION_2_0)
+  if (theTarget == GL_TEXTURE_1D)
   {
-  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
-    theContext.core33->glSamplerParameteri (mySamplerID, theParam, theValue);
-  #else
-    (void )theContext;
-    (void )theParam;
-    (void )theValue;
-  #endif
+    return;
   }
+#endif
+  setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_T, aWrapMode);
+  if (theTarget == GL_TEXTURE_3D)
+  {
+    setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode);
+    return;
+  }
+
+  if (theCtx->extAnis)
+  {
+    // setup degree of anisotropy filter
+    const GLint aMaxDegree = theCtx->MaxDegreeOfAnisotropy();
+    GLint aDegree;
+    switch (theParams->AnisoFilter())
+    {
+      case Graphic3d_LOTA_QUALITY:
+      {
+        aDegree = aMaxDegree;
+        break;
+      }
+      case Graphic3d_LOTA_MIDDLE:
+      {
+        aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
+        break;
+      }
+      case Graphic3d_LOTA_FAST:
+      {
+        aDegree = 2;
+        break;
+      }
+      case Graphic3d_LOTA_OFF:
+      default:
+      {
+        aDegree = 1;
+        break;
+      }
+    }
+
+    setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
+  }
+}
+
+// =======================================================================
+// function : applyGlobalTextureParams
+// purpose  :
+// =======================================================================
+void OpenGl_Sampler::applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
+                                               const OpenGl_Texture& theTexture,
+                                               const Handle(Graphic3d_TextureParams)& theParams)
+{
+#if defined(GL_ES_VERSION_2_0)
+  (void )theCtx;
+  (void )theTexture;
+  (void )theParams;
+#else
+  if (theCtx->core11 == NULL)
+  {
+    return;
+  }
+
+  GLint anEnvMode = GL_MODULATE; // lighting mode
+  if (!theParams->IsModulate())
+  {
+    anEnvMode = GL_DECAL;
+    if (theTexture.GetFormat() == GL_ALPHA
+     || theTexture.GetFormat() == GL_LUMINANCE)
+    {
+      anEnvMode = GL_REPLACE;
+    }
+  }
+
+  // setup generation of texture coordinates
+  switch (theParams->GenMode())
+  {
+    case Graphic3d_TOTM_OBJECT:
+    {
+      theCtx->core11->glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+      theCtx->core11->glTexGenfv (GL_S, GL_OBJECT_PLANE,     theParams->GenPlaneS().GetData());
+      if (theTexture.GetTarget() != GL_TEXTURE_1D)
+      {
+        theCtx->core11->glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+        theCtx->core11->glTexGenfv (GL_T, GL_OBJECT_PLANE,     theParams->GenPlaneT().GetData());
+      }
+      break;
+    }
+    case Graphic3d_TOTM_SPHERE:
+    {
+      theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+      if (theTexture.GetTarget() != GL_TEXTURE_1D)
+      {
+        theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+      }
+      break;
+    }
+    case Graphic3d_TOTM_EYE:
+    {
+      theCtx->WorldViewState.Push();
+      theCtx->WorldViewState.SetIdentity();
+      theCtx->ApplyWorldViewMatrix();
+
+      theCtx->core11->glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+      theCtx->core11->glTexGenfv (GL_S, GL_EYE_PLANE,        theParams->GenPlaneS().GetData());
+      if (theTexture.GetTarget() != GL_TEXTURE_1D)
+      {
+        theCtx->core11->glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+        theCtx->core11->glTexGenfv (GL_T, GL_EYE_PLANE,        theParams->GenPlaneT().GetData());
+      }
+
+      theCtx->WorldViewState.Pop();
+      break;
+    }
+    case Graphic3d_TOTM_SPRITE:
+    {
+      if (theCtx->core20fwd != NULL)
+      {
+        theCtx->core11fwd->glEnable (GL_POINT_SPRITE);
+        glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+        anEnvMode = GL_REPLACE;
+      }
+      break;
+    }
+    case Graphic3d_TOTM_MANUAL:
+    default: break;
+  }
+
+  // setup lighting
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
+
+  switch (theTexture.GetTarget())
+  {
+    case GL_TEXTURE_1D:
+    {
+      if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
+      {
+        theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
+      }
+      theCtx->core11fwd->glEnable (GL_TEXTURE_1D);
+      break;
+    }
+    case GL_TEXTURE_2D:
+    {
+      if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
+      {
+        theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
+        theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T);
+      }
+      theCtx->core11fwd->glEnable (GL_TEXTURE_2D);
+      break;
+    }
+    default: break;
+  }
+#endif
+}
+
+// =======================================================================
+// function : resetGlobalTextureParams
+// purpose  :
+// =======================================================================
+void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
+                                               const OpenGl_Texture& theTexture,
+                                               const Handle(Graphic3d_TextureParams)& theParams)
+{
+#if defined(GL_ES_VERSION_2_0)
+  (void )theCtx;
+  (void )theTexture;
+  (void )theParams;
+#else
+  if (theCtx->core11 == NULL)
+  {
+    return;
+  }
+
+  // reset texture matrix because some code may expect it is identity
+  GLint aMatrixMode = GL_TEXTURE;
+  theCtx->core11fwd->glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
+  theCtx->core11->glMatrixMode (GL_TEXTURE);
+  theCtx->core11->glLoadIdentity();
+  theCtx->core11->glMatrixMode (aMatrixMode);
+
+  switch (theTexture.GetTarget())
+  {
+    case GL_TEXTURE_1D:
+    {
+      if (theParams->GenMode() != GL_NONE)
+      {
+        theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
+      }
+      theCtx->core11fwd->glDisable (GL_TEXTURE_1D);
+      break;
+    }
+    case GL_TEXTURE_2D:
+    {
+      if (theParams->GenMode() != GL_NONE)
+      {
+        theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
+        theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_T);
+        if (theParams->GenMode() == Graphic3d_TOTM_SPRITE)
+        {
+          theCtx->core11fwd->glDisable (GL_POINT_SPRITE);
+        }
+      }
+      theCtx->core11fwd->glDisable (GL_TEXTURE_2D);
+      break;
+    }
+    default: break;
+  }
+#endif
 }
index 83a7a86..af740e4 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#ifndef OPENGL_SAMPLER_H
-#define OPENGL_SAMPLER_H
+#ifndef _OpenGl_Sampler_Header
+#define _OpenGl_Sampler_Header
 
 #include <OpenGl_Context.hxx>
+#include <OpenGl_Resource.hxx>
 
-class OpenGl_Sampler;
-DEFINE_STANDARD_HANDLE(OpenGl_Sampler, OpenGl_Resource)
+class OpenGl_Texture;
 
 //! Class implements OpenGL sampler object resource that
 //! stores the sampling parameters for a texture access.
 class OpenGl_Sampler : public OpenGl_Resource
 {
+  friend class OpenGl_Context;
+  friend class OpenGl_Texture;
+  DEFINE_STANDARD_RTTIEXT(OpenGl_Sampler, OpenGl_Resource)
 public:
 
   //! Helpful constant defining invalid sampler identifier
@@ -33,7 +36,7 @@ public:
 public:
 
   //! Creates new sampler object.
-  Standard_EXPORT OpenGl_Sampler();
+  Standard_EXPORT OpenGl_Sampler (const Handle(Graphic3d_TextureParams)& theParams);
 
   //! Releases resources of sampler object.
   Standard_EXPORT virtual ~OpenGl_Sampler();
@@ -41,8 +44,14 @@ public:
   //! Destroys object - will release GPU memory if any.
   Standard_EXPORT virtual void Release (OpenGl_Context* theContext) Standard_OVERRIDE;
 
-  //! Initializes sampler object.
-  Standard_EXPORT Standard_Boolean Init (OpenGl_Context& theContext);
+  //! Creates an uninitialized sampler object.
+  Standard_EXPORT Standard_Boolean Create (const Handle(OpenGl_Context)& theContext);
+
+  //! Creates and initializes sampler object.
+  //! Existing object will be reused if possible, however if existing Sampler Object has Immutable flag
+  //! and texture parameters should be re-initialized, then Sampler Object will be recreated.
+  Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theContext,
+                                         const OpenGl_Texture& theTexture);
 
   //! Returns true if current object was initialized.
   Standard_Boolean IsValid() const
@@ -50,14 +59,34 @@ public:
     return isValidSampler();
   }
 
+  //! Binds sampler object to texture unit specified in parameters.
+  void Bind (const Handle(OpenGl_Context)& theCtx)
+  {
+    Bind (theCtx, myParams->TextureUnit());
+  }
+
+  //! Unbinds sampler object from texture unit specified in parameters.
+  void Unbind (const Handle(OpenGl_Context)& theCtx)
+  {
+    Unbind (theCtx, myParams->TextureUnit());
+  }
+
   //! Binds sampler object to the given texture unit.
-  Standard_EXPORT void Bind (OpenGl_Context& theContext, const GLuint theUnit = 0);
+  Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx,
+                             const Graphic3d_TextureUnit   theUnit);
 
   //! Unbinds sampler object from the given texture unit.
-  Standard_EXPORT void Unbind (OpenGl_Context& theContext, const GLuint theUnit = 0);
+  Standard_EXPORT void Unbind (const Handle(OpenGl_Context)& theCtx,
+                               const Graphic3d_TextureUnit   theUnit);
 
   //! Sets specific sampler parameter.
-  Standard_EXPORT void SetParameter (OpenGl_Context& theContext, const GLenum theParam, const GLint theValue);
+  void SetParameter (const Handle(OpenGl_Context)& theCtx,
+                     GLenum theTarget,
+                     GLenum theParam,
+                     GLint  theValue)
+  {
+    setParameter (theCtx, this, theTarget, theParam, theValue);
+  }
 
   //! Returns OpenGL sampler ID.
   GLuint SamplerID() const
@@ -65,6 +94,22 @@ public:
     return mySamplerID;
   }
 
+  //! Return immutable flag preventing further modifications of sampler parameters, FALSE by default.
+  //! Immutable flag might be set when Sampler Object is used within Bindless Texture.
+  bool IsImmutable() const { return myIsImmutable; }
+
+  //! Setup immutable flag. It is not possible unsetting this flag without Sampler destruction.
+  void SetImmutable() { myIsImmutable = true; }
+
+  //! Returns texture parameters.
+  const Handle(Graphic3d_TextureParams)& Parameters() { return myParams; }
+
+  //! Sets texture parameters.
+  Standard_EXPORT void SetParameters (const Handle(Graphic3d_TextureParams)& theParams);
+
+  //! Returns texture parameters initialization state.
+  bool ToUpdateParameters() const { return mySamplerRevision != myParams->SamplerRevision(); }
+
 protected:
 
   //! Checks if sampler object is valid.
@@ -73,14 +118,41 @@ protected:
     return mySamplerID != NO_SAMPLER;
   }
 
-protected:
-
-  GLuint mySamplerID; //!< OpenGL sampler object ID
+  //! Sets specific sampler parameter.
+  Standard_EXPORT static void setParameter (const Handle(OpenGl_Context)& theContext,
+                                            OpenGl_Sampler* theSampler,
+                                            GLenum theTarget,
+                                            GLenum theParam,
+                                            GLint  theValue);
+
+  //! Apply sampler parameters.
+  //! If Sampler Object is not NULL and valid resource, the parameters will be set to it (and it is not required Sampler Object being bound).
+  //! Otherwise, parameters will be applied to currently bound Texture object.
+  Standard_EXPORT static void applySamplerParams (const Handle(OpenGl_Context)& theCtx,
+                                                  const Handle(Graphic3d_TextureParams)& theParams,
+                                                  OpenGl_Sampler* theSampler,
+                                                  const GLenum theTarget,
+                                                  const bool theHasMipMaps);
+
+  //! Apply global texture state for deprecated OpenGL functionality.
+  Standard_EXPORT static void applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
+                                                        const OpenGl_Texture& theTexture,
+                                                        const Handle(Graphic3d_TextureParams)& theParams);
+
+  //! Reset global texture state for deprecated OpenGL functionality.
+  Standard_EXPORT static void resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
+                                                        const OpenGl_Texture& theTexture,
+                                                        const Handle(Graphic3d_TextureParams)& theParams);
 
-public:
+protected:
 
-  DEFINE_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource)
+  Handle(Graphic3d_TextureParams) myParams;          //!< texture parameters
+  unsigned int                    mySamplerRevision; //!< modification counter of parameters related to sampler state
+  GLuint                          mySamplerID;       //!< OpenGL sampler object ID
+  bool                            myIsImmutable;     //!< immutable flag preventing further modifications of sampler parameters, FALSE by default
 
 };
 
-#endif // OPENGL_SAMPLER_H
+DEFINE_STANDARD_HANDLE(OpenGl_Sampler, OpenGl_Resource)
+
+#endif // _OpenGl_Sampler_Header
index 6f92d70..6b72d90 100644 (file)
@@ -439,7 +439,7 @@ OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNo
 // function : AcquireTextures
 // purpose  : Makes the OpenGL texture handles resident
 // =======================================================================
-Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_Context)& theContext) const
+Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_Context)& theContext)
 {
   if (theContext->arbTexBindless == NULL)
   {
@@ -447,15 +447,39 @@ Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_C
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  Standard_Integer aTexIter = 0;
+  for (NCollection_Vector<Handle(OpenGl_Texture)>::Iterator aTexSrcIter (myTextures); aTexSrcIter.More(); aTexSrcIter.Next(), ++aTexIter)
   {
-    theContext->arbTexBindless->glMakeTextureHandleResidentARB (myTextureHandles[anIdx]);
+    GLuint64& aHandle = myTextureHandles[aTexIter];
+    const Handle(OpenGl_Texture)& aTexture = aTexSrcIter.Value();
+    if (!aTexture->Sampler()->IsValid()
+     || !aTexture->Sampler()->IsImmutable())
+    {
+      // need to recreate texture sampler handle
+      aHandle = GLuint64(-1); // specs do not define value for invalid handle, set -1 to initialize something
+      if (!aTexture->InitSamplerObject (theContext))
+      {
+        continue;
+      }
 
-    if (glGetError() != GL_NO_ERROR)
+      aTexture->Sampler()->SetImmutable();
+      aHandle = theContext->arbTexBindless->glGetTextureSamplerHandleARB (aTexture->TextureId(), aTexture->Sampler()->SamplerID());
+      const GLenum anErr = glGetError();
+      if (anErr != GL_NO_ERROR)
+      {
+        theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                                 TCollection_AsciiString ("Error: Failed to get 64-bit handle of OpenGL texture #") + int(anErr));
+        myTextureHandles.clear();
+        return Standard_False;
+      }
+    }
+
+    theContext->arbTexBindless->glMakeTextureHandleResidentARB (aHandle);
+    const GLenum anErr = glGetError();
+    if (anErr != GL_NO_ERROR)
     {
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to make OpenGL texture resident" << std::endl;
-#endif
+      theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                               TCollection_AsciiString ("Error: Failed to make OpenGL texture resident #") + int(anErr));
       return Standard_False;
     }
   }
@@ -476,15 +500,14 @@ Standard_Boolean OpenGl_RaytraceGeometry::ReleaseTextures (const Handle(OpenGl_C
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  for (size_t aTexIter = 0; aTexIter < myTextureHandles.size(); ++aTexIter)
   {
-    theContext->arbTexBindless->glMakeTextureHandleNonResidentARB (myTextureHandles[anIdx]);
-
-    if (glGetError() != GL_NO_ERROR)
+    theContext->arbTexBindless->glMakeTextureHandleNonResidentARB (myTextureHandles[aTexIter]);
+    const GLenum anErr = glGetError();
+    if (anErr != GL_NO_ERROR)
     {
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to make OpenGL texture non-resident" << std::endl;
-#endif
+      theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                               TCollection_AsciiString("Error: Failed to make OpenGL texture non-resident #") + int(anErr));
       return Standard_False;
     }
   }
@@ -531,33 +554,33 @@ Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(Ope
     return Standard_False;
   }
 
-  if (myTextureSampler.IsNull())
-  {
-    myTextureSampler = new OpenGl_Sampler();
-    myTextureSampler->Init (*theContext.operator->());
-    myTextureSampler->SetParameter (*theContext.operator->(), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    myTextureSampler->SetParameter (*theContext.operator->(), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    myTextureSampler->SetParameter (*theContext.operator->(), GL_TEXTURE_WRAP_S,     GL_REPEAT);
-    myTextureSampler->SetParameter (*theContext.operator->(), GL_TEXTURE_WRAP_T,     GL_REPEAT);
-  }
-
   myTextureHandles.clear();
+  myTextureHandles.resize (myTextures.Size());
 
 #if !defined(GL_ES_VERSION_2_0)
-  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  Standard_Integer aTexIter = 0;
+  for (NCollection_Vector<Handle(OpenGl_Texture)>::Iterator aTexSrcIter (myTextures); aTexSrcIter.More(); aTexSrcIter.Next(), ++aTexIter)
   {
-    const GLuint64 aHandle = theContext->arbTexBindless->glGetTextureSamplerHandleARB (
-      myTextures.Value (anIdx)->TextureId(), myTextureSampler->SamplerID());
+    GLuint64& aHandle = myTextureHandles[aTexIter];
+    aHandle = GLuint64(-1); // specs do not define value for invalid handle, set -1 to initialize something
 
-    if (glGetError() != GL_NO_ERROR)
+    const Handle(OpenGl_Texture)& aTexture = aTexSrcIter.Value();
+    if (!aTexture->Sampler()->IsValid()
+     && !aTexture->InitSamplerObject (theContext))
     {
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to get 64-bit handle of OpenGL texture" << std::endl;
-#endif
-      return Standard_False;
+      continue;
     }
 
-    myTextureHandles.push_back (aHandle);
+    aTexture->Sampler()->SetImmutable();
+    aHandle = theContext->arbTexBindless->glGetTextureSamplerHandleARB (aTexture->TextureId(), aTexture->Sampler()->SamplerID());
+    const GLenum anErr = glGetError();
+    if (anErr != GL_NO_ERROR)
+    {
+      theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                               TCollection_AsciiString ("Error: Failed to get 64-bit handle of OpenGL texture #") + int(anErr));
+      myTextureHandles.clear();
+      return Standard_False;
+    }
   }
 #endif
 
index d79f6d5..8fa64e2 100644 (file)
@@ -331,7 +331,7 @@ public: //! @name methods related to texture management
   Standard_Boolean UpdateTextureHandles (const Handle(OpenGl_Context)& theContext);
 
   //! Makes the OpenGL texture handles resident (must be called before using).
-  Standard_Boolean AcquireTextures (const Handle(OpenGl_Context)& theContext) const;
+  Standard_Boolean AcquireTextures (const Handle(OpenGl_Context)& theContext);
 
   //! Makes the OpenGL texture handles non-resident (must be called after using).
   Standard_Boolean ReleaseTextures (const Handle(OpenGl_Context)& theContext) const;
@@ -343,13 +343,9 @@ public: //! @name methods related to texture management
   }
 
   //! Releases OpenGL resources.
-  void ReleaseResources (const Handle(OpenGl_Context)& theContext)
+  void ReleaseResources (const Handle(OpenGl_Context)& )
   {
-    if (!myTextureSampler.IsNull())
-    {
-      myTextureSampler->Release (theContext.operator->());
-      myTextureSampler.Nullify();
-    }
+    //
   }
 
 public: //! @name auxiliary methods
@@ -369,7 +365,6 @@ public: //! @name auxiliary methods
 protected:
 
   NCollection_Vector<Handle(OpenGl_Texture)> myTextures;           //!< Array of texture maps shared between rendered objects
-  Handle(OpenGl_Sampler)                     myTextureSampler;     //!< Sampler object providing fixed sampling params for texures
   std::vector<GLuint64>                      myTextureHandles;     //!< Array of unique 64-bit texture handles obtained from OpenGL
   Standard_Integer                           myTopLevelTreeDepth;  //!< Depth of high-level scene BVH from last build
   Standard_Integer                           myBotLevelTreeDepth;  //!< Maximum depth of bottom-level scene BVHs from last build
index e3b5eca..e01e151 100644 (file)
@@ -1136,11 +1136,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
        EOL"}";
 
   TCollection_AsciiString
-    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
+    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
 #if !defined(GL_ES_VERSION_2_0)
   if (myContext->core11 == NULL)
   {
-    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
+    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
   }
 #endif
 
@@ -1243,8 +1243,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
   }
 
   myContext->BindProgram (myBlitProgram);
-  myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
-  myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
+  myBlitProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
+  myBlitProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
   myContext->BindProgram (NULL);
   return Standard_True;
 }
@@ -1331,8 +1331,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
   }
 
   myContext->BindProgram (aProgram);
-  aProgram->SetSampler (myContext, "uAccumTexture",  0);
-  aProgram->SetSampler (myContext, "uWeightTexture", 1);
+  aProgram->SetSampler (myContext, "uAccumTexture",  Graphic3d_TextureUnit_0);
+  aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
   myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
   return Standard_True;
 }
@@ -1343,12 +1343,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
 // =======================================================================
 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
 {
-  TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").a; }";
+  TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").a; }";
 #if !defined(GL_ES_VERSION_2_0)
   if (myContext->core11 == NULL
    && (theBits & OpenGl_PO_TextureA) != 0)
   {
-    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").r; }";
+    aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").r; }";
   }
 #else
   (void )theBits;
@@ -1391,7 +1391,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
     if ((theBits & OpenGl_PO_TextureRGB) != 0)
     {
       aSrcFragGetColor =
-        EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord "); }";
+        EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord "); }";
     }
 
     if (textureUsed (theBits))
@@ -1429,7 +1429,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
       aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
 
       aSrcFragGetColor =
-        EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
+        EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
     }
     else if ((theBits & OpenGl_PO_TextureEnv) != 0)
     {
@@ -1446,7 +1446,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
         EOL"  TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
 
       aSrcFragGetColor =
-        EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
+        EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
     }
   }
   if ((theBits & OpenGl_PO_VertColor) != 0)
@@ -1605,7 +1605,7 @@ TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TColl
       EOL"vec4 getColor(void)"
       EOL"{"
       EOL"  vec4 aColor = " + theBaseColorSrc + ";"
-      EOL"  aColor = occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ") * aColor;"
+      EOL"  aColor = occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ") * aColor;"
       EOL"  if (aColor.a <= 0.1) discard;"
       EOL"  return aColor;"
       EOL"}";
@@ -1745,7 +1745,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
         EOL"vec4 getColor(void)"
         EOL"{"
         EOL"  vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
-        EOL"  return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
+        EOL"  return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
         EOL"}";
     }
   }
@@ -1886,7 +1886,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
         EOL"vec4 getColor(void)"
         EOL"{"
         EOL"  vec4 aColor = " thePhongCompLight ";"
-        EOL"  return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
+        EOL"  return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
         EOL"}";
     }
   }
@@ -2200,8 +2200,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
   }
 
   myContext->BindProgram (theProgram);
-  theProgram->SetSampler (myContext, "uLeftSampler",  0);
-  theProgram->SetSampler (myContext, "uRightSampler", 1);
+  theProgram->SetSampler (myContext, "uLeftSampler",  Graphic3d_TextureUnit_0);
+  theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
   myContext->BindProgram (NULL);
   return Standard_True;
 }
index bba6b92..9e5d2f7 100644 (file)
@@ -83,8 +83,8 @@ public:
   Standard_EXPORT Standard_Boolean IsEmpty() const;
 
   //! Bind program for filled primitives rendering
-  Standard_Boolean BindFaceProgram (const Handle(OpenGl_Texture)&       theTexture,
-                                    const Standard_Boolean              theToLightOn,
+  Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures,
+                                    const Standard_Boolean           theToLightOn,
                                     const Standard_Boolean              theHasVertColor,
                                     const Standard_Boolean              theEnableEnvMap,
                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
@@ -95,13 +95,13 @@ public:
       return bindProgramWithState (theCustomProgram);
     }
 
-    const Standard_Integer        aBits    = getProgramBits (theTexture, theHasVertColor, theEnableEnvMap);
+    const Standard_Integer        aBits    = getProgramBits (theTextures, theHasVertColor, theEnableEnvMap);
     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theToLightOn, aBits);
     return bindProgramWithState (aProgram);
   }
 
   //! Bind program for line rendering
-  Standard_Boolean BindLineProgram (const Handle(OpenGl_Texture)&       theTexture,
+  Standard_Boolean BindLineProgram (const Handle(OpenGl_TextureSet)&    theTextures,
                                     const Standard_Boolean              theStipple,
                                     const Standard_Boolean              theToLightOn,
                                     const Standard_Boolean              theHasVertColor,
@@ -113,7 +113,7 @@ public:
       return bindProgramWithState (theCustomProgram);
     }
 
-    Standard_Integer aBits = getProgramBits (theTexture, theHasVertColor);
+    Standard_Integer aBits = getProgramBits (theTextures, theHasVertColor);
     if (theStipple)
     {
       aBits |= OpenGl_PO_StippleLine;
@@ -124,7 +124,7 @@ public:
   }
 
   //! Bind program for point rendering
-  Standard_Boolean BindMarkerProgram (const Handle(OpenGl_Texture)&       theTexture,
+  Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)&    theTextures,
                                       const Standard_Boolean              theToLightOn,
                                       const Standard_Boolean              theHasVertColor,
                                       const Handle(OpenGl_ShaderProgram)& theCustomProgram)
@@ -135,7 +135,7 @@ public:
       return bindProgramWithState (theCustomProgram);
     }
 
-    const Standard_Integer        aBits    = getProgramBits (theTexture, theHasVertColor) | OpenGl_PO_Point;
+    const Standard_Integer        aBits    = getProgramBits (theTextures, theHasVertColor) | OpenGl_PO_Point;
     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theToLightOn, aBits);
     return bindProgramWithState (aProgram);
   }
@@ -332,9 +332,9 @@ public:
 protected:
 
   //! Define program bits.
-  Standard_Integer getProgramBits (const Handle(OpenGl_Texture)& theTexture,
-                                   const Standard_Boolean        theHasVertColor,
-                                   const Standard_Boolean        theEnableEnvMap = Standard_False)
+  Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures,
+                                   const Standard_Boolean theHasVertColor,
+                                   const Standard_Boolean theEnableEnvMap = Standard_False)
 
   {
     Standard_Integer aBits = 0;
@@ -358,9 +358,11 @@ protected:
       // Environment map overwrites material texture
       aBits |= OpenGl_PO_TextureEnv;
     }
-    else if (!theTexture.IsNull())
+    else if (!theTextures.IsNull()
+          && !theTextures->IsEmpty()
+          && !theTextures->First().IsNull())
     {
-      aBits |= theTexture->IsAlpha() ? OpenGl_PO_TextureA : OpenGl_PO_TextureRGB;
+      aBits |= theTextures->First()->IsAlpha() ? OpenGl_PO_TextureA : OpenGl_PO_TextureRGB;
     }
     if (theHasVertColor)
     {
index 7d8fe6d..74344dd 100755 (executable)
@@ -35,7 +35,7 @@
   #include <malloc.h> // for alloca()
 #endif
 
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram,OpenGl_Resource)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
 
 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
 
@@ -63,7 +63,6 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
   "occLightSources",       // OpenGl_OCC_LIGHT_SOURCE_PARAMS
   "occLightAmbient",       // OpenGl_OCC_LIGHT_AMBIENT
 
-  "occActiveSampler",      // OpenGl_OCCT_ACTIVE_SAMPLER
   "occTextureEnable",      // OpenGl_OCCT_TEXTURE_ENABLE
   "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
   "occFrontMaterial",      // OpenGl_OCCT_FRONT_MATERIAL
@@ -128,7 +127,8 @@ void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&
 // purpose  : Creates uninitialized shader program
 // =======================================================================
 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
-: myProgramID (NO_PROGRAM),
+: OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : ""),
+  myProgramID (NO_PROGRAM),
   myProxy     (theProxy),
   myShareCount(1)
 {
@@ -360,18 +360,36 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
   }
 
   // set uniform defaults
-  const GLint aLocSampler   = GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER);
-  const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
-  if (aLocSampler   != INVALID_LOCATION
-   || aLocTexEnable != INVALID_LOCATION)
+  const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
+  theCtx->core20fwd->glUseProgram (myProgramID);
   {
-    const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
-    theCtx->core20fwd->glUseProgram (myProgramID);
-    SetUniform (theCtx, aLocSampler,   0); // GL_TEXTURE0
-    SetUniform (theCtx, aLocTexEnable, 0); // Off
-    theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
+    const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
+    if (aLocTexEnable != INVALID_LOCATION)
+    {
+      SetUniform (theCtx, aLocTexEnable, 0); // Off
+    }
+  }
+  {
+    const GLint aLocSampler = GetUniformLocation (theCtx, "occActiveSampler");
+    if (aLocSampler != INVALID_LOCATION)
+    {
+      SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
+    }
+  }
+
+  const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
+  const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
+  for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
+  {
+    const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
+    const GLint aLocSampler = GetUniformLocation (theCtx, aName.ToCString());
+    if (aLocSampler != INVALID_LOCATION)
+    {
+      SetUniform (theCtx, aLocSampler, aUnitIter);
+    }
   }
 
+  theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
   return Standard_True;
 }
 
@@ -1283,7 +1301,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
                                                    const GLchar*                 theName,
-                                                   const GLenum                  theTextureUnit)
+                                                   const Graphic3d_TextureUnit   theTextureUnit)
 {
   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
 }
@@ -1294,7 +1312,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
                                                    GLint                         theLocation,
-                                                   const GLenum                  theTextureUnit)
+                                                   const Graphic3d_TextureUnit   theTextureUnit)
 {
   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
   {
index 155845f..ea7dc6c 100755 (executable)
 
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_Matrix.hxx>
+#include <OpenGl_NamedResource.hxx>
 #include <OpenGl_ShaderObject.hxx>
 
 class OpenGl_ShaderProgram;
-DEFINE_STANDARD_HANDLE(OpenGl_ShaderProgram, OpenGl_Resource)
+DEFINE_STANDARD_HANDLE(OpenGl_ShaderProgram, OpenGl_NamedResource)
 
 //! The enumeration of OCCT-specific OpenGL/GLSL variables.
 enum OpenGl_StateVariable
@@ -58,7 +59,6 @@ enum OpenGl_StateVariable
   OpenGl_OCC_LIGHT_AMBIENT,
 
   // Material state
-  OpenGl_OCCT_ACTIVE_SAMPLER,
   OpenGl_OCCT_TEXTURE_ENABLE,
   OpenGl_OCCT_DISTINGUISH_MODE,
   OpenGl_OCCT_FRONT_MATERIAL,
@@ -77,8 +77,6 @@ enum OpenGl_StateVariable
   OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES
 };
 
-class OpenGl_ShaderProgram;
-
 //! Interface for generic setter of user-defined uniform variables.
 struct OpenGl_SetterInterface
 {
@@ -134,10 +132,11 @@ enum OpenGl_UniformStateType
 };
 
 //! Wrapper for OpenGL program object.
-class OpenGl_ShaderProgram : public OpenGl_Resource
+class OpenGl_ShaderProgram : public OpenGl_NamedResource
 {
   friend class OpenGl_View;
-
+  friend class OpenGl_ShaderManager;
+  DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
 public:
 
   //! Non-valid shader name.
@@ -521,12 +520,12 @@ public:
   //! Specifies the value of the sampler uniform variable.
   Standard_EXPORT Standard_Boolean SetSampler (const Handle(OpenGl_Context)& theCtx,
                                                const GLchar*                 theName,
-                                               const GLenum                  theTextureUnit);
+                                               const Graphic3d_TextureUnit   theTextureUnit);
 
   //! Specifies the value of the sampler uniform variable.
   Standard_EXPORT Standard_Boolean SetSampler (const Handle(OpenGl_Context)& theCtx,
                                                GLint                         theLocation,
-                                               const GLenum                  theTextureUnit);
+                                               const Graphic3d_TextureUnit   theTextureUnit);
 
 protected:
 
@@ -560,11 +559,6 @@ protected:
   //! Stores locations of OCCT state uniform variables.
   GLint myStateLocations[OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES];
 
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderProgram,OpenGl_Resource)
-  friend class OpenGl_ShaderManager;
-
 };
 
 template<class T>
index 9d4d15e..bfb9938 100644 (file)
@@ -67,16 +67,20 @@ public:
   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
   {
   #if !defined(GL_ES_VERSION_2_0)
-    // Apply line aspect
-    const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
+    const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+    if (aCtx->core11 == NULL)
+    {
+      return;
+    }
 
-    theWorkspace->GetGlContext()->BindProgram (Handle(OpenGl_ShaderProgram)());
-    theWorkspace->GetGlContext()->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
+    const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
+    aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
+    aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
 
     glDisable (GL_LIGHTING);
 
     // Use highlight colors
-    theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().GetData());
+    aCtx->core11->glColor3fv (theWorkspace->LineColor().GetData());
 
     glEnableClientState (GL_VERTEX_ARRAY);
     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
@@ -86,7 +90,7 @@ public:
     // restore aspects
     if (!aPrevTexture.IsNull())
     {
-      theWorkspace->EnableTexture (aPrevTexture);
+      aCtx->BindTextures (aPrevTexture);
     }
   #else
     (void )theWorkspace;
index 1219a76..9a8633f 100644 (file)
@@ -421,8 +421,8 @@ void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
   const OpenGl_AspectText*      aTextAspect  = theWorkspace->ApplyAspectText();
-  const Handle(OpenGl_Texture)  aPrevTexture = theWorkspace->DisableTexture();
   const Handle(OpenGl_Context)& aCtx         = theWorkspace->GetGlContext();
+  const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
 #if !defined(GL_ES_VERSION_2_0)
   const Standard_Integer aPrevPolygonMode  = aCtx->SetPolygonMode (GL_FILL);
   const bool             aPrevHatchingMode = aCtx->SetPolygonHatchEnabled (false);
@@ -444,7 +444,7 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
   // restore aspects
   if (!aPrevTexture.IsNull())
   {
-    theWorkspace->EnableTexture (aPrevTexture);
+    aCtx->BindTextures (aPrevTexture);
   }
 #if !defined(GL_ES_VERSION_2_0)
   aCtx->SetPolygonMode         (aPrevPolygonMode);
@@ -725,7 +725,7 @@ void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx,
   }
 
   // bind flat program
-  theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_Texture)(), Standard_False, Standard_False, Standard_False, Handle(OpenGl_ShaderProgram)());
+  theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Standard_False, Standard_False, Standard_False, Handle(OpenGl_ShaderProgram)());
 
 #if !defined(GL_ES_VERSION_2_0)
   if (theCtx->core11 != NULL
index 04bad58..fa0b87d 100644 (file)
 #include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_GlCore32.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <Graphic3d_TextureParams.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <Standard_Assert.hxx>
 #include <Image_PixMap.hxx>
 
-
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture,OpenGl_Resource)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
 
 //! Simple class to reset unpack alignment settings
 struct OpenGl_UnpackAlignmentSentry
@@ -49,8 +49,10 @@ struct OpenGl_UnpackAlignmentSentry
 // function : OpenGl_Texture
 // purpose  :
 // =======================================================================
-OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
-: OpenGl_Resource(),
+OpenGl_Texture::OpenGl_Texture (const TCollection_AsciiString& theResourceId,
+                                const Handle(Graphic3d_TextureParams)& theParams)
+: OpenGl_NamedResource (theResourceId),
+  mySampler (new OpenGl_Sampler (theParams)),
   myRevision (0),
   myTextureId (NO_TEXTURE),
   myTarget (GL_TEXTURE_2D),
@@ -59,13 +61,9 @@ OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams
   mySizeZ (0),
   myTextFormat (GL_RGBA),
   myHasMipmaps (Standard_False),
-  myIsAlpha    (false),
-  myParams     (theParams)
+  myIsAlpha    (false)
 {
-  if (myParams.IsNull())
-  {
-    myParams = new Graphic3d_TextureParams();
-  }
+  //
 }
 
 // =======================================================================
@@ -78,43 +76,24 @@ OpenGl_Texture::~OpenGl_Texture()
 }
 
 // =======================================================================
-// function : HasMipmaps
-// purpose  :
-// =======================================================================
-Standard_Boolean OpenGl_Texture::HasMipmaps() const
-{
-  return myHasMipmaps;
-}
-
-// =======================================================================
-// function : GetParams
-// purpose  :
-// =======================================================================
-const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
-{
-  return myParams;
-}
-
-// =======================================================================
-// function : SetParams
-// purpose  :
-// =======================================================================
-void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
-{
-  myParams = theParams;
-}
-
-// =======================================================================
 // function : Create
 // purpose  :
 // =======================================================================
-bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
+bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& theCtx)
 {
+  if (myTextureId != NO_TEXTURE)
+  {
+    return true;
+  }
+
+  theCtx->core11fwd->glGenTextures (1, &myTextureId);
   if (myTextureId == NO_TEXTURE)
   {
-    glGenTextures (1, &myTextureId);
+    return false;
   }
-  return myTextureId != NO_TEXTURE;
+
+  //mySampler->Create (theCtx); // do not create sampler object by default
+  return true;
 }
 
 // =======================================================================
@@ -123,6 +102,7 @@ bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
 // =======================================================================
 void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
 {
+  mySampler->Release (theGlCtx);
   if (myTextureId == NO_TEXTURE)
   {
     return;
@@ -141,16 +121,30 @@ void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
 }
 
 // =======================================================================
+// function : applyDefaultSamplerParams
+// purpose  :
+// =======================================================================
+void OpenGl_Texture::applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx)
+{
+  OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myHasMipmaps);
+  if (mySampler->IsValid() && !mySampler->IsImmutable())
+  {
+    OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myHasMipmaps);
+  }
+}
+
+// =======================================================================
 // function : Bind
 // purpose  :
 // =======================================================================
 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
-                           const GLenum theTextureUnit) const
+                           const Graphic3d_TextureUnit   theTextureUnit) const
 {
   if (theCtx->core15fwd != NULL)
   {
-    theCtx->core15fwd->glActiveTexture (theTextureUnit);
+    theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   }
+  mySampler->Bind (theCtx, theTextureUnit);
   glBindTexture (myTarget, myTextureId);
 }
 
@@ -159,16 +153,27 @@ void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
 // purpose  :
 // =======================================================================
 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
-                             const GLenum theTextureUnit) const
+                             const Graphic3d_TextureUnit   theTextureUnit) const
 {
   if (theCtx->core15fwd != NULL)
   {
-    theCtx->core15fwd->glActiveTexture (theTextureUnit);
+    theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   }
+  mySampler->Unbind (theCtx, theTextureUnit);
   glBindTexture (myTarget, NO_TEXTURE);
 }
 
 //=======================================================================
+//function : InitSamplerObject
+//purpose  :
+//=======================================================================
+bool OpenGl_Texture::InitSamplerObject (const Handle(OpenGl_Context)& theCtx)
+{
+  return myTextureId != NO_TEXTURE
+      && mySampler->Init (theCtx, *this);
+}
+
+//=======================================================================
 //function : GetDataFormat
 //purpose  :
 //=======================================================================
@@ -497,9 +502,6 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
   }
 #endif
 
-  const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
-  const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
-
 #if !defined(GL_ES_VERSION_2_0)
   GLint aTestWidth  = 0;
   GLint aTestHeight = 0;
@@ -530,9 +532,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
     {
     #if !defined(GL_ES_VERSION_2_0)
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
+      applyDefaultSamplerParams (theCtx);
       if (toPatchExisting)
       {
         glTexSubImage1D (GL_TEXTURE_1D, 0, 0,
@@ -579,10 +579,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
     case Graphic3d_TOT_2D:
     {
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
+      applyDefaultSamplerParams (theCtx);
       if (toPatchExisting)
       {
         glTexSubImage2D (GL_TEXTURE_2D, 0,
@@ -632,22 +629,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
     }
     case Graphic3d_TOT_2D_MIPMAP:
     {
-      GLenum aFilterMin = aFilter;
-      aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
-      if (myParams->Filter() == Graphic3d_TOTF_BILINEAR)
-      {
-        aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
-      }
-      else if (myParams->Filter() == Graphic3d_TOTF_TRILINEAR)
-      {
-        aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
-      }
-
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
+      applyDefaultSamplerParams (theCtx);
       if (toPatchExisting)
       {
         glTexSubImage2D (GL_TEXTURE_2D, 0,
@@ -839,14 +822,9 @@ bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
 
   const GLsizei aSizeX    = Min (theCtx->MaxTextureSize(), theSizeX);
   const GLsizei aSizeY    = Min (theCtx->MaxTextureSize(), theSizeY);
-  const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
-  const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
 
   Bind (theCtx);
-  glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
-  glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
-  glTexParameteri (myTarget, GL_TEXTURE_WRAP_S,     aWrapMode);
-  glTexParameteri (myTarget, GL_TEXTURE_WRAP_T,     aWrapMode);
+  applyDefaultSamplerParams (theCtx);
 
   const GLint anIntFormat = theFormat.Internal();
   myTextFormat = theFormat.Format();
@@ -988,16 +966,7 @@ bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
   }
 #endif
 
-  const GLenum aWrapMode = myParams->IsRepeat() ? GL_REPEAT :  theCtx->TextureWrapClamp();
-  const GLenum aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
-
-  glTexParameteri (myTarget, GL_TEXTURE_WRAP_S, aWrapMode);
-  glTexParameteri (myTarget, GL_TEXTURE_WRAP_T, aWrapMode);
-  glTexParameteri (myTarget, GL_TEXTURE_WRAP_R, aWrapMode);
-
-  glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
-  glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
-
+  applyDefaultSamplerParams (theCtx);
   theCtx->Functions()->glTexImage3D (myTarget,
                                      0,
                                      anIntFormat,
index e8e9b84..debbd6d 100644 (file)
 #define _OpenGl_Texture_H__
 
 #include <OpenGl_GlCore13.hxx>
-#include <OpenGl_Resource.hxx>
+#include <OpenGl_NamedResource.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <Graphic3d_TypeOfTexture.hxx>
+#include <Graphic3d_TextureUnit.hxx>
 
-class OpenGl_Context;
 class Graphic3d_TextureParams;
 class Image_PixMap;
 
@@ -279,13 +280,10 @@ private:
 
 };
 
-class OpenGl_Texture;
-DEFINE_STANDARD_HANDLE(OpenGl_Texture, OpenGl_Resource)
-
 //! Texture resource.
-class OpenGl_Texture : public OpenGl_Resource
+class OpenGl_Texture : public OpenGl_NamedResource
 {
-
+  DEFINE_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
 public:
 
   //! Helpful constants
@@ -293,8 +291,9 @@ public:
 
 public:
 
-  //! Create uninitialized VBO.
-  Standard_EXPORT OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams = NULL);
+  //! Create uninitialized texture.
+  Standard_EXPORT OpenGl_Texture (const TCollection_AsciiString& theResourceId = TCollection_AsciiString(),
+                                  const Handle(Graphic3d_TextureParams)& theParams = Handle(Graphic3d_TextureParams)());
 
   //! Destroy object.
   Standard_EXPORT virtual ~OpenGl_Texture();
@@ -355,13 +354,39 @@ public:
   //! Destroy object - will release GPU memory if any.
   Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
 
+  //! Return texture sampler.
+  const Handle(OpenGl_Sampler)& Sampler() const { return mySampler; }
+
+  //! Set texture sampler.
+  void SetSampler (const Handle(OpenGl_Sampler)& theSampler) { mySampler = theSampler; }
+
+  //! Initialize the Sampler Object (as OpenGL object).
+  //! @param theCtx currently bound OpenGL context
+  Standard_EXPORT bool InitSamplerObject (const Handle(OpenGl_Context)& theCtx);
+
+  //! Bind this Texture to the unit specified in sampler parameters.
+  //! Also binds Sampler Object if it is allocated.
+  void Bind (const Handle(OpenGl_Context)& theCtx) const
+  {
+    Bind (theCtx, mySampler->Parameters()->TextureUnit());
+  }
+
+  //! Unbind texture from the unit specified in sampler parameters.
+  //! Also unbinds Sampler Object if it is allocated.
+  void Unbind (const Handle(OpenGl_Context)& theCtx) const
+  {
+    Unbind (theCtx, mySampler->Parameters()->TextureUnit());
+  }
+
   //! Bind this Texture to specified unit.
+  //! Also binds Sampler Object if it is allocated.
   Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx,
-                             const GLenum                  theTextureUnit = GL_TEXTURE0) const;
+                             const Graphic3d_TextureUnit   theTextureUnit) const;
 
   //! Unbind texture from specified unit.
+  //! Also unbinds Sampler Object if it is allocated.
   Standard_EXPORT void Unbind (const Handle(OpenGl_Context)& theCtx,
-                               const GLenum                  theTextureUnit = GL_TEXTURE0) const;
+                               const Graphic3d_TextureUnit   theTextureUnit) const;
 
   //! Revision of associated data source.
   Standard_Size Revision() const { return myRevision; }
@@ -411,13 +436,7 @@ public:
                                const void*                   thePixels);
 
   //! @return true if texture was generated within mipmaps
-  Standard_EXPORT Standard_Boolean HasMipmaps() const;
-
-  //! @return assigned texture parameters (not necessary applied)
-  Standard_EXPORT const Handle(Graphic3d_TextureParams)& GetParams() const;
-
-  //! @param texture parameters
-  Standard_EXPORT void SetParams (const Handle(Graphic3d_TextureParams)& theParams);
+  Standard_Boolean HasMipmaps() const { return myHasMipmaps; }
 
   //! Return texture type and format by Image_PixMap data format.
   Standard_EXPORT static bool GetDataFormat (const Handle(OpenGl_Context)& theCtx,
@@ -428,6 +447,12 @@ public:
 
 protected:
 
+  //! Apply default sampler parameters after texture creation.
+  Standard_EXPORT void applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx);
+
+protected:
+
+  Handle(OpenGl_Sampler) mySampler; //!< texture sampler
   Standard_Size    myRevision;   //!< revision of associated data source
   GLuint           myTextureId;  //!< GL resource ID
   GLenum           myTarget;     //!< GL_TEXTURE_1D/GL_TEXTURE_2D/GL_TEXTURE_3D
@@ -438,12 +463,8 @@ protected:
   Standard_Boolean myHasMipmaps; //!< flag indicates that texture was uploaded with mipmaps
   bool             myIsAlpha;    //!< indicates alpha format
 
-  Handle(Graphic3d_TextureParams) myParams; //!< texture parameters
-
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OpenGl_Texture,OpenGl_Resource) // Type definition
-
 };
 
+DEFINE_STANDARD_HANDLE(OpenGl_Texture, OpenGl_NamedResource)
+
 #endif // _OpenGl_Texture_H__
index b5e1d8b..38a14d1 100644 (file)
@@ -128,9 +128,9 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
   }
 
   Bind (theGlCtx);
-  BindTexture (theGlCtx);
+  BindTexture  (theGlCtx, Graphic3d_TextureUnit_0);
   theGlCtx->arbTBO->glTexBuffer (GetTarget(), myTexFormat, myBufferId);
-  UnbindTexture (theGlCtx);
+  UnbindTexture(theGlCtx, Graphic3d_TextureUnit_0);
   Unbind (theGlCtx);
   return true;
 }
@@ -174,9 +174,9 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
   }
 
   Bind (theGlCtx);
-  BindTexture (theGlCtx);
+  BindTexture  (theGlCtx, Graphic3d_TextureUnit_0);
   theGlCtx->arbTBO->glTexBuffer (GetTarget(), myTexFormat, myBufferId);
-  UnbindTexture (theGlCtx);
+  UnbindTexture(theGlCtx, Graphic3d_TextureUnit_0);
   Unbind (theGlCtx);
   return true;
 }
@@ -215,9 +215,9 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
   }
 
   Bind (theGlCtx);
-  BindTexture (theGlCtx);
+  BindTexture  (theGlCtx, Graphic3d_TextureUnit_0);
   theGlCtx->arbTBO->glTexBuffer (GetTarget(), myTexFormat, myBufferId);
-  UnbindTexture (theGlCtx);
+  UnbindTexture(theGlCtx, Graphic3d_TextureUnit_0);
   Unbind (theGlCtx);
   return true;
 }
@@ -256,9 +256,9 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
   }
 
   Bind (theGlCtx);
-  BindTexture (theGlCtx);
+  BindTexture  (theGlCtx, Graphic3d_TextureUnit_0);
   theGlCtx->arbTBO->glTexBuffer (GetTarget(), myTexFormat, myBufferId);
-  UnbindTexture (theGlCtx);
+  UnbindTexture(theGlCtx, Graphic3d_TextureUnit_0);
   Unbind (theGlCtx);
   return true;
 }
@@ -268,9 +268,9 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
 // purpose  :
 // =======================================================================
 void OpenGl_TextureBufferArb::BindTexture (const Handle(OpenGl_Context)& theGlCtx,
-                                           const GLenum theTextureUnit) const
+                                           const Graphic3d_TextureUnit   theTextureUnit) const
 {
-  theGlCtx->core20fwd->glActiveTexture (theTextureUnit);
+  theGlCtx->core20fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   glBindTexture (GetTarget(), myTextureId);
 }
 
@@ -279,8 +279,8 @@ void OpenGl_TextureBufferArb::BindTexture (const Handle(OpenGl_Context)& theGlCt
 // purpose  :
 // =======================================================================
 void OpenGl_TextureBufferArb::UnbindTexture (const Handle(OpenGl_Context)& theGlCtx,
-                                             const GLenum theTextureUnit) const
+                                             const Graphic3d_TextureUnit   theTextureUnit) const
 {
-  theGlCtx->core20fwd->glActiveTexture (theTextureUnit);
+  theGlCtx->core20fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   glBindTexture (GetTarget(), NO_TEXTURE);
 }
index 851640e..9193f84 100644 (file)
@@ -92,11 +92,11 @@ public:
 
   //! Bind TBO to specified Texture Unit.
   Standard_EXPORT void BindTexture (const Handle(OpenGl_Context)& theGlCtx,
-                                    const GLenum theTextureUnit = GL_TEXTURE0) const;
+                                    const Graphic3d_TextureUnit   theTextureUnit) const;
 
   //! Unbind TBO.
   Standard_EXPORT void UnbindTexture (const Handle(OpenGl_Context)& theGlCtx,
-                                      const GLenum theTextureUnit = GL_TEXTURE0) const;
+                                      const Graphic3d_TextureUnit   theTextureUnit) const;
 
 protected:
 
diff --git a/src/OpenGl/OpenGl_TextureSet.cxx b/src/OpenGl/OpenGl_TextureSet.cxx
new file mode 100644 (file)
index 0000000..c35315e
--- /dev/null
@@ -0,0 +1,17 @@
+// Created by: Kirill GAVRILOV
+// 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.
+
+#include <OpenGl_TextureSet.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient)
diff --git a/src/OpenGl/OpenGl_TextureSet.hxx b/src/OpenGl/OpenGl_TextureSet.hxx
new file mode 100644 (file)
index 0000000..3019e6a
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (c) 2017 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_TextureSet_Header
+#define _OpenGl_TextureSet_Header
+
+#include <Graphic3d_TextureSet.hxx>
+
+class OpenGl_Texture;
+
+//! Class holding array of textures to be mapped as a set.
+class OpenGl_TextureSet : public Standard_Transient
+{
+  DEFINE_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient)
+public:
+
+  //! Class for iterating texture set.
+  class Iterator : public NCollection_Array1<Handle(OpenGl_Texture)>::Iterator
+  {
+  public:
+    //! Empty constructor.
+    Iterator() {}
+
+    //! Constructor.
+    Iterator (const Handle(OpenGl_TextureSet)& theSet)
+    {
+      if (!theSet.IsNull())
+      {
+        NCollection_Array1<Handle(OpenGl_Texture)>::Iterator::Init (theSet->myTextures);
+      }
+    }
+  };
+
+public:
+
+  //! Empty constructor.
+  OpenGl_TextureSet() {}
+
+  //! Constructor.
+  OpenGl_TextureSet (Standard_Integer theNbTextures)
+  : myTextures (0, theNbTextures - 1) {}
+
+  //! Constructor for a single texture.
+  OpenGl_TextureSet (const Handle(OpenGl_Texture)& theTexture)
+  : myTextures (0, 0)
+  {
+    myTextures.ChangeFirst() = theTexture;
+  }
+
+  //! Return TRUE if texture array is empty.
+  Standard_Boolean IsEmpty() const { return myTextures.IsEmpty(); }
+
+  //! Return number of textures.
+  Standard_Integer Size() const { return myTextures.Size(); }
+
+  //! Return the lower index in texture set.
+  Standard_Integer Lower() const { return myTextures.Lower(); }
+
+  //! Return the upper index in texture set.
+  Standard_Integer Upper() const { return myTextures.Upper(); }
+
+  //! Return the first texture.
+  const Handle(OpenGl_Texture)& First() const { return myTextures.First(); }
+
+  //! Return the first texture.
+  Handle(OpenGl_Texture)& ChangeFirst() { return myTextures.ChangeFirst(); }
+
+  //! Return the texture at specified position within [0, Size()) range.
+  const Handle(OpenGl_Texture)& Value (Standard_Integer theIndex) const { return myTextures.Value (theIndex); }
+
+  //! Return the texture at specified position within [0, Size()) range.
+  Handle(OpenGl_Texture)& ChangeValue (Standard_Integer theIndex) { return myTextures.ChangeValue (theIndex); }
+
+protected:
+
+  NCollection_Array1<Handle(OpenGl_Texture)> myTextures;
+
+};
+
+#endif //_OpenGl_TextureSet_Header
index 41af8b0..4518242 100644 (file)
@@ -145,7 +145,11 @@ void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
 
   if (!myTextureEnv.IsNull())
   {
-    theCtx->DelayedRelease (myTextureEnv);
+    for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
+    {
+      theCtx->DelayedRelease (aTextureIter.ChangeValue());
+      aTextureIter.ChangeValue().Nullify();
+    }
     myTextureEnv.Nullify();
   }
 
@@ -227,7 +231,11 @@ void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureE
   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
   if (!aCtx.IsNull() && !myTextureEnv.IsNull())
   {
-    aCtx->DelayedRelease (myTextureEnv);
+    for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
+    {
+      aCtx->DelayedRelease (aTextureIter.ChangeValue());
+      aTextureIter.ChangeValue().Nullify();
+    }
   }
 
   myToUpdateEnvironmentMap = Standard_True;
@@ -249,11 +257,13 @@ void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
     return;
   }
 
-  myTextureEnv = new OpenGl_Texture (myTextureEnvData->GetParams());
+  myTextureEnv = new OpenGl_TextureSet (1);
+  Handle(OpenGl_Texture)& aTextureEnv = myTextureEnv->ChangeFirst();
+  aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams());
   Handle(Image_PixMap) anImage = myTextureEnvData->GetImage();
   if (!anImage.IsNull())
   {
-    myTextureEnv->Init (theContext, *anImage.operator->(), myTextureEnvData->Type());
+    aTextureEnv->Init (theContext, *anImage.operator->(), myTextureEnvData->Type());
   }
 }
 
index 0607e26..95adf31 100644 (file)
@@ -332,7 +332,7 @@ public:
   const Handle(OpenGl_Window) GlWindow() const { return myWindow; }
 
   //! Returns OpenGL environment map.
-  const Handle(OpenGl_Texture)& GlTextureEnv() const { return myTextureEnv; }
+  const Handle(OpenGl_TextureSet)& GlTextureEnv() const { return myTextureEnv; }
 
   //! Returns selector for BVH tree, providing a possibility to store information
   //! about current view volume and to detect which objects are overlapping it.
@@ -503,7 +503,7 @@ protected:
 
   OpenGl_GraduatedTrihedron myGraduatedTrihedron;
 
-  Handle(OpenGl_Texture) myTextureEnv;
+  Handle(OpenGl_TextureSet) myTextureEnv;
 
   //! Framebuffers for OpenGL output.
   Handle(OpenGl_FrameBuffer) myOpenGlFBO;
@@ -614,30 +614,6 @@ protected: //! @name data types related to ray-tracing
     OpenGl_RT_NbVariables // special field
   };
 
-  //! Defines OpenGL texture samplers.
-  enum ShaderSamplerNames
-  {
-    OpenGl_RT_EnvironmentMapTexture = 0,
-
-    OpenGl_RT_SceneNodeInfoTexture  = 1,
-    OpenGl_RT_SceneMinPointTexture  = 2,
-    OpenGl_RT_SceneMaxPointTexture  = 3,
-    OpenGl_RT_SceneTransformTexture = 4,
-
-    OpenGl_RT_GeometryVertexTexture = 5,
-    OpenGl_RT_GeometryNormalTexture = 6,
-    OpenGl_RT_GeometryTexCrdTexture = 7,
-    OpenGl_RT_GeometryTriangTexture = 8,
-
-    OpenGl_RT_RaytraceMaterialTexture = 9,
-    OpenGl_RT_RaytraceLightSrcTexture = 10,
-
-    OpenGl_RT_FsaaInputTexture = 11,
-    OpenGl_RT_PrevAccumTexture = 12,
-
-    OpenGl_RT_RaytraceDepthTexture = 13
-  };
-
   //! Defines OpenGL image samplers.
   enum ShaderImageNames
   {
index 0800cf9..04fcc20 100644 (file)
@@ -62,6 +62,30 @@ namespace
   };
 }
 
+namespace
+{
+  //! Defines OpenGL texture samplers.
+  static const Graphic3d_TextureUnit OpenGl_RT_EnvironmentMapTexture = Graphic3d_TextureUnit_0;
+
+  static const Graphic3d_TextureUnit OpenGl_RT_SceneNodeInfoTexture  = Graphic3d_TextureUnit_1;
+  static const Graphic3d_TextureUnit OpenGl_RT_SceneMinPointTexture  = Graphic3d_TextureUnit_2;
+  static const Graphic3d_TextureUnit OpenGl_RT_SceneMaxPointTexture  = Graphic3d_TextureUnit_3;
+  static const Graphic3d_TextureUnit OpenGl_RT_SceneTransformTexture = Graphic3d_TextureUnit_4;
+
+  static const Graphic3d_TextureUnit OpenGl_RT_GeometryVertexTexture = Graphic3d_TextureUnit_5;
+  static const Graphic3d_TextureUnit OpenGl_RT_GeometryNormalTexture = Graphic3d_TextureUnit_6;
+  static const Graphic3d_TextureUnit OpenGl_RT_GeometryTexCrdTexture = Graphic3d_TextureUnit_7;
+  static const Graphic3d_TextureUnit OpenGl_RT_GeometryTriangTexture = Graphic3d_TextureUnit_8;
+
+  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceMaterialTexture = Graphic3d_TextureUnit_9;
+  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceLightSrcTexture = Graphic3d_TextureUnit_10;
+
+  static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_11;
+  static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_12;
+
+  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_13;
+}
+
 // =======================================================================
 // function : updateRaytraceGeometry
 // purpose  : Updates 3D scene geometry for ray-tracing
@@ -289,6 +313,10 @@ Standard_Boolean OpenGl_View::toUpdateStructure (const OpenGl_Structure* theStru
 void buildTextureTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix)
 {
   theMatrix.InitIdentity();
+  if (theParams.IsNull())
+  {
+    return;
+  }
 
   // Apply scaling
   const Graphic3d_Vec2& aScale = theParams->Scale();
@@ -418,27 +446,37 @@ OpenGl_RaytraceMaterial OpenGl_View::convertMaterial (const OpenGl_AspectFace*
   theMaterial.BSDF.FresnelBase = aBSDF.FresnelBase.Serialize ();
 
   // Handle material textures
-  if (theAspect->Aspect()->ToMapTexture())
+  if (!theAspect->Aspect()->ToMapTexture())
   {
-    if (theGlContext->HasRayTracingTextures())
-    {
-      buildTextureTransform (theAspect->TextureParams(), theMaterial.TextureTransform);
+    return theMaterial;
+  }
 
-      // write texture ID to diffuse w-component
-      theMaterial.Diffuse.w() = theMaterial.BSDF.Kd.w() =
-        static_cast<Standard_ShortReal> (myRaytraceGeometry.AddTexture (theAspect->TextureRes (theGlContext)));
-    }
-    else if (!myIsRaytraceWarnTextures)
-    {
-      const TCollection_ExtendedString aWarnMessage =
-        "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
-        "Please try to update graphics card driver. At the moment textures will be ignored.";
+  const Handle(OpenGl_TextureSet)& aTextureSet = theAspect->TextureSet (theGlContext);
+  if (aTextureSet.IsNull()
+   || aTextureSet->IsEmpty()
+   || aTextureSet->First().IsNull())
+  {
+    return theMaterial;
+  }
 
-      theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
-        GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
+  if (theGlContext->HasRayTracingTextures())
+  {
+    const Handle(OpenGl_Texture)& aTexture = aTextureSet->First();
+    buildTextureTransform (aTexture->Sampler()->Parameters(), theMaterial.TextureTransform);
 
-      myIsRaytraceWarnTextures = Standard_True;
-    }
+    // write texture ID to diffuse w-component
+    theMaterial.Diffuse.w() = theMaterial.BSDF.Kd.w() = static_cast<Standard_ShortReal> (myRaytraceGeometry.AddTexture (aTexture));
+  }
+  else if (!myIsRaytraceWarnTextures)
+  {
+    const TCollection_ExtendedString aWarnMessage =
+      "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
+      "Please try to update graphics card driver. At the moment textures will be ignored.";
+
+    theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+      GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
+
+    myIsRaytraceWarnTextures = Standard_True;
   }
 
   return theMaterial;
@@ -2681,8 +2719,10 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
   }
 
   // Set environment map parameters
-  const Standard_Boolean toDisableEnvironmentMap = myTextureEnv.IsNull() || !myTextureEnv->IsValid();
-  
+  const Standard_Boolean toDisableEnvironmentMap = myTextureEnv.IsNull()
+                                               ||  myTextureEnv->IsEmpty()
+                                               || !myTextureEnv->First()->IsValid();
+
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uSphereMapEnabled], toDisableEnvironmentMap ? 0 : 1);
 
@@ -2748,21 +2788,23 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
 #endif
   }
 
-  if (!myTextureEnv.IsNull() && myTextureEnv->IsValid())
+  if (!myTextureEnv.IsNull()
+   && !myTextureEnv->IsEmpty()
+   &&  myTextureEnv->First()->IsValid())
   {
-    myTextureEnv->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
+    myTextureEnv->First()->Bind (theGlContext, OpenGl_RT_EnvironmentMapTexture);
   }
 
-  mySceneMinPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
-  mySceneMaxPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
-  mySceneNodeInfoTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
-  myGeometryVertexTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
-  myGeometryNormalTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
-  myGeometryTexCrdTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
-  myGeometryTriangTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
-  mySceneTransformTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
-  myRaytraceMaterialTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
-  myRaytraceLightSrcTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
+  mySceneMinPointTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneMinPointTexture);
+  mySceneMaxPointTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneMaxPointTexture);
+  mySceneNodeInfoTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneNodeInfoTexture);
+  myGeometryVertexTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryVertexTexture);
+  myGeometryNormalTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryNormalTexture);
+  myGeometryTexCrdTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryTexCrdTexture);
+  myGeometryTriangTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryTriangTexture);
+  mySceneTransformTexture  ->BindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
+  myRaytraceMaterialTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
+  myRaytraceLightSrcTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
 }
 
 // =======================================================================
@@ -2771,16 +2813,16 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
 // =======================================================================
 void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext)
 {
-  mySceneMinPointTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
-  mySceneMaxPointTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
-  mySceneNodeInfoTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
-  myGeometryVertexTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
-  myGeometryNormalTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
-  myGeometryTexCrdTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
-  myGeometryTriangTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
-  mySceneTransformTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
-  myRaytraceMaterialTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
-  myRaytraceLightSrcTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
+  mySceneMinPointTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneMinPointTexture);
+  mySceneMaxPointTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneMaxPointTexture);
+  mySceneNodeInfoTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneNodeInfoTexture);
+  myGeometryVertexTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryVertexTexture);
+  myGeometryNormalTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryNormalTexture);
+  myGeometryTexCrdTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryTexCrdTexture);
+  myGeometryTriangTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryTriangTexture);
+  mySceneTransformTexture  ->UnbindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
+  myRaytraceMaterialTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
+  myRaytraceLightSrcTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
 
   theGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
 }
@@ -2849,7 +2891,7 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSize
     glDisable (GL_DEPTH_TEST); // improve jagged edges without depth buffer
 
     // bind ray-tracing output image as input
-    myRaytraceFBO1[aFBOIdx]->ColorTexture()->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_FsaaInputTexture);
+    myRaytraceFBO1[aFBOIdx]->ColorTexture()->Bind (theGlContext, OpenGl_RT_FsaaInputTexture);
 
     aResult &= theGlContext->BindProgram (myPostFSAAProgram);
 
@@ -2900,7 +2942,7 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSize
       // perform adaptive FSAA pass
       theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
-      aFramebuffer->ColorTexture()->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_FsaaInputTexture);
+      aFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_FsaaInputTexture);
     }
 
     aRenderImageFramebuffer = myRaytraceFBO2[aFBOIdx];
@@ -2920,20 +2962,14 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSize
       aRenderImageFramebuffer->UnbindBuffer (theGlContext);
     }
 
-    aRenderImageFramebuffer->ColorTexture()->Bind (
-      theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
-
-    aDepthSourceFramebuffer->DepthStencilTexture()->Bind (
-      theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceDepthTexture);
+    aRenderImageFramebuffer->ColorTexture()       ->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
+    aDepthSourceFramebuffer->DepthStencilTexture()->Bind (theGlContext, OpenGl_RT_RaytraceDepthTexture);
 
     // copy the output image with depth values
     theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
-    aDepthSourceFramebuffer->DepthStencilTexture()->Unbind (
-      theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceDepthTexture);
-
-    aRenderImageFramebuffer->ColorTexture()->Unbind (
-      theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
+    aDepthSourceFramebuffer->DepthStencilTexture()->Unbind (theGlContext, OpenGl_RT_RaytraceDepthTexture);
+    aRenderImageFramebuffer->ColorTexture()       ->Unbind (theGlContext, OpenGl_RT_PrevAccumTexture);
   }
 
   unbindRaytraceTextures (theGlContext);
@@ -3011,8 +3047,7 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
 
   aDepthSourceFramebuffer = aRenderImageFramebuffer;
 
-  anAccumImageFramebuffer->ColorTexture()->Bind (
-    theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
+  anAccumImageFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
 
   aRenderImageFramebuffer->BindBuffer (theGlContext);
 
@@ -3105,16 +3140,14 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
     aRenderImageFramebuffer->UnbindBuffer (theGlContext);
   }
 
-  aRenderImageFramebuffer->ColorTexture()->Bind (
-    theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
+  aRenderImageFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
 
   glEnable (GL_DEPTH_TEST);
 
   // Copy accumulated image with correct depth values
   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
-  aRenderImageFramebuffer->ColorTexture()->Unbind (
-    theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
+  aRenderImageFramebuffer->ColorTexture()->Unbind (theGlContext, OpenGl_RT_PrevAccumTexture);
 
   if (myRaytraceParameters.AdaptiveScreenSampling)
   {
index 6ad77f0..5b6bb69 100644 (file)
@@ -974,7 +974,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
 
   renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate);
 
-  myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
+  myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
 
   // ===============================
   //      Step 4: Trihedron
@@ -1161,7 +1161,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
   }
 
   renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
-  myWorkspace->DisableTexture();
+  aContext->BindTextures (Handle(OpenGl_TextureSet)());
 
   // Apply restored view matrix.
   aContext->ApplyWorldViewMatrix();
@@ -1375,7 +1375,7 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer*    theReadFbo,
     }
   #endif
 
-    myWorkspace->DisableTexture();
+    aCtx->BindTextures (Handle(OpenGl_TextureSet)());
 
     const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR;
     const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR;
@@ -1385,18 +1385,18 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer*    theReadFbo,
     if (aVerts->IsValid()
      && aManager->BindFboBlitProgram())
     {
-      theReadFbo->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
-      if (theReadFbo->ColorTexture()->GetParams()->Filter() != aFilter)
+      theReadFbo->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0);
+      if (theReadFbo->ColorTexture()->Sampler()->Parameters()->Filter() != aFilter)
       {
-        theReadFbo->ColorTexture()->GetParams()->SetFilter (aFilter);
+        theReadFbo->ColorTexture()->Sampler()->Parameters()->SetFilter (aFilter);
         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl);
         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl);
       }
 
-      theReadFbo->DepthStencilTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
-      if (theReadFbo->DepthStencilTexture()->GetParams()->Filter() != aFilter)
+      theReadFbo->DepthStencilTexture()->Bind (aCtx, Graphic3d_TextureUnit_1);
+      if (theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->Filter() != aFilter)
       {
-        theReadFbo->DepthStencilTexture()->GetParams()->SetFilter (aFilter);
+        theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->SetFilter (aFilter);
         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl);
         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl);
       }
@@ -1406,8 +1406,8 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer*    theReadFbo,
       aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
 
       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
-      theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
-      theReadFbo->ColorTexture()       ->Unbind (aCtx, GL_TEXTURE0 + 0);
+      theReadFbo->DepthStencilTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1);
+      theReadFbo->ColorTexture()       ->Unbind (aCtx, Graphic3d_TextureUnit_0);
       aCtx->BindProgram (NULL);
     }
     else
@@ -1518,7 +1518,7 @@ void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
   aCtx->core20fwd->glDepthMask (GL_TRUE);
   aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
 
-  myWorkspace->DisableTexture();
+  aCtx->BindTextures (Handle(OpenGl_TextureSet)());
   OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
 
   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
@@ -1588,15 +1588,15 @@ void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
     }
 
-    aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
-    aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
+    aPair[0]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0);
+    aPair[1]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_1);
     aVerts->BindVertexAttrib (aCtx, 0);
 
     aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
 
     aVerts->UnbindVertexAttrib (aCtx, 0);
-    aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
-    aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0);
+    aPair[1]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1);
+    aPair[0]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_0);
   }
   else
   {
index a851580..a8a0238 100644 (file)
@@ -229,345 +229,6 @@ void OpenGl_Workspace::ResetAppliedAspect()
 }
 
 // =======================================================================
-// function : DisableTexture
-// purpose  :
-// =======================================================================
-Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
-{
-  if (myTextureBound.IsNull())
-  {
-    return myTextureBound;
-  }
-
-  const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
-  if (!aSampler.IsNull())
-  {
-    aSampler->Unbind (*myGlContext);
-  }
-
-#if !defined(GL_ES_VERSION_2_0)
-  // reset texture matrix because some code may expect it is identity
-  if (myGlContext->core11 != NULL)
-  {
-    GLint aMatrixMode = GL_TEXTURE;
-    glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
-    glMatrixMode (GL_TEXTURE);
-    glLoadIdentity();
-    glMatrixMode (aMatrixMode);
-  }
-#endif
-
-  myTextureBound->Unbind (myGlContext);
-  switch (myTextureBound->GetTarget())
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    case GL_TEXTURE_1D:
-    {
-      if (myGlContext->core11 != NULL)
-      {
-        if (myTextureBound->GetParams()->GenMode() != GL_NONE)
-        {
-          glDisable (GL_TEXTURE_GEN_S);
-        }
-        glDisable (GL_TEXTURE_1D);
-      }
-      break;
-    }
-  #endif
-    case GL_TEXTURE_2D:
-    {
-    #if !defined(GL_ES_VERSION_2_0)
-      if (myGlContext->core11 != NULL)
-      {
-        if (myTextureBound->GetParams()->GenMode() != GL_NONE)
-        {
-          glDisable (GL_TEXTURE_GEN_S);
-          glDisable (GL_TEXTURE_GEN_T);
-          if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
-          {
-            glDisable (GL_POINT_SPRITE);
-          }
-        }
-        glDisable (GL_TEXTURE_2D);
-      }
-    #endif
-      break;
-    }
-    default: break;
-  }
-
-  Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
-  myTextureBound.Nullify();
-  return aPrevTexture;
-}
-
-// =======================================================================
-// function : setTextureParams
-// purpose  :
-// =======================================================================
-void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
-                                         const Handle(Graphic3d_TextureParams)& theParams)
-{
-  const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
-  if (aParams.IsNull())
-  {
-    return;
-  }
-
-#if !defined(GL_ES_VERSION_2_0)
-  if (myGlContext->core11 != NULL)
-  {
-    GLint anEnvMode = GL_MODULATE; // lighting mode
-    if (!aParams->IsModulate())
-    {
-      anEnvMode = GL_DECAL;
-      if (theTexture->GetFormat() == GL_ALPHA
-       || theTexture->GetFormat() == GL_LUMINANCE)
-      {
-        anEnvMode = GL_REPLACE;
-      }
-    }
-
-    // setup generation of texture coordinates
-    switch (aParams->GenMode())
-    {
-      case Graphic3d_TOTM_OBJECT:
-      {
-        glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
-        glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
-        if (theTexture->GetTarget() != GL_TEXTURE_1D)
-        {
-          glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
-          glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
-        }
-        break;
-      }
-      case Graphic3d_TOTM_SPHERE:
-      {
-        glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-        if (theTexture->GetTarget() != GL_TEXTURE_1D)
-        {
-          glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-        }
-        break;
-      }
-      case Graphic3d_TOTM_EYE:
-      {
-        myGlContext->WorldViewState.Push();
-
-        myGlContext->WorldViewState.SetIdentity();
-        myGlContext->ApplyWorldViewMatrix();
-
-        glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
-
-        if (theTexture->GetTarget() != GL_TEXTURE_1D)
-        {
-          glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-          glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
-        }
-
-        myGlContext->WorldViewState.Pop();
-
-        break;
-      }
-      case Graphic3d_TOTM_SPRITE:
-      {
-        if (myGlContext->core20fwd != NULL)
-        {
-          glEnable  (GL_POINT_SPRITE);
-          glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
-          anEnvMode = GL_REPLACE;
-        }
-        break;
-      }
-      case Graphic3d_TOTM_MANUAL:
-      default: break;
-    }
-
-    // setup lighting
-    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
-  }
-#endif
-
-  // get active sampler object to override default texture parameters
-  const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
-
-  // setup texture filtering and wrapping
-  //if (theTexture->GetParams() != theParams)
-  const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
-  const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
-  switch (theTexture->GetTarget())
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    case GL_TEXTURE_1D:
-    {
-      if (aSampler.IsNull() || !aSampler->IsValid())
-      {
-        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
-        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
-        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
-      }
-      else
-      {
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
-      }
-
-      break;
-    }
-  #endif
-    case GL_TEXTURE_2D:
-    {
-      GLenum aFilterMin = aFilter;
-      if (theTexture->HasMipmaps())
-      {
-        aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
-        if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
-        {
-          aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
-        }
-        else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
-        {
-          aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
-        }
-
-        if (myGlContext->extAnis)
-        {
-          // setup degree of anisotropy filter
-          const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
-          GLint aDegree;
-          switch (aParams->AnisoFilter())
-          {
-            case Graphic3d_LOTA_QUALITY:
-            {
-              aDegree = aMaxDegree;
-              break;
-            }
-            case Graphic3d_LOTA_MIDDLE:
-            {
-              aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
-              break;
-            }
-            case Graphic3d_LOTA_FAST:
-            {
-              aDegree = 2;
-              break;
-            }
-            case Graphic3d_LOTA_OFF:
-            default:
-            {
-              aDegree = 1;
-              break;
-            }
-          }
-
-          if (aSampler.IsNull() || !aSampler->IsValid())
-          {
-            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
-          }
-          else
-          {
-            aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
-          }
-        }
-      }
-
-      if (aSampler.IsNull() || !aSampler->IsValid())
-      {
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
-      }
-      else
-      {
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
-        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
-      }
-
-      break;
-    }
-    default: break;
-  }
-
-  switch (theTexture->GetTarget())
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    case GL_TEXTURE_1D:
-    {
-      if (myGlContext->core11 != NULL)
-      {
-        if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
-        {
-          glEnable (GL_TEXTURE_GEN_S);
-        }
-        glEnable (GL_TEXTURE_1D);
-      }
-      break;
-    }
-  #endif
-    case GL_TEXTURE_2D:
-    {
-    #if !defined(GL_ES_VERSION_2_0)
-      if (myGlContext->core11 != NULL)
-      {
-        if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
-        {
-          glEnable (GL_TEXTURE_GEN_S);
-          glEnable (GL_TEXTURE_GEN_T);
-        }
-        glEnable (GL_TEXTURE_2D);
-      }
-    #endif
-      break;
-    }
-    default: break;
-  }
-
-  theTexture->SetParams (aParams);
-}
-
-// =======================================================================
-// function : EnableTexture
-// purpose  :
-// =======================================================================
-Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
-                                                        const Handle(Graphic3d_TextureParams)& theParams)
-{
-  if (theTexture.IsNull() || !theTexture->IsValid())
-  {
-    return DisableTexture();
-  }
-
-  if (myTextureBound == theTexture
-   && (theParams.IsNull() || theParams == theTexture->GetParams()))
-  {
-    // already bound
-    return myTextureBound;
-  }
-
-  Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
-  myTextureBound = theTexture;
-  myTextureBound->Bind (myGlContext);
-  setTextureParams (myTextureBound, theParams);
-
-  // If custom sampler object is available it will be
-  // used for overriding default texture parameters
-  const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
-
-  if (!aSampler.IsNull() && aSampler->IsValid())
-  {
-    aSampler->Bind (*myGlContext);
-  }
-
-  return aPrevTexture;
-}
-
-// =======================================================================
 // function : SetAspectLine
 // purpose  :
 // =======================================================================
@@ -716,20 +377,11 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
 
   if (myAspectFaceSet->Aspect()->ToMapTexture())
   {
-    EnableTexture (myAspectFaceSet->TextureRes (myGlContext),
-                   myAspectFaceSet->TextureParams());
+    myGlContext->BindTextures (myAspectFaceSet->TextureSet (myGlContext));
   }
   else
   {
-    if (!myEnvironmentTexture.IsNull())
-    {
-      EnableTexture (myEnvironmentTexture,
-                     myEnvironmentTexture->GetParams());
-    }
-    else
-    {
-      DisableTexture();
-    }
+    myGlContext->BindTextures (myEnvironmentTexture);
   }
 
   myAspectFaceApplied = myAspectFaceSet->Aspect();
@@ -836,10 +488,9 @@ Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer t
   if (!Activate())
     return Handle(OpenGl_FrameBuffer)();
 
-  DisableTexture();
-
   // create the FBO
   const Handle(OpenGl_Context)& aCtx = GetGlContext();
+  aCtx->BindTextures (Handle(OpenGl_TextureSet)());
   Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
   {
index 9086b01..7b1648f 100644 (file)
@@ -235,11 +235,6 @@ public:
   //! Clear the applied aspect state to default values.
   void ResetAppliedAspect();
 
-  Standard_EXPORT Handle(OpenGl_Texture) DisableTexture();
-  Standard_EXPORT Handle(OpenGl_Texture) EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
-                                                        const Handle(Graphic3d_TextureParams)& theParams = NULL);
-  const Handle(OpenGl_Texture)& ActiveTexture() const { return myTextureBound; }
-
   //! Set filter for restricting rendering of particular elements.
   //! Filter can be applied for rendering passes used by recursive
   //! rendering algorithms for rendering elements of groups.
@@ -287,21 +282,10 @@ public:
   }
 
   //! Sets a new environment texture.
-  void SetEnvironmentTexture (const Handle(OpenGl_Texture)& theTexture)
-  {
-    myEnvironmentTexture = theTexture;
-  }
+  void SetEnvironmentTexture (const Handle(OpenGl_TextureSet)& theTexture) { myEnvironmentTexture = theTexture; }
 
   //! Returns environment texture.
-  const Handle(OpenGl_Texture)& EnvironmentTexture() const
-  {
-    return myEnvironmentTexture;
-  }
-
-protected:
-
-  void setTextureParams (Handle(OpenGl_Texture)&                theTexture,
-                         const Handle(Graphic3d_TextureParams)& theParams);
+  const Handle(OpenGl_TextureSet)& EnvironmentTexture() const { return myEnvironmentTexture; }
 
 protected: //! @name protected fields
 
@@ -317,7 +301,6 @@ protected: //! @name protected fields
 protected: //! @name fields related to status
 
   Handle(OpenGl_RenderFilter) myRenderFilter;
-  Handle(OpenGl_Texture) myTextureBound;    //!< currently bound texture (managed by OpenGl_AspectFace and OpenGl_View environment texture)
   const OpenGl_AspectLine*   myAspectLineSet;
   const OpenGl_AspectFace*   myAspectFaceSet;
   Handle(Graphic3d_AspectFillArea3d) myAspectFaceApplied;
@@ -338,7 +321,7 @@ protected: //! @name fields related to status
 
   OpenGl_AspectFace myAspectFaceHl; //!< Hiddenline aspect
 
-  Handle(OpenGl_Texture) myEnvironmentTexture;
+  Handle(OpenGl_TextureSet) myEnvironmentTexture;
 
 public: //! @name type definition
 
index be565d0..efdfb2d 100644 (file)
@@ -118,10 +118,13 @@ vec4  occBackMaterial_Specular(void);      //!< Specular reflection
 float occBackMaterial_Shininess(void);     //!< Specular exponent
 float occBackMaterial_Transparency(void);  //!< Transparency coefficient
 
+#define occActiveSampler    occSampler0                //!< alias for backward compatibility
+#define occSamplerBaseColor occSampler0                //!< alias to a base color texture
+uniform               sampler2D occSampler0;           //!< current active sampler;
+                                                       //!  occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing
 uniform               vec4      occColor;              //!< color value (in case of disabled lighting)
 uniform THE_PREC_ENUM int       occDistinguishingMode; //!< Are front and back faces distinguished?
 uniform THE_PREC_ENUM int       occTextureEnable;      //!< Is texture enabled?
-uniform               sampler2D occActiveSampler;      //!< Current active sampler
 uniform               vec4      occTexTrsf2d[2];       //!< 2D texture transformation parameters
 uniform               float     occPointSize;          //!< point size
 
index ea1a087..488d06d 100644 (file)
@@ -121,10 +121,13 @@ static const char Shaders_Declarations_glsl[] =
   "float occBackMaterial_Shininess(void);     //!< Specular exponent\n"
   "float occBackMaterial_Transparency(void);  //!< Transparency coefficient\n"
   "\n"
+  "#define occActiveSampler    occSampler0                //!< alias for backward compatibility\n"
+  "#define occSamplerBaseColor occSampler0                //!< alias to a base color texture\n"
+  "uniform               sampler2D occSampler0;           //!< current active sampler;\n"
+  "                                                       //!  occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing\n"
   "uniform               vec4      occColor;              //!< color value (in case of disabled lighting)\n"
   "uniform THE_PREC_ENUM int       occDistinguishingMode; //!< Are front and back faces distinguished?\n"
   "uniform THE_PREC_ENUM int       occTextureEnable;      //!< Is texture enabled?\n"
-  "uniform               sampler2D occActiveSampler;      //!< Current active sampler\n"
   "uniform               vec4      occTexTrsf2d[2];       //!< 2D texture transformation parameters\n"
   "uniform               float     occPointSize;          //!< point size\n"
   "\n"
index 8eaf0dd..c290f62 100644 (file)
@@ -50,6 +50,7 @@
 #include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_CStructure.hxx>
 #include <Graphic3d_Texture2Dmanual.hxx>
+#include <Graphic3d_GraphicDriver.hxx>
 #include <Image_AlienPixMap.hxx>
 #include <OSD_File.hxx>
 #include <Prs3d_Drawer.hxx>
@@ -3420,13 +3421,13 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
   Graphic3d_LevelOfTextureAnisotropy anAnisoFilter = Graphic3d_LOTA_OFF;
 
   Handle(AIS_Shape) aTexturedIO;
-  Handle(Graphic3d_TextureMap) aTextureOld;
-  Handle(Graphic3d_Texture2Dmanual) aTextureNew;
+  Handle(Graphic3d_TextureSet) aTextureSetOld;
+  NCollection_Vector<Handle(Graphic3d_Texture2Dmanual)> aTextureVecNew;
   bool toSetGenRepeat = false;
   bool toSetGenScale  = false;
   bool toSetGenOrigin = false;
   bool toSetImage     = false;
-  bool toSetNewImage  = false;
+  bool toComputeUV    = false;
 
   const TCollection_AsciiString aCommandName (theArgVec[0]);
   bool toSetDefaults = aCommandName == "vtexdefault";
@@ -3456,7 +3457,7 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
 
       if (aTexturedIO->Attributes()->HasOwnShadingAspect())
       {
-        aTextureOld = aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap();
+        aTextureSetOld = aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureSet();
       }
     }
     else if (aNameCase == "-scale"
@@ -3665,22 +3666,51 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
     {
       toSetDefaults = true;
     }
-    else if (aTextureNew.IsNull()
-          && aCommandName == "vtexture")
+    else if (aCommandName == "vtexture"
+          && (aTextureVecNew.IsEmpty()
+           || aNameCase.StartsWith ("-tex")))
     {
+      Standard_Integer aTexIndex = 0;
+      TCollection_AsciiString aTexName = aName;
+      if (aNameCase.StartsWith ("-tex"))
+      {
+        if (anArgIter + 1 >= theArgsNb
+         || aNameCase.Length() < 5)
+        {
+          std::cout << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'\n";
+          return 1;
+        }
+
+        TCollection_AsciiString aTexIndexStr = aNameCase.SubString (5, aNameCase.Length());
+        if (!aTexIndexStr.IsIntegerValue())
+        {
+          std::cout << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'\n";
+          return 1;
+        }
+
+        aTexIndex = aTexIndexStr.IntegerValue();
+        aTexName  = theArgVec[anArgIter + 1];
+        ++anArgIter;
+      }
+      if (aTexIndex >= Graphic3d_TextureUnit_NB
+       || aTexIndex >= aCtx->CurrentViewer()->Driver()->InquireLimit (Graphic3d_TypeOfLimit_MaxCombinedTextureUnits))
+      {
+        std::cout << "Error: too many textures specified\n";
+        return 1;
+      }
+
       toSetImage = true;
-      toSetNewImage = true;
-      if (aName.IsIntegerValue())
+      if (aTexName.IsIntegerValue())
       {
-        const Standard_Integer aValue = aName.IntegerValue();
+        const Standard_Integer aValue = aTexName.IntegerValue();
         if (aValue < 0 || aValue >= Graphic3d_Texture2D::NumberOfTextures())
         {
           std::cout << "Syntax error: texture with ID " << aValue << " is undefined!\n";
           return 1;
         }
-        aTextureNew = new Graphic3d_Texture2Dmanual (Graphic3d_NameOfTexture2D (aValue));
+        aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2Dmanual (Graphic3d_NameOfTexture2D (aValue)));
       }
-      else if (aNameCase == "?")
+      else if (aTexName == "?")
       {
         const TCollection_AsciiString aTextureFolder = Graphic3d_TextureRoot::TexturesFolder();
 
@@ -3695,19 +3725,49 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
         theDi.Eval (aCmnd.ToCString());
         return 0;
       }
-      else if (aNameCase != "off")
+      else if (aTexName != "off")
       {
-        if (!OSD_File (aName).Exists())
+        if (!OSD_File (aTexName).Exists())
         {
-          std::cout << "Syntax error: non-existing image file has been specified '" << aName << "'.\n";
+          std::cout << "Syntax error: non-existing image file has been specified '" << aTexName << "'.\n";
           return 1;
         }
-        aTextureNew = new Graphic3d_Texture2Dmanual (aName);
+        aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2Dmanual (aTexName));
+      }
+      else
+      {
+        aTextureVecNew.SetValue (aTexIndex, Handle(Graphic3d_Texture2Dmanual)());
       }
+      aTextureVecNew.ChangeValue (aTexIndex)->GetParams()->SetTextureUnit ((Graphic3d_TextureUnit )aTexIndex);
+    }
+    else
+    {
+      std::cout << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'\n";
+      return 1;
+    }
+  }
 
-      if (!aTextureNew.IsNull())
+  if (toSetImage)
+  {
+    // check if new image set is equal to already set one
+    Standard_Integer aNbChanged = 0;
+    Handle(Graphic3d_TextureSet) aTextureSetNew;
+    if (!aTextureVecNew.IsEmpty())
+    {
+      aNbChanged = aTextureVecNew.Size();
+      aTextureSetNew = new Graphic3d_TextureSet (aTextureVecNew.Size());
+      for (Standard_Integer aTexIter = 0; aTexIter < aTextureSetNew->Size(); ++aTexIter)
       {
-        if (!aTextureOld.IsNull())
+        Handle(Graphic3d_Texture2Dmanual)& aTextureNew = aTextureVecNew.ChangeValue (aTexIter);
+        Handle(Graphic3d_TextureRoot) aTextureOld;
+        if (!aTextureSetOld.IsNull()
+          && aTexIter < aTextureSetOld->Size())
+        {
+          aTextureOld = aTextureSetOld->Value (aTexIter);
+        }
+
+        if (!aTextureOld.IsNull()
+         && !aTextureNew.IsNull())
         {
           *aTextureNew->GetParams() = *aTextureOld->GetParams();
           if (Handle(Graphic3d_Texture2Dmanual) anOldManualTex = Handle(Graphic3d_Texture2Dmanual)::DownCast (aTextureOld))
@@ -3719,39 +3779,31 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
              && aFilePathOld == aFilePathNew
              && (!aFilePathNew.IsEmpty() || aTextureNew->Name() != Graphic3d_NOT_2D_UNKNOWN))
             {
-              toSetNewImage = false;
+              --aNbChanged;
               aTextureNew = anOldManualTex;
             }
           }
         }
-        else
-        {
-          aTexturedIO->SetToUpdate (AIS_Shaded);
-        }
-      }
-
-      if (!aTexturedIO->Attributes()->HasOwnShadingAspect())
-      {
-        aTexturedIO->Attributes()->SetShadingAspect (new Prs3d_ShadingAspect());
-        *aTexturedIO->Attributes()->ShadingAspect()->Aspect() = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
-      }
-
-      if (!aTextureNew.IsNull())
-      {
-        aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn();
-      }
-      else
-      {
-        aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOff();
+        aTextureSetNew->SetValue (aTexIter, aTextureNew);
       }
-      aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMap (aTextureNew);
-      aTextureOld.Nullify();
     }
-    else
+    if (aNbChanged == 0
+     && ((aTextureSetOld.IsNull() && aTextureSetNew.IsNull())
+      || (aTextureSetOld->Size() == aTextureSetNew->Size())))
     {
-      std::cout << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'\n";
-      return 1;
+      aTextureSetNew = aTextureSetOld;
+    }
+
+    if (!aTexturedIO->Attributes()->HasOwnShadingAspect())
+    {
+      aTexturedIO->Attributes()->SetShadingAspect (new Prs3d_ShadingAspect());
+      *aTexturedIO->Attributes()->ShadingAspect()->Aspect() = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
     }
+
+    toComputeUV = !aTextureSetNew.IsNull() && aTextureSetOld.IsNull();
+    aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn (!aTextureSetNew.IsNull());
+    aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (aTextureSetNew);
+    aTextureSetOld.Nullify();
   }
 
   if (toSetDefaults)
@@ -3790,12 +3842,12 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
   if (aCommandName == "vtexture"
    && theArgsNb == 2)
   {
-    if (!aTextureOld.IsNull())
+    if (!aTextureSetOld.IsNull())
     {
-      toSetNewImage = true;
+      //toComputeUV = true; // we can keep UV vertex attributes
       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOff();
-      aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMap (Handle(Graphic3d_TextureMap)());
-      aTextureOld.Nullify();
+      aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (Handle(Graphic3d_TextureSet)());
+      aTextureSetOld.Nullify();
     }
   }
 
@@ -3851,7 +3903,7 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
     toSetGenScale = true;
   }
 
-  if (toSetGenRepeat || toSetGenOrigin || toSetGenScale || toSetNewImage)
+  if (toSetGenRepeat || toSetGenOrigin || toSetGenScale || toComputeUV)
   {
     aTexturedIO->SetToUpdate (AIS_Shaded);
     if (toSetImage)
@@ -6267,6 +6319,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
 
   theCommands.Add ("vtexture",
                    "vtexture [-noupdate|-update] name [ImageFile|IdOfTexture|off]"
+                   "\n\t\t:          [-tex0 Image0] [-tex1 Image1] [...]"
                    "\n\t\t:          [-origin {u v|off}] [-scale {u v|off}] [-repeat {u v|off}]"
                    "\n\t\t:          [-trsfTrans du dv] [-trsfScale su sv] [-trsfAngle Angle]"
                    "\n\t\t:          [-modulate {on|off}]"
index e7e63f1..114b6ac 100644 (file)
@@ -594,28 +594,40 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
   {
     if (theArgNb < 3)
     {
-      std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
+      std::cout << "Syntax error: lack of arguments\n";
       return 1;
     }
 
     const TCollection_AsciiString aSrcVert = theArgVec[theArgNb - 2];
     const TCollection_AsciiString aSrcFrag = theArgVec[theArgNb - 1];
-    if (!aSrcVert.IsEmpty()
-     && !OSD_File (aSrcVert).Exists())
+    if (aSrcVert.IsEmpty() || aSrcFrag.IsEmpty())
     {
-      std::cerr << "Non-existing vertex shader source\n";
+      std::cout << "Syntax error: lack of arguments\n";
       return 1;
     }
-    if (!aSrcFrag.IsEmpty()
-     && !OSD_File (aSrcFrag).Exists())
+
+    const bool isVertFile = OSD_File (aSrcVert).Exists();
+    const bool isFragFile = OSD_File (aSrcFrag).Exists();
+    if (!isVertFile
+     && aSrcVert.Search ("gl_Position") == -1)
     {
-      std::cerr << "Non-existing fragment shader source\n";
+      std::cerr << "Error: non-existing or invalid vertex shader source\n";
+      return 1;
+    }
+    if (!isFragFile
+      && aSrcFrag.Search ("occFragColor") == -1)
+    {
+      std::cerr << "Error: non-existing or invalid fragment shader source\n";
       return 1;
     }
 
     aProgram = new Graphic3d_ShaderProgram();
-    aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX,   aSrcVert));
-    aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
+    aProgram->AttachShader (isVertFile
+                          ? Graphic3d_ShaderObject::CreateFromFile  (Graphic3d_TOS_VERTEX,   aSrcVert)
+                          : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX,   aSrcVert));
+    aProgram->AttachShader (isFragFile
+                          ? Graphic3d_ShaderObject::CreateFromFile  (Graphic3d_TOS_FRAGMENT, aSrcFrag)
+                          : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_FRAGMENT, aSrcFrag));
     anArgsNb = theArgNb - 2;
   }
 
diff --git a/tests/v3d/glsl/texture_multi1 b/tests/v3d/glsl/texture_multi1
new file mode 100644 (file)
index 0000000..92456d8
--- /dev/null
@@ -0,0 +1,40 @@
+puts "========"
+puts "0028912: Visualization, TKOpenGl - multi-texture support"
+puts "========"
+
+pload MODELING VISUALIZATION
+
+set aShaderVert "
+THE_SHADER_OUT vec2 TexCoord;
+void main() {
+  TexCoord    = occTexCoord.st;
+  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
+}"
+
+set aShaderFrag "
+uniform sampler2D occSampler1;
+uniform sampler2D occSampler2;
+uniform sampler2D occSampler3;
+THE_SHADER_IN vec2 TexCoord;
+void main() {
+  if      (TexCoord.s <  0.5 && TexCoord.t <  0.5) { occFragColor = occTexture2D(occSampler0, TexCoord.st); }
+  else if (TexCoord.s <  0.5 && TexCoord.t >= 0.5) { occFragColor = occTexture2D(occSampler1, TexCoord.st); }
+  else if (TexCoord.s >= 0.5 && TexCoord.t <  0.5) { occFragColor = occTexture2D(occSampler2, TexCoord.st); }
+  else                                             { occFragColor = occTexture2D(occSampler3, TexCoord.st); }
+}"
+
+# draw a box
+box b 1 2 3
+vclear
+vinit View1
+vaxo
+vdisplay -dispMode 1 b
+vfit
+vrotate 0.2 0.0 0.0
+
+# take snapshot with built-in shader
+vtexture b -tex0 3 -tex1 4 -tex2 5 -tex3 6
+vdump $::imagedir/${::casename}_normal.png
+
+vshaderprog b $aShaderVert $aShaderFrag
+vdump $::imagedir/${::casename}_multi.png