From cc8cbabe5c8928f16926481145bf9bacffd5bcd6 Mon Sep 17 00:00:00 2001 From: kgv Date: Mon, 10 Jul 2017 15:43:25 +0300 Subject: [PATCH] 0028912: Visualization, TKOpenGl - multi-texture support 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. --- src/Graphic3d/FILES | 3 + src/Graphic3d/Graphic3d_AspectFillArea3d.cxx | 15 + src/Graphic3d/Graphic3d_AspectFillArea3d.hxx | 25 +- src/Graphic3d/Graphic3d_ClipPlane.cxx | 12 +- src/Graphic3d/Graphic3d_ClipPlane.hxx | 4 +- src/Graphic3d/Graphic3d_TextureParams.cxx | 130 ++---- src/Graphic3d/Graphic3d_TextureParams.hxx | 99 +++-- src/Graphic3d/Graphic3d_TextureRoot.hxx | 14 +- src/Graphic3d/Graphic3d_TextureSet.cxx | 16 + src/Graphic3d/Graphic3d_TextureSet.hxx | 90 +++++ src/Graphic3d/Graphic3d_TextureUnit.hxx | 49 +++ src/Graphic3d/Graphic3d_TypeOfLimit.hxx | 1 + src/OpenGl/FILES | 4 + src/OpenGl/OpenGl_ArbSamplerObject.hxx | 43 ++ src/OpenGl/OpenGl_AspectFace.cxx | 215 +++++++--- src/OpenGl/OpenGl_AspectFace.hxx | 50 ++- src/OpenGl/OpenGl_AspectMarker.cxx | 217 ++++++---- src/OpenGl/OpenGl_AspectMarker.hxx | 71 ++-- src/OpenGl/OpenGl_BackgroundArray.cxx | 4 +- src/OpenGl/OpenGl_CappingPlaneResource.cxx | 2 +- src/OpenGl/OpenGl_Context.cxx | 153 ++++++- src/OpenGl/OpenGl_Context.hxx | 36 +- src/OpenGl/OpenGl_Font.cxx | 2 +- src/OpenGl/OpenGl_GlFunctions.hxx | 30 ++ src/OpenGl/OpenGl_GraphicDriver.cxx | 2 + src/OpenGl/OpenGl_Layer.cxx | 4 +- src/OpenGl/OpenGl_LayerList.cxx | 12 +- src/OpenGl/OpenGl_NamedResource.hxx | 41 ++ src/OpenGl/OpenGl_PointSprite.cxx | 17 +- src/OpenGl/OpenGl_PointSprite.hxx | 2 +- src/OpenGl/OpenGl_PrimitiveArray.cxx | 62 +-- src/OpenGl/OpenGl_Resource.cxx | 5 +- src/OpenGl/OpenGl_Sampler.cxx | 404 ++++++++++++++++--- src/OpenGl/OpenGl_Sampler.hxx | 104 ++++- src/OpenGl/OpenGl_SceneGeometry.cxx | 91 +++-- src/OpenGl/OpenGl_SceneGeometry.hxx | 11 +- src/OpenGl/OpenGl_ShaderManager.cxx | 32 +- src/OpenGl/OpenGl_ShaderManager.hxx | 26 +- src/OpenGl/OpenGl_ShaderProgram.cxx | 46 ++- src/OpenGl/OpenGl_ShaderProgram.hxx | 20 +- src/OpenGl/OpenGl_Structure.cxx | 16 +- src/OpenGl/OpenGl_Text.cxx | 6 +- src/OpenGl/OpenGl_Texture.cxx | 139 +++---- src/OpenGl/OpenGl_Texture.hxx | 69 ++-- src/OpenGl/OpenGl_TextureBufferArb.cxx | 24 +- src/OpenGl/OpenGl_TextureBufferArb.hxx | 4 +- src/OpenGl/OpenGl_TextureSet.cxx | 17 + src/OpenGl/OpenGl_TextureSet.hxx | 90 +++++ src/OpenGl/OpenGl_View.cxx | 18 +- src/OpenGl/OpenGl_View.hxx | 28 +- src/OpenGl/OpenGl_View_Raytrace.cxx | 151 ++++--- src/OpenGl/OpenGl_View_Redraw.cxx | 32 +- src/OpenGl/OpenGl_Workspace.cxx | 355 +--------------- src/OpenGl/OpenGl_Workspace.hxx | 23 +- src/Shaders/Declarations.glsl | 5 +- src/Shaders/Shaders_Declarations_glsl.pxx | 5 +- src/ViewerTest/ViewerTest.cxx | 151 ++++--- src/ViewerTest/ViewerTest_OpenGlCommands.cxx | 30 +- tests/v3d/glsl/texture_multi1 | 40 ++ 59 files changed, 2095 insertions(+), 1272 deletions(-) create mode 100644 src/Graphic3d/Graphic3d_TextureSet.cxx create mode 100644 src/Graphic3d/Graphic3d_TextureSet.hxx create mode 100644 src/Graphic3d/Graphic3d_TextureUnit.hxx create mode 100644 src/OpenGl/OpenGl_ArbSamplerObject.hxx create mode 100644 src/OpenGl/OpenGl_NamedResource.hxx create mode 100644 src/OpenGl/OpenGl_TextureSet.cxx create mode 100644 src/OpenGl/OpenGl_TextureSet.hxx create mode 100644 tests/v3d/glsl/texture_multi1 diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index a8570d846c..334dcdf8fa 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -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 diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx index d8c395ce24..2e65f35f72 100644 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx @@ -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); +} diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx b/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx index 44c8f00d1b..1cd298da05 100644 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/Graphic3d/Graphic3d_ClipPlane.cxx b/src/Graphic3d/Graphic3d_ClipPlane.cxx index 6c6d7e7b63..1524c946fa 100755 --- a/src/Graphic3d/Graphic3d_ClipPlane.cxx +++ b/src/Graphic3d/Graphic3d_ClipPlane.cxx @@ -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; } diff --git a/src/Graphic3d/Graphic3d_ClipPlane.hxx b/src/Graphic3d/Graphic3d_ClipPlane.hxx index 08f33aef70..11058e3599 100755 --- a/src/Graphic3d/Graphic3d_ClipPlane.hxx +++ b/src/Graphic3d/Graphic3d_ClipPlane.hxx @@ -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. diff --git a/src/Graphic3d/Graphic3d_TextureParams.cxx b/src/Graphic3d/Graphic3d_TextureParams.cxx index 178f39b95c..1eacf67bdc 100644 --- a/src/Graphic3d/Graphic3d_TextureParams.cxx +++ b/src/Graphic3d/Graphic3d_TextureParams.cxx @@ -11,9 +11,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #include -#include IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_TextureParams,Standard_Transient) @@ -22,38 +20,31 @@ 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 : @@ -63,31 +54,17 @@ void Graphic3d_TextureParams::SetModulate (const Standard_Boolean theToModulate) myToModulate = 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(); + } } // ======================================================================= @@ -135,15 +102,6 @@ void Graphic3d_TextureParams::SetRotation (const Standard_ShortReal theAngleDegr myRotAngle = theAngleDegrees; } -// ======================================================================= -// function : Scale -// purpose : -// ======================================================================= -const Graphic3d_Vec2& Graphic3d_TextureParams::Scale() const -{ - return myScale; -} - // ======================================================================= // function : SetScale // purpose : @@ -153,15 +111,6 @@ void Graphic3d_TextureParams::SetScale (const Graphic3d_Vec2 theScale) myScale = theScale; } -// ======================================================================= -// function : Translation -// purpose : -// ======================================================================= -const Graphic3d_Vec2& Graphic3d_TextureParams::Translation() const -{ - return myTranslation; -} - // ======================================================================= // function : SetTranslation // purpose : @@ -171,33 +120,6 @@ void Graphic3d_TextureParams::SetTranslation (const Graphic3d_Vec2 theVec) myTranslation = 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 : diff --git a/src/Graphic3d/Graphic3d_TextureParams.hxx b/src/Graphic3d/Graphic3d_TextureParams.hxx index 2215f1352b..06fd0f1d2c 100644 --- a/src/Graphic3d/Graphic3d_TextureParams.hxx +++ b/src/Graphic3d/Graphic3d_TextureParams.hxx @@ -14,130 +14,123 @@ #ifndef _Graphic3d_TextureParams_HeaderFile #define _Graphic3d_TextureParams_HeaderFile -#include -#include - -#include -#include #include -#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include #include - -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 diff --git a/src/Graphic3d/Graphic3d_TextureRoot.hxx b/src/Graphic3d/Graphic3d_TextureRoot.hxx index f9e1139858..90cb639dc5 100644 --- a/src/Graphic3d/Graphic3d_TextureRoot.hxx +++ b/src/Graphic3d/Graphic3d_TextureRoot.hxx @@ -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 index 0000000000..518b8df224 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TextureSet.cxx @@ -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 + +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 index 0000000000..7b0d5bc5dc --- /dev/null +++ b/src/Graphic3d/Graphic3d_TextureSet.hxx @@ -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 +#include + +//! 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::Iterator + { + public: + //! Empty constructor. + Iterator() {} + + //! Constructor. + Iterator (const Handle(Graphic3d_TextureSet)& theSet) + { + if (!theSet.IsNull()) + { + NCollection_Array1::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 myTextures; + +}; + +#endif // _Graphic3d_TextureSet_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TextureUnit.hxx b/src/Graphic3d/Graphic3d_TextureUnit.hxx new file mode 100644 index 0000000000..c587f68734 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TextureUnit.hxx @@ -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 diff --git a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx index 9a8de15343..e27984a5d0 100644 --- a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx +++ b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx @@ -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 diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 7c3eab0b65..61597805cd 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -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 index 0000000000..654fdc2743 --- /dev/null +++ b/src/OpenGl/OpenGl_ArbSamplerObject.hxx @@ -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 + +//! 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 diff --git a/src/OpenGl/OpenGl_AspectFace.cxx b/src/OpenGl/OpenGl_AspectFace.cxx index c262d76489..2f4fde3ef7 100644 --- a/src/OpenGl/OpenGl_AspectFace.cxx +++ b/src/OpenGl/OpenGl_AspectFace.cxx @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -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()) { - if (!theTexture.IsNull() - && theTexture->GetId() == TextureId - && theTexture->Revision() != Texture->Revision()) + return; + } + + for (OpenGl_TextureSet::Iterator aTextureIter (myTextures); aTextureIter.More(); aTextureIter.Next()) + { + Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue(); + if (aTextureRes.IsNull()) { - Handle(Image_PixMap) anImage = theTexture->GetImage(); - if (!anImage.IsNull()) - { - Texture->Init (theCtx, *anImage.operator->(), theTexture->Type()); - Texture->SetRevision (Texture->Revision()); - return; - } + continue; } - if (TextureId.IsEmpty()) + if (theCtx != NULL) { - theCtx->DelayedRelease (Texture); - Texture.Nullify(); + if (aTextureRes->ResourceId().IsEmpty()) + { + 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; + } + + const TCollection_AsciiString& aTextureKey = aTexture->GetId(); + if (aTextureKey.IsEmpty() || aResource->ResourceId() != aTextureKey) + { + myIsTextureReady = Standard_False; + return; + } + else if (aResource->Revision() != aTexture->Revision()) + { + 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(); - - if (!theTexture.IsNull()) +// ======================================================================= +// 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) { - if (TextureId.IsEmpty() || !theCtx->GetResource (TextureId, Texture)) + ReleaseTextures (theCtx.get()); + if (aNbTexturesNew > 0) { - Texture = new OpenGl_Texture (theTexture->GetParams()); - Handle(Image_PixMap) anImage = theTexture->GetImage(); - if (!anImage.IsNull()) + myTextures = new OpenGl_TextureSet (theTextures->Size()); + } + else + { + myTextures.Nullify(); + } + } + if (myTextures.IsNull()) + { + return; + } + + Graphic3d_TextureSet::Iterator aTextureIter (theTextures); + OpenGl_TextureSet::Iterator aResIter (myTextures); + for (; aResIter.More(); aResIter.Next(), aTextureIter.Next()) + { + 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()) { - Texture->Init (theCtx, *anImage.operator->(), theTexture->Type()); - Texture->SetRevision (Texture->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 (!TextureId.IsEmpty()) + + if (aResource->ResourceId().IsEmpty()) { - theCtx->ShareResource (TextureId, Texture); + 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()) + { + const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId(); + if (aTextureKeyNew.IsEmpty() + || !theCtx->GetResource (aTextureKeyNew, aResource)) + { + 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); + } + } + else + { + aResource->Sampler()->SetParameters (aTexture->GetParams()); } } } diff --git a/src/OpenGl/OpenGl_AspectFace.hxx b/src/OpenGl/OpenGl_AspectFace.hxx index dde2e67148..e362839c9f 100644 --- a/src/OpenGl/OpenGl_AspectFace.hxx +++ b/src/OpenGl/OpenGl_AspectFace.hxx @@ -17,6 +17,7 @@ #define _OpenGl_AspectFace_Header #include +#include #include #include #include @@ -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; diff --git a/src/OpenGl/OpenGl_AspectMarker.cxx b/src/OpenGl/OpenGl_AspectMarker.cxx index a2899f5c51..f94d236d35 100644 --- a/src/OpenGl/OpenGl_AspectMarker.cxx +++ b/src/OpenGl/OpenGl_AspectMarker.cxx @@ -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()) { - if (theCtx) + return; + } + + if (theCtx != NULL) + { + 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(); +} - if (!myResources.ShaderProgram.IsNull() && theCtx) +// ======================================================================= +// function : ReleaseShaders +// purpose : +// ======================================================================= +void OpenGl_AspectMarker::Resources::ReleaseShaders (OpenGl_Context* theCtx) +{ + if (!myShaderProgram.IsNull() && theCtx != NULL) { - theCtx->ShaderManager()->Unregister (myResources.ShaderProgramId, - myResources.ShaderProgram); + theCtx->ShaderManager()->Unregister (myShaderProgramId, + myShaderProgram); + } + myShaderProgramId.Clear(); + myIsShaderReady = Standard_False; +} + +// ======================================================================= +// 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) + { + 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 (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 (aNewKeyA, SpriteA) // alpha sprite could be shared - && theCtx->GetResource (aNewKey, Sprite)) + && theCtx->GetResource (aNewKeyA, aSpriteA) // alpha sprite could be shared + && theCtx->GetResource (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, diff --git a/src/OpenGl/OpenGl_AspectMarker.hxx b/src/OpenGl/OpenGl_AspectMarker.hxx index 02ae41f00f..2f83701ee3 100644 --- a/src/OpenGl/OpenGl_AspectMarker.hxx +++ b/src/OpenGl/OpenGl_AspectMarker.hxx @@ -21,6 +21,7 @@ #include #include +#include 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); + private: - Handle(OpenGl_PointSprite) Sprite; - TCollection_AsciiString SpriteKey; - - Handle(OpenGl_PointSprite) SpriteA; - TCollection_AsciiString SpriteAKey; - - 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; diff --git a/src/OpenGl/OpenGl_BackgroundArray.cxx b/src/OpenGl/OpenGl_BackgroundArray.cxx index b49b4d97a5..0f5723b419 100644 --- a/src/OpenGl/OpenGl_BackgroundArray.cxx +++ b/src/OpenGl/OpenGl_BackgroundArray.cxx @@ -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) { diff --git a/src/OpenGl/OpenGl_CappingPlaneResource.cxx b/src/OpenGl/OpenGl_CappingPlaneResource.cxx index dd032d9d9b..a4b77939d1 100755 --- a/src/OpenGl/OpenGl_CappingPlaneResource.cxx +++ b/src/OpenGl/OpenGl_CappingPlaneResource.cxx @@ -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 diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 0a7d3963b1..52f9a16050 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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)); } @@ -2953,6 +2973,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 : diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index a6a6599918..018fa460df 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,12 +36,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include @@ -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 struct OpenGl_TmplCore12; typedef OpenGl_TmplCore12 OpenGl_GlCore12; @@ -130,11 +132,12 @@ template struct OpenGl_TmplCore44; typedef OpenGl_TmplCore44 OpenGl_GlCore44Back; typedef OpenGl_TmplCore44 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 diff --git a/src/OpenGl/OpenGl_Font.cxx b/src/OpenGl/OpenGl_Font.cxx index f9215e7fb3..8cbd467cbe 100755 --- a/src/OpenGl/OpenGl_Font.cxx +++ b/src/OpenGl/OpenGl_Font.cxx @@ -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; diff --git a/src/OpenGl/OpenGl_GlFunctions.hxx b/src/OpenGl/OpenGl_GlFunctions.hxx index 880589d173..03e3411f37 100644 --- a/src/OpenGl/OpenGl_GlFunctions.hxx +++ b/src/OpenGl/OpenGl_GlFunctions.hxx @@ -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); diff --git a/src/OpenGl/OpenGl_GraphicDriver.cxx b/src/OpenGl/OpenGl_GraphicDriver.cxx index 0912755d62..196837e041 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver.cxx @@ -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: diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx index 1c82e6bf4e..d3d86014e1 100644 --- a/src/OpenGl/OpenGl_Layer.cxx +++ b/src/OpenGl/OpenGl_Layer.cxx @@ -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 diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index d7bf035844..6a15b019d0 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -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 index 0000000000..e316fe1546 --- /dev/null +++ b/src/OpenGl/OpenGl_NamedResource.hxx @@ -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 +#include + +//! 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 diff --git a/src/OpenGl/OpenGl_PointSprite.cxx b/src/OpenGl/OpenGl_PointSprite.cxx index 57ff6b690e..acbe7d1f20 100755 --- a/src/OpenGl/OpenGl_PointSprite.cxx +++ b/src/OpenGl/OpenGl_PointSprite.cxx @@ -16,25 +16,25 @@ #include #include +#include #include #include - 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 : diff --git a/src/OpenGl/OpenGl_PointSprite.hxx b/src/OpenGl/OpenGl_PointSprite.hxx index bf550ab845..bb8f458ccc 100755 --- a/src/OpenGl/OpenGl_PointSprite.hxx +++ b/src/OpenGl/OpenGl_PointSprite.hxx @@ -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(); diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 811097de6c..98ee3c2d26 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -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 (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 (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 (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 { diff --git a/src/OpenGl/OpenGl_Resource.cxx b/src/OpenGl/OpenGl_Resource.cxx index 802af35e91..4f1c0c3e41 100644 --- a/src/OpenGl/OpenGl_Resource.cxx +++ b/src/OpenGl/OpenGl_Resource.cxx @@ -14,9 +14,10 @@ // commercial license or contractual agreement. #include +#include - -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() {} diff --git a/src/OpenGl/OpenGl_Sampler.cxx b/src/OpenGl/OpenGl_Sampler.cxx index 0dc8f9bb79..4ee9e5b576 100644 --- a/src/OpenGl/OpenGl_Sampler.cxx +++ b/src/OpenGl/OpenGl_Sampler.cxx @@ -14,9 +14,10 @@ // commercial license or contractual agreement. #include -#include -#include +#include +#include +#include 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...",); - - if (theContext->IsValid()) - { - #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) - theContext->core33->glDeleteSamplers (1, &mySamplerID); - #endif - } - - mySamplerID = NO_SAMPLER; + return; } + + // 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...",); + + 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 !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) - theContext.core33->glGenSamplers (1, &mySamplerID); + if (!Create (theCtx)) + { + return Standard_False; + } + + 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()) { - #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 + 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) + { + 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 +} diff --git a/src/OpenGl/OpenGl_Sampler.hxx b/src/OpenGl/OpenGl_Sampler.hxx index 83a7a86995..af740e4a2d 100644 --- a/src/OpenGl/OpenGl_Sampler.hxx +++ b/src/OpenGl/OpenGl_Sampler.hxx @@ -13,18 +13,21 @@ // 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 +#include -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; } + //! 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); + protected: - GLuint mySamplerID; //!< OpenGL sampler object ID - -public: - - 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 diff --git a/src/OpenGl/OpenGl_SceneGeometry.cxx b/src/OpenGl/OpenGl_SceneGeometry.cxx index 6f92d70028..6b72d90829 100644 --- a/src/OpenGl/OpenGl_SceneGeometry.cxx +++ b/src/OpenGl/OpenGl_SceneGeometry.cxx @@ -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::Iterator aTexSrcIter (myTextures); aTexSrcIter.More(); aTexSrcIter.Next(), ++aTexIter) { - theContext->arbTexBindless->glMakeTextureHandleResidentARB (myTextureHandles[anIdx]); - - if (glGetError() != GL_NO_ERROR) + GLuint64& aHandle = myTextureHandles[aTexIter]; + const Handle(OpenGl_Texture)& aTexture = aTexSrcIter.Value(); + if (!aTexture->Sampler()->IsValid() + || !aTexture->Sampler()->IsImmutable()) { -#ifdef RAY_TRACE_PRINT_INFO - std::cout << "Error: Failed to make OpenGL texture resident" << std::endl; -#endif + // 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; + } + + 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) + { + 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::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 diff --git a/src/OpenGl/OpenGl_SceneGeometry.hxx b/src/OpenGl/OpenGl_SceneGeometry.hxx index d79f6d502c..8fa64e2959 100644 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -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 myTextures; //!< Array of texture maps shared between rendered objects - Handle(OpenGl_Sampler) myTextureSampler; //!< Sampler object providing fixed sampling params for texures std::vector 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 diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index e3b5ecae7c..e01e151343 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -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; } diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index bba6b92079..9e5d2f7cf2 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -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) { diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 7d8fe6d77a..74344dd8ec 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -35,7 +35,7 @@ #include // 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) { diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 155845fc93..ea7dc6ca84 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -25,10 +25,11 @@ #include #include +#include #include 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 diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 9d4d15e301..bfb99381fd 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -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; diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 1219a76807..9a8633fe99 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -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 diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 04bad58076..fa0b87d26c 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -17,13 +17,13 @@ #include #include #include +#include #include #include #include #include - -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(); - } + // } // ======================================================================= @@ -77,44 +75,25 @@ OpenGl_Texture::~OpenGl_Texture() Release (NULL); } -// ======================================================================= -// 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; @@ -140,17 +120,31 @@ void OpenGl_Texture::Release (OpenGl_Context* theGlCtx) mySizeX = mySizeY = mySizeZ = 0; } +// ======================================================================= +// 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,15 +153,26 @@ 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, diff --git a/src/OpenGl/OpenGl_Texture.hxx b/src/OpenGl/OpenGl_Texture.hxx index e8e9b84536..debbd6d097 100644 --- a/src/OpenGl/OpenGl_Texture.hxx +++ b/src/OpenGl/OpenGl_Texture.hxx @@ -16,10 +16,11 @@ #define _OpenGl_Texture_H__ #include -#include +#include +#include #include +#include -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__ diff --git a/src/OpenGl/OpenGl_TextureBufferArb.cxx b/src/OpenGl/OpenGl_TextureBufferArb.cxx index b5e1d8bf79..38a14d1aef 100644 --- a/src/OpenGl/OpenGl_TextureBufferArb.cxx +++ b/src/OpenGl/OpenGl_TextureBufferArb.cxx @@ -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); } diff --git a/src/OpenGl/OpenGl_TextureBufferArb.hxx b/src/OpenGl/OpenGl_TextureBufferArb.hxx index 851640ed8c..9193f842be 100644 --- a/src/OpenGl/OpenGl_TextureBufferArb.hxx +++ b/src/OpenGl/OpenGl_TextureBufferArb.hxx @@ -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 index 0000000000..c35315e2e0 --- /dev/null +++ b/src/OpenGl/OpenGl_TextureSet.cxx @@ -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 + +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 index 0000000000..3019e6afd9 --- /dev/null +++ b/src/OpenGl/OpenGl_TextureSet.hxx @@ -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 + +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::Iterator + { + public: + //! Empty constructor. + Iterator() {} + + //! Constructor. + Iterator (const Handle(OpenGl_TextureSet)& theSet) + { + if (!theSet.IsNull()) + { + NCollection_Array1::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 myTextures; + +}; + +#endif //_OpenGl_TextureSet_Header diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 41af8b0365..45182424d0 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -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()); } } diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 0607e2690e..95adf316fa 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -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 { diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 0800cf97cc..04fcc20749 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -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 (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 (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) { diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index 6ad77f0959..5b6bb69aa6 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -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 { diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index a851580a2f..a8a02385c6 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -228,345 +228,6 @@ void OpenGl_Workspace::ResetAppliedAspect() myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width()); } -// ======================================================================= -// 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)) { diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 9086b0194b..7b1648f40a 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -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 diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index be565d0e60..efdfb2dbdf 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -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 diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index ea1a087554..488d06d8e4 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -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" diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 8eaf0dd1e6..c290f62284 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -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 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"))) { - toSetImage = true; - toSetNewImage = true; - if (aName.IsIntegerValue()) + Standard_Integer aTexIndex = 0; + TCollection_AsciiString aTexName = aName; + if (aNameCase.StartsWith ("-tex")) { - const Standard_Integer aValue = aName.IntegerValue(); + 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; + if (aTexName.IsIntegerValue()) + { + 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)); } - - if (!aTextureNew.IsNull()) + else { - if (!aTextureOld.IsNull()) + 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 (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) + { + 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); - } + aTextureSetNew->SetValue (aTexIter, aTextureNew); } - - 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(); - } - 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}]" diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index e7e63f15cc..114b6ac32d 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -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 index 0000000000..92456d8faf --- /dev/null +++ b/tests/v3d/glsl/texture_multi1 @@ -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