From: kgv Date: Sat, 16 Mar 2019 13:47:33 +0000 (+0300) Subject: 0030571: Visualization, TKOpenGl - mapped texture is ignored while drawing points X-Git-Tag: V7_4_0_beta~210 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=737e9a8da482070ba81b8f3b80d33d823680f7d8 0030571: Visualization, TKOpenGl - mapped texture is ignored while drawing points OpenGl_AspectsTextureSet now appends Sprite texture to the end of texture set. OpenGl_Context::init() - fixed usage of GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS on too old GL context. Default sampler names occSampler0, occActiveSampler and occSamplerBaseColor are now excluded from header with common declarations for build-in GLSL programs. OpenGl_ShaderObject::LoadAndCompile() and OpenGl_ShaderProgram::Link() now includes program Id within error log. OpenGl_ShaderManager now supports mapping texture onto point primitive within built-in programs (texture transformation is ignored). --- diff --git a/src/Graphic3d/Graphic3d_Aspects.hxx b/src/Graphic3d/Graphic3d_Aspects.hxx index 8675df890d..70aa6a2779 100644 --- a/src/Graphic3d/Graphic3d_Aspects.hxx +++ b/src/Graphic3d/Graphic3d_Aspects.hxx @@ -286,6 +286,19 @@ public: //! Set marker's image texture. void SetMarkerImage (const Handle(Graphic3d_MarkerImage)& theImage) { myMarkerImage = theImage; } + //! Returns TRUE if marker should be drawn using marker sprite (either user-provided or generated). + bool IsMarkerSprite() const + { + if (myMarkerType == Aspect_TOM_POINT + || myMarkerType == Aspect_TOM_EMPTY) + { + return false; + } + + return myMarkerType != Aspect_TOM_USERDEFINED + || !myMarkerImage.IsNull(); + } + //! @name parameters specific to text rendering public: diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index c7638c16f1..5e5d4c7a0a 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -80,6 +80,7 @@ Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), myNbFragOutputs (THE_NB_FRAG_OUTPUTS), + myHasDefSampler (true), myHasAlphaTest (false), myHasWeightOitOutput (false) { diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 96d13e8830..c44ba1205f 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -138,6 +138,12 @@ public: //! Note that this flag is designed for usage with - custom shader program may discard fragment regardless this flag. void SetAlphaTest (Standard_Boolean theAlphaTest) { myHasAlphaTest = theAlphaTest; } + //! Return TRUE if standard program header should define default texture sampler occSampler0; TRUE by default for compatibility. + Standard_Boolean HasDefaultSampler() const { return myHasDefSampler; } + + //! Set if standard program header should define default texture sampler occSampler0. + void SetDefaultSampler (Standard_Boolean theHasDefSampler) { myHasDefSampler = theHasDefSampler; } + //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default. Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; } @@ -195,6 +201,7 @@ private: Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) + Standard_Boolean myHasDefSampler; //!< flag indicating that program defines default texture sampler occSampler0 Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader performs alpha test Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage diff --git a/src/OpenGl/OpenGl_Aspects.cxx b/src/OpenGl/OpenGl_Aspects.cxx index 080c7edc0c..13cf990279 100644 --- a/src/OpenGl/OpenGl_Aspects.cxx +++ b/src/OpenGl/OpenGl_Aspects.cxx @@ -86,9 +86,13 @@ void OpenGl_Aspects::SetAspect (const Handle(Graphic3d_Aspects)& theAspect) : Graphic3d_TOSM_UNLIT; // invalidate resources - myResTextureSet.UpdateRediness (myAspect->TextureSet()); + myResTextureSet.UpdateRediness (myAspect); myResSprite.UpdateRediness (myAspect); myResProgram.UpdateRediness (myAspect); + if (!myResSprite.IsReady()) + { + myResTextureSet.Invalidate(); + } } // ======================================================================= diff --git a/src/OpenGl/OpenGl_Aspects.hxx b/src/OpenGl/OpenGl_Aspects.hxx index a711c78445..9e881dfebc 100644 --- a/src/OpenGl/OpenGl_Aspects.hxx +++ b/src/OpenGl/OpenGl_Aspects.hxx @@ -45,9 +45,12 @@ public: void SetNoLighting() { myShadingModel = Graphic3d_TOSM_UNLIT; } //! Returns textures map. - const Handle(OpenGl_TextureSet)& TextureSet (const Handle(OpenGl_Context)& theCtx) const + const Handle(OpenGl_TextureSet)& TextureSet (const Handle(OpenGl_Context)& theCtx, + bool theToHighlight = false) const { - return myResTextureSet.TextureSet (theCtx, myAspect->TextureSet()); + const Handle(OpenGl_PointSprite)& aSprite = myResSprite.Sprite (theCtx, myAspect, false); + const Handle(OpenGl_PointSprite)& aSpriteA = myResSprite.Sprite (theCtx, myAspect, true); + return myResTextureSet.TextureSet (theCtx, myAspect, aSprite, aSpriteA, theToHighlight); } //! Init and return OpenGl shader program resource. @@ -60,18 +63,24 @@ public: //! @return marker size Standard_ShortReal MarkerSize() const { return myResSprite.MarkerSize(); } - //! Init and return OpenGl point sprite resource. - //! @return point sprite texture. - const Handle(OpenGl_TextureSet)& SpriteRes (const Handle(OpenGl_Context)& theCtx) const + //! Return TRUE if OpenGl point sprite resource defines texture. + bool HasPointSprite (const Handle(OpenGl_Context)& theCtx) const { - return myResSprite.Sprite (theCtx, myAspect); + return myResSprite.HasPointSprite (theCtx, myAspect); } - //! Init and return OpenGl highlight point sprite resource. - //! @return point sprite texture for highlight. - const Handle(OpenGl_TextureSet)& SpriteHighlightRes (const Handle(OpenGl_Context)& theCtx) const + //! Return TRUE if OpenGl point sprite resource defined by obsolete Display List (bitmap). + bool IsDisplayListSprite (const Handle(OpenGl_Context)& theCtx) const + { + return myResSprite.IsDisplayListSprite (theCtx, myAspect); + } + + //! Init and return OpenGl point sprite resource. + //! @return point sprite texture. + const Handle(OpenGl_PointSprite)& SpriteRes (const Handle(OpenGl_Context)& theCtx, + bool theIsAlphaSprite) const { - return myResSprite.SpriteA (theCtx, myAspect); + return myResSprite.Sprite (theCtx, myAspect, theIsAlphaSprite); } Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const Standard_OVERRIDE; diff --git a/src/OpenGl/OpenGl_AspectsSprite.cxx b/src/OpenGl/OpenGl_AspectsSprite.cxx index b779522e16..646f7281cb 100644 --- a/src/OpenGl/OpenGl_AspectsSprite.cxx +++ b/src/OpenGl/OpenGl_AspectsSprite.cxx @@ -1450,21 +1450,21 @@ void OpenGl_AspectsSprite::Release (OpenGl_Context* theCtx) if (theCtx != NULL) { - if (mySprite->First()->ResourceId().IsEmpty()) + if (mySprite->ResourceId().IsEmpty()) { - theCtx->DelayedRelease (mySprite->ChangeFirst()); - theCtx->DelayedRelease (mySpriteA->ChangeFirst()); + theCtx->DelayedRelease (mySprite); + theCtx->DelayedRelease (mySpriteA); } else { { - const TCollection_AsciiString aSpriteKey = mySprite->First()->ResourceId(); + const TCollection_AsciiString aSpriteKey = mySprite->ResourceId(); mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call theCtx->ReleaseResource (aSpriteKey, Standard_True); } if (!mySpriteA.IsNull()) { - const TCollection_AsciiString aSpriteKeyA = mySpriteA->First()->ResourceId(); + const TCollection_AsciiString aSpriteKeyA = mySpriteA->ResourceId(); mySpriteA.Nullify(); theCtx->ReleaseResource (aSpriteKeyA, Standard_True); } @@ -1474,6 +1474,36 @@ void OpenGl_AspectsSprite::Release (OpenGl_Context* theCtx) mySpriteA.Nullify(); } +// ======================================================================= +// function : HasPointSprite +// purpose : +// ======================================================================= +bool OpenGl_AspectsSprite::HasPointSprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects) +{ + const Handle(OpenGl_PointSprite)& aSprite = Sprite (theCtx, theAspects, false); + return !aSprite.IsNull() + && !aSprite->IsDisplayList(); +} + +// ======================================================================= +// function : IsDisplayListSprite +// purpose : +// ======================================================================= +bool OpenGl_AspectsSprite::IsDisplayListSprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects) +{ +#if !defined(GL_ES_VERSION_2_0) + const Handle(OpenGl_PointSprite)& aSprite = Sprite (theCtx, theAspects, false); + return !aSprite.IsNull() + && aSprite->IsDisplayList(); +#else + (void )theCtx; + (void )theAspects; + return false; +#endif +} + // ======================================================================= // function : UpdateRediness // purpose : @@ -1483,8 +1513,8 @@ void OpenGl_AspectsSprite::UpdateRediness (const Handle(Graphic3d_Aspects)& theA // update sprite resource bindings TCollection_AsciiString aSpriteKeyNew, aSpriteAKeyNew; spriteKeys (theAspect->MarkerImage(), theAspect->MarkerType(), theAspect->MarkerScale(), 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; + const TCollection_AsciiString& aSpriteKeyOld = !mySprite.IsNull() ? mySprite ->ResourceId() : THE_EMPTY_KEY; + const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->ResourceId() : THE_EMPTY_KEY; if (aSpriteKeyNew.IsEmpty() || aSpriteKeyOld != aSpriteKeyNew || aSpriteAKeyNew.IsEmpty() || aSpriteAKeyOld != aSpriteAKeyNew) { @@ -1493,6 +1523,24 @@ void OpenGl_AspectsSprite::UpdateRediness (const Handle(Graphic3d_Aspects)& theA } } +// ======================================================================= +// function : Sprite +// purpose : +// ======================================================================= +const Handle(OpenGl_PointSprite)& OpenGl_AspectsSprite::Sprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects, + bool theIsAlphaSprite) +{ + if (!myIsSpriteReady) + { + build (theCtx, theAspects->MarkerImage(), theAspects->MarkerType(), theAspects->MarkerScale(), theAspects->ColorRGBA(), myMarkerSize); + myIsSpriteReady = true; + } + return theIsAlphaSprite && !mySpriteA.IsNull() && mySpriteA->IsValid() + ? mySpriteA + : mySprite; +} + // ======================================================================= // function : build // purpose : @@ -1508,8 +1556,8 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, 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; + const TCollection_AsciiString& aSpriteKeyOld = !mySprite.IsNull() ? mySprite ->ResourceId() : THE_EMPTY_KEY; + const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->ResourceId() : THE_EMPTY_KEY; // release old shared resources const Standard_Boolean aNewResource = aNewKey.IsEmpty() @@ -1518,14 +1566,14 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, { if (!mySprite.IsNull()) { - if (mySprite->First()->ResourceId().IsEmpty()) + if (mySprite->ResourceId().IsEmpty()) { - theCtx->DelayedRelease (mySprite->ChangeFirst()); + theCtx->DelayedRelease (mySprite); mySprite.Nullify(); } else { - const TCollection_AsciiString anOldKey = mySprite->First()->ResourceId(); + const TCollection_AsciiString anOldKey = mySprite->ResourceId(); mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call theCtx->ReleaseResource (anOldKey, Standard_True); } @@ -1535,14 +1583,14 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, { if (!mySpriteA.IsNull()) { - if (mySpriteA->First()->ResourceId().IsEmpty()) + if (mySpriteA->ResourceId().IsEmpty()) { - theCtx->DelayedRelease (mySpriteA->ChangeFirst()); + theCtx->DelayedRelease (mySpriteA); mySpriteA.Nullify(); } else { - const TCollection_AsciiString anOldKey = mySpriteA->First()->ResourceId(); + const TCollection_AsciiString anOldKey = mySpriteA->ResourceId(); mySpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call theCtx->ReleaseResource (anOldKey, Standard_True); } @@ -1551,7 +1599,7 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, if (!aNewResource) { - const OpenGl_PointSprite* aSprite = dynamic_cast (mySprite->First().get()); + const OpenGl_PointSprite* aSprite = dynamic_cast (mySprite.get()); if (!aSprite->IsDisplayList()) { theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY())); @@ -1566,13 +1614,8 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, return; } - if (mySprite.IsNull()) - { - mySprite = new OpenGl_TextureSet (1); - mySpriteA = new OpenGl_TextureSet (1); - } - - Handle(OpenGl_PointSprite) aSprite, aSpriteA; + Handle(OpenGl_PointSprite)& aSprite = mySprite; + Handle(OpenGl_PointSprite)& aSpriteA = mySpriteA; if (!aNewKey.IsEmpty() && theCtx->GetResource (aNewKeyA, aSpriteA) // alpha sprite could be shared && theCtx->GetResource (aNewKey, aSprite)) @@ -1582,8 +1625,6 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, { theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY())); } - mySprite ->ChangeFirst() = aSprite; - mySpriteA->ChangeFirst() = aSpriteA; return; } @@ -1593,8 +1634,6 @@ void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, aSpriteA = new OpenGl_PointSprite (aNewKeyA); } aSprite = new OpenGl_PointSprite (aNewKey); - mySprite ->ChangeFirst() = aSprite; - mySpriteA->ChangeFirst() = aSpriteA; if (!aNewKey.IsEmpty()) { theCtx->ShareResource (aNewKey, aSprite); diff --git a/src/OpenGl/OpenGl_AspectsSprite.hxx b/src/OpenGl/OpenGl_AspectsSprite.hxx index 36b5125411..e7f1a0002e 100644 --- a/src/OpenGl/OpenGl_AspectsSprite.hxx +++ b/src/OpenGl/OpenGl_AspectsSprite.hxx @@ -18,7 +18,7 @@ #include class OpenGl_Context; -class OpenGl_TextureSet; +class OpenGl_PointSprite; //! OpenGl resources for custom point sprites. class OpenGl_AspectsSprite @@ -31,30 +31,25 @@ public: Standard_ShortReal MarkerSize() const { return myMarkerSize; } - //! Return RGB sprite. - const Handle(OpenGl_TextureSet)& Sprite (const Handle(OpenGl_Context)& theCtx, - const Handle(Graphic3d_Aspects)& theAspecta) - { - if (!myIsSpriteReady) - { - build (theCtx, theAspecta->MarkerImage(), theAspecta->MarkerType(), theAspecta->MarkerScale(), theAspecta->ColorRGBA(), myMarkerSize); - myIsSpriteReady = true; - } - return mySprite; - } - - //! Return Alpha sprite. - const Handle(OpenGl_TextureSet)& SpriteA (const Handle(OpenGl_Context)& theCtx, - const Handle(Graphic3d_Aspects)& theAspecta) - { - if (!myIsSpriteReady) - { - build (theCtx, theAspecta->MarkerImage(), theAspecta->MarkerType(), theAspecta->MarkerScale(), theAspecta->ColorRGBA(), myMarkerSize); - myIsSpriteReady = true; - } - return mySpriteA; - } - + //! Return TRUE if resource is up-to-date. + bool IsReady() const { return myIsSpriteReady; } + + //! Invalidate resource state. + void Invalidate() { myIsSpriteReady = false; } + + //! Return TRUE if OpenGl point sprite resource defines texture. + Standard_EXPORT bool HasPointSprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects); + + //! Return TRUE if OpenGl point sprite resource defined by obsolete Display List (bitmap). + Standard_EXPORT bool IsDisplayListSprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects); + + //! Return sprite. + Standard_EXPORT const Handle(OpenGl_PointSprite)& Sprite (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_Aspects)& theAspects, + bool theIsAlphaSprite); + //! Update texture resource up-to-date state. Standard_EXPORT void UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect); @@ -81,8 +76,8 @@ private: private: - Handle(OpenGl_TextureSet) mySprite; - Handle(OpenGl_TextureSet) mySpriteA; + Handle(OpenGl_PointSprite) mySprite; + Handle(OpenGl_PointSprite) mySpriteA; Standard_ShortReal myMarkerSize; Standard_Boolean myIsSpriteReady; diff --git a/src/OpenGl/OpenGl_AspectsTextureSet.cxx b/src/OpenGl/OpenGl_AspectsTextureSet.cxx index 1d705854bd..ac3906f738 100644 --- a/src/OpenGl/OpenGl_AspectsTextureSet.cxx +++ b/src/OpenGl/OpenGl_AspectsTextureSet.cxx @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -33,12 +33,18 @@ namespace // ======================================================================= void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx) { - if (myTextures.IsNull()) + if (myTextures[0].IsNull()) { return; } - for (OpenGl_TextureSet::Iterator aTextureIter (myTextures); aTextureIter.More(); aTextureIter.Next()) + if (!myTextures[1].IsNull()) + { + // ReleaseResource() will have no effect until nullifying all copies + myTextures[1]->InitZero(); + } + + for (OpenGl_TextureSet::Iterator aTextureIter (myTextures[0]); aTextureIter.More(); aTextureIter.Next()) { Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue(); if (aTextureRes.IsNull()) @@ -54,6 +60,8 @@ void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx) } else { + // OpenGl_PointSprite will be actually released later by OpenGl_AspectsSprite, + // see order OpenGl_Aspects::Release() const TCollection_AsciiString aName = aTextureRes->ResourceId(); aTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call theCtx->ReleaseResource (aName, Standard_True); @@ -68,23 +76,33 @@ void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx) // function : UpdateRediness // purpose : // ======================================================================= -void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_TextureSet)& theTextures) +void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect) { - const Standard_Integer aNbTexturesOld = !myTextures.IsNull() ? myTextures->Size() : 0; - const Standard_Integer aNbTexturesNew = !theTextures.IsNull() ? theTextures->Size() : 0; + const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet(); + + const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0; + Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture() + ? aNewTextureSet->Size() + : 0; + if (theAspect->IsMarkerSprite()) + { + ++aNbTexturesNew; + } + if (aNbTexturesOld != aNbTexturesNew) { myIsTextureReady = Standard_False; return; } - if (aNbTexturesOld == 0) + if (aNbTexturesOld == 0 + || !theAspect->ToMapTexture()) { return; } - Graphic3d_TextureSet::Iterator aTextureIter (theTextures); - OpenGl_TextureSet::Iterator aResIter (myTextures); - for (; aResIter.More(); aResIter.Next(), aTextureIter.Next()) + Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet); + OpenGl_TextureSet::Iterator aResIter (myTextures[0]); + for (; aTextureIter.More(); aResIter.Next(), aTextureIter.Next()) { const Handle(OpenGl_Texture)& aResource = aResIter.Value(); const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value(); @@ -122,91 +140,150 @@ void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_TextureSet // purpose : // ======================================================================= void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, - const Handle(Graphic3d_TextureSet)& theTextures) + const Handle(Graphic3d_Aspects)& theAspect, + const Handle(OpenGl_PointSprite)& theSprite, + const Handle(OpenGl_PointSprite)& theSpriteA) { + const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet(); + + const bool hasSprite = theAspect->IsMarkerSprite(); + const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0; + Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture() + ? aNewTextureSet->Size() + : 0; + if (hasSprite) + { + ++aNbTexturesNew; + } + // 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) { Release (theCtx.get()); if (aNbTexturesNew > 0) { - myTextures = new OpenGl_TextureSet (theTextures->Size()); + myTextures[0] = new OpenGl_TextureSet (aNbTexturesNew); } else { - myTextures.Nullify(); + myTextures[0].Nullify(); + myTextures[1].Nullify(); } } - if (myTextures.IsNull()) + if (myTextures[0].IsNull()) { return; } - Graphic3d_TextureSet::Iterator aTextureIter (theTextures); - OpenGl_TextureSet::Iterator aResIter (myTextures); - for (; aResIter.More(); aResIter.Next(), aTextureIter.Next()) + if (theSprite == theSpriteA) + { + myTextures[1].Nullify(); + } + else { - Handle(OpenGl_Texture)& aResource = aResIter.ChangeValue(); - const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value(); - if (!aResource.IsNull()) + if (myTextures[1].IsNull() + || myTextures[1]->Size() != myTextures[0]->Size()) { - if (!aTexture.IsNull() - && aTexture->GetId() == aResource->ResourceId() - && aTexture->Revision() != aResource->Revision()) - { - if (Handle(Image_PixMap) anImage = aTexture->GetImage()) - { - aResource->Sampler()->SetParameters (aTexture->GetParams()); - aResource->Init (theCtx, *anImage.operator->(), aTexture->Type()); - aResource->SetRevision (aTexture->Revision()); - continue; - } - } - - if (aResource->ResourceId().IsEmpty()) - { - theCtx->DelayedRelease (aResource); - aResource.Nullify(); - } - else - { - const TCollection_AsciiString aTextureKey = aResource->ResourceId(); - aResource.Nullify(); // we need nullify all handles before ReleaseResource() call - theCtx->ReleaseResource (aTextureKey, Standard_True); - } + myTextures[1] = new OpenGl_TextureSet (aNbTexturesNew); } + else + { + myTextures[1]->InitZero(); + } + } - if (!aTexture.IsNull()) + if (theAspect->ToMapTexture()) + { + Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet); + OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]); + for (; aTextureIter.More(); aResIter0.Next(), aTextureIter.Next()) { - const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId(); - if (aTextureKeyNew.IsEmpty() - || !theCtx->GetResource (aTextureKeyNew, aResource)) + Handle(OpenGl_Texture)& aResource = aResIter0.ChangeValue(); + const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value(); + if (!aResource.IsNull()) { - aResource = new OpenGl_Texture (aTextureKeyNew, aTexture->GetParams()); - if (Handle(Image_PixMap) anImage = aTexture->GetImage()) + if (!aTexture.IsNull() + && aTexture->GetId() == aResource->ResourceId() + && aTexture->Revision() != aResource->Revision()) { - aResource->Init (theCtx, *anImage.operator->(), aTexture->Type()); - aResource->SetRevision (aTexture->Revision()); + if (Handle(Image_PixMap) anImage = aTexture->GetImage()) + { + aResource->Sampler()->SetParameters (aTexture->GetParams()); + aResource->Init (theCtx, *anImage.operator->(), aTexture->Type()); + aResource->SetRevision (aTexture->Revision()); + continue; + } + } + + if (aResource->ResourceId().IsEmpty()) + { + theCtx->DelayedRelease (aResource); + aResource.Nullify(); } - if (!aTextureKeyNew.IsEmpty()) + else { - theCtx->ShareResource (aTextureKeyNew, aResource); + const TCollection_AsciiString aTextureKey = aResource->ResourceId(); + aResource.Nullify(); // we need nullify all handles before ReleaseResource() call + theCtx->ReleaseResource (aTextureKey, Standard_True); } } - else + + if (!aTexture.IsNull()) { - if (aTexture->Revision() != aResource->Revision()) + 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 + { + if (aTexture->Revision() != aResource->Revision()) + { + if (Handle(Image_PixMap) anImage = aTexture->GetImage()) + { + aResource->Init (theCtx, *anImage.operator->(), aTexture->Type()); + aResource->SetRevision (aTexture->Revision()); + } + } + aResource->Sampler()->SetParameters (aTexture->GetParams()); } - aResource->Sampler()->SetParameters (aTexture->GetParams()); } } } + + if (hasSprite) + { + myTextures[0]->ChangeLast() = theSprite; + if (!theSprite.IsNull()) + { + theSprite ->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit()); + } + if (!theSpriteA.IsNull()) + { + theSpriteA->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit()); + } + } + if (myTextures[1].IsNull()) + { + return; + } + + for (OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]), aResIter1 (myTextures[1]); aResIter0.More(); aResIter0.Next(), aResIter1.Next()) + { + aResIter1.ChangeValue() = aResIter0.Value(); + } + if (hasSprite) + { + myTextures[1]->ChangeLast() = theSpriteA; + } } diff --git a/src/OpenGl/OpenGl_AspectsTextureSet.hxx b/src/OpenGl/OpenGl_AspectsTextureSet.hxx index 9fbf3ce61f..0aa2c29c1a 100644 --- a/src/OpenGl/OpenGl_AspectsTextureSet.hxx +++ b/src/OpenGl/OpenGl_AspectsTextureSet.hxx @@ -14,11 +14,13 @@ #ifndef _OpenGl_AspectsTextureSet_Header #define _OpenGl_AspectsTextureSet_Header +#include #include #include class OpenGl_Context; class OpenGl_TextureSet; +class OpenGl_PointSprite; //! OpenGl resources for custom textures. class OpenGl_AspectsTextureSet @@ -29,20 +31,31 @@ public: //! Empty constructor. OpenGl_AspectsTextureSet() : myIsTextureReady (Standard_False) {} + //! Return TRUE if resource is up-to-date. + bool IsReady() const { return myIsTextureReady; } + + //! Invalidate resource state. + void Invalidate() { myIsTextureReady = false; } + //! Return textures array. const Handle(OpenGl_TextureSet)& TextureSet (const Handle(OpenGl_Context)& theCtx, - const Handle(Graphic3d_TextureSet)& theTextures) + const Handle(Graphic3d_Aspects)& theAspect, + const Handle(OpenGl_PointSprite)& theSprite, + const Handle(OpenGl_PointSprite)& theSpriteA, + bool theToHighlight) { if (!myIsTextureReady) { - build (theCtx, theTextures); + build (theCtx, theAspect, theSprite, theSpriteA); myIsTextureReady = true; } - return myTextures; + return theToHighlight && !myTextures[1].IsNull() + ? myTextures[1] + : myTextures[0]; } //! Update texture resource up-to-date state. - Standard_EXPORT void UpdateRediness (const Handle(Graphic3d_TextureSet)& theTextures); + Standard_EXPORT void UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect); //! Release texture resource. Standard_EXPORT void Release (OpenGl_Context* theCtx); @@ -51,11 +64,13 @@ private: //! Build texture resource. Standard_EXPORT void build (const Handle(OpenGl_Context)& theCtx, - const Handle(Graphic3d_TextureSet)& theTextures); + const Handle(Graphic3d_Aspects)& theAspect, + const Handle(OpenGl_PointSprite)& theSprite, + const Handle(OpenGl_PointSprite)& theSpriteA); private: - Handle(OpenGl_TextureSet) myTextures; + Handle(OpenGl_TextureSet) myTextures[2]; Standard_Boolean myIsTextureReady; }; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index f16fb4a8e2..48bd620f7d 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -170,6 +170,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myIsInitialized (Standard_False), myIsStereoBuffers (Standard_False), myIsGlNormalizeEnabled (Standard_False), + mySpriteTexUnit (Graphic3d_TextureUnit_0), myHasRayTracing (Standard_False), myHasRayTracingTextures (Standard_False), myHasRayTracingAdaptiveSampling (Standard_False), @@ -1481,10 +1482,21 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) } glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim); - if (IsGlGreaterEqual (1, 5)) + if (IsGlGreaterEqual (2, 0)) { glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined); } +#if !defined(GL_ES_VERSION_2_0) + else if (IsGlGreaterEqual (1, 3)) + { + // this is a maximum of texture units for FFP functionality, + // dramatically smaller than combined texture units available for GLSL + glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexCombined); + } +#endif + mySpriteTexUnit = myMaxTexCombined >= 2 + ? Graphic3d_TextureUnit_1 + : Graphic3d_TextureUnit_0; GLint aMaxVPortSize[2] = {0, 0}; glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize); diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 5733865e09..f58cb999b3 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -473,6 +473,9 @@ public: //! @return value for GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS Standard_Integer MaxCombinedTextureUnits() const { return myMaxTexCombined; } + //! @return texture unit to be used for sprites + Graphic3d_TextureUnit SpriteTextureUnit() const { return mySpriteTexUnit; } + //! @return value for GL_MAX_SAMPLES Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; } @@ -946,6 +949,7 @@ private: // context info Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag //!< Used to tell OpenGl that normals should be normalized + Graphic3d_TextureUnit mySpriteTexUnit; //!< texture unit for point sprite texture Standard_Boolean myHasRayTracing; //! indicates whether ray tracing mode is supported Standard_Boolean myHasRayTracingTextures; //! indicates whether textures in ray tracing mode are supported diff --git a/src/OpenGl/OpenGl_PointSprite.hxx b/src/OpenGl/OpenGl_PointSprite.hxx index bb8f458ccc..8573f7689a 100755 --- a/src/OpenGl/OpenGl_PointSprite.hxx +++ b/src/OpenGl/OpenGl_PointSprite.hxx @@ -24,7 +24,7 @@ DEFINE_STANDARD_HANDLE(OpenGl_PointSprite, OpenGl_Texture) //! On ancient hardware sprites will be drawn using bitmaps. class OpenGl_PointSprite : public OpenGl_Texture { - + DEFINE_STANDARD_RTTIEXT(OpenGl_PointSprite, OpenGl_Texture) public: //! Create uninitialized resource. @@ -36,6 +36,9 @@ public: //! Destroy object - will release GPU memory if any. Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE; + //! Returns TRUE for point sprite texture. + virtual bool IsPointSprite() const Standard_OVERRIDE { return true; } + //! @return true if this is display list bitmap inline Standard_Boolean IsDisplayList() const { @@ -54,10 +57,6 @@ protected: GLuint myBitmapList; //!< if of display list to draw sprite using glBitmap (for backward compatibility) -public: - - DEFINE_STANDARD_RTTIEXT(OpenGl_PointSprite,OpenGl_Texture) // Type definition - }; #endif // _OpenGl_PointSprite_H__ diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 95a76a160e..30f7cd2a67 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -592,16 +592,12 @@ void OpenGl_PrimitiveArray::drawEdges (const Handle(OpenGl_Workspace)& theWorksp void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const { const OpenGl_Aspects* anAspectMarker = theWorkspace->Aspects(); - const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull() && aCtx->ActiveProgram()->HasTessellationStage() ? GL_PATCHES : myDrawMode; - - 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()) + if (anAspectMarker->HasPointSprite (aCtx)) { // Textured markers will be drawn with the point sprites aCtx->SetPointSize (anAspectMarker->MarkerSize()); @@ -644,9 +640,14 @@ 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()->MarkerType() != Aspect_TOM_POINT - && aSpriteNorm != NULL) + else if (anAspectMarker->Aspect()->MarkerType() != Aspect_TOM_POINT) { + const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx, false); + if (aSpriteNorm.IsNull()) + { + return; + } + /**if (!isHilight && (myPArray->vcolours != NULL)) { for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++) @@ -771,7 +772,8 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace const OpenGl_Aspects* anAspectFace = theWorkspace->ApplyAspects(); const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - Handle(OpenGl_TextureSet) aTextureBack; + const bool toEnableEnvMap = !aCtx->ActiveTextures().IsNull() + && aCtx->ActiveTextures() == theWorkspace->EnvironmentTexture(); bool toDrawArray = true; int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode if (myIsFillType) @@ -818,23 +820,14 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace return; } } - - // Temporarily disable environment mapping - aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)()); } // create VBOs on first render call if (!myIsVboInit) { // compatibility - keep data to draw markers using display lists - Standard_Boolean toKeepData = Standard_False; - if (myDrawMode == GL_POINTS) - { - const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectFace->SpriteRes (aCtx); - const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast (aSpriteNormRes->First().get()) : NULL; - toKeepData = aSpriteNorm != NULL - && aSpriteNorm->IsDisplayList(); - } + Standard_Boolean toKeepData = myDrawMode == GL_POINTS + && anAspectFace->IsDisplayListSprite (aCtx); #if defined (GL_ES_VERSION_2_0) processIndices (aCtx); #endif @@ -862,28 +855,16 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace case GL_POINTS: { aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm); - const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectFace->SpriteRes (aCtx); - const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast (aSpriteNormRes->First().get()) : NULL; - if (aSpriteNorm != NULL - && !aSpriteNorm->IsDisplayList()) - { - const Handle(OpenGl_TextureSet)& aSprite = toHilight && anAspectFace->SpriteHighlightRes (aCtx)->First()->IsValid() - ? anAspectFace->SpriteHighlightRes (aCtx) - : aSpriteNormRes; - aCtx->BindTextures (aSprite); - aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectFace->ShaderProgramRes (aCtx)); - } - else - { - aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectFace->ShaderProgramRes (aCtx)); - } + aCtx->ShaderManager()->BindMarkerProgram (aCtx->ActiveTextures(), + aShadingModel, Graphic3d_AlphaMode_Opaque, + hasVertColor, anAspectFace->ShaderProgramRes (aCtx)); break; } case GL_LINES: case GL_LINE_STRIP: { aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm); - aCtx->ShaderManager()->BindLineProgram (NULL, + aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspectFace->Aspect()->LineType(), aShadingModel, Graphic3d_AlphaMode_Opaque, @@ -894,9 +875,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace default: { aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm); - const Handle(OpenGl_TextureSet)& aTextures = aCtx->ActiveTextures(); - const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture())); - aCtx->ShaderManager()->BindFaceProgram (aTextures, + aCtx->ShaderManager()->BindFaceProgram (aCtx->ActiveTextures(), aShadingModel, aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque, toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID, @@ -952,7 +931,6 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } drawArray (theWorkspace, aFaceColors, hasColorAttrib); - aCtx->BindTextures (aTextureBack); return; } diff --git a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx index e82b7858cc..8c0434b0c4 100644 --- a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx +++ b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx @@ -23,10 +23,11 @@ //! Standard GLSL program combination bits. enum OpenGl_ProgramOptions { - OpenGl_PO_Point = 0x0001, //!< point marker - OpenGl_PO_VertColor = 0x0002, //!< per-vertex color - OpenGl_PO_TextureRGB = 0x0004, //!< handle RGB texturing - OpenGl_PO_TextureA = 0x0008, //!< handle Alpha texturing (point sprites only) + OpenGl_PO_VertColor = 0x0001, //!< per-vertex color + OpenGl_PO_TextureRGB = 0x0002, //!< handle RGB texturing + OpenGl_PO_PointSimple = 0x0004, //!< point marker without sprite + OpenGl_PO_PointSprite = 0x0008, //!< point sprite with RGB image + OpenGl_PO_PointSpriteA = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite, //!< point sprite with Alpha image OpenGl_PO_TextureEnv = 0x0010, //!< handle environment map OpenGl_PO_StippleLine = 0x0020, //!< stipple line OpenGl_PO_ClipPlanes1 = 0x0040, //!< handle 1 clipping plane @@ -38,7 +39,8 @@ enum OpenGl_ProgramOptions OpenGl_PO_WriteOit = 0x0800, //!< write coverage buffer for Blended Order-Independent Transparency // OpenGl_PO_NB = 0x1000, //!< overall number of combinations - OpenGl_PO_HasTextures = OpenGl_PO_TextureRGB|OpenGl_PO_TextureA, + OpenGl_PO_IsPoint = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite|OpenGl_PO_PointSpriteA, + OpenGl_PO_HasTextures = OpenGl_PO_TextureRGB, OpenGl_PO_NeedsGeomShader = OpenGl_PO_MeshEdges, }; diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 3e8be7ffe4..5544e67f9e 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1297,6 +1298,7 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() { OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); TCollection_AsciiString aSrcVert = TCollection_AsciiString() @@ -1327,6 +1329,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); defaultGlslVersion (aProgramSrc, "font", 0); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1392,6 +1395,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit() } #endif aProgramSrc->SetId ("occt_blit"); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1483,6 +1487,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St } aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit"); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1505,14 +1510,14 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St // function : pointSpriteAlphaSrc // purpose : // ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits) +TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits) { - TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").a; }"; + TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }"; #if !defined(GL_ES_VERSION_2_0) if (myContext->core11 == NULL - && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureA) + && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA) { - aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").r; }"; + aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }"; } #else (void )theBits; @@ -1699,18 +1704,29 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());"; OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - if ((theBits & OpenGl_PO_Point) != 0) + if ((theBits & OpenGl_PO_IsPoint) != 0) { #if defined(GL_ES_VERSION_2_0) aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; #endif - if ((theBits & OpenGl_PO_HasTextures) != 0) + if ((theBits & OpenGl_PO_PointSprite) != 0) { - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) + aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); + if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA) { aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord "); }"; + EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }"; + } + else if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + && (theBits & OpenGl_PO_VertColor) == 0) + { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return VertColor; }"; } aSrcGetAlpha = pointSpriteAlphaSrc (theBits); @@ -1731,6 +1747,17 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha } else { + if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + && (theBits & OpenGl_PO_VertColor) == 0) + { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return VertColor; }"; + } + aSrcFragMainGetColor = EOL" vec4 aColor = getColor();" EOL" if (aColor.a <= 0.1) discard;" @@ -1741,6 +1768,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha { if ((theBits & OpenGl_PO_TextureRGB) != 0 || (theBits & OpenGl_PO_TextureEnv) != 0) { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); } @@ -1863,6 +1891,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha + EOL"}"; defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -1883,11 +1912,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha // function : pointSpriteShadingSrc // purpose : // ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc, - const Standard_Integer theBits) +TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, + Standard_Integer theBits) { TCollection_AsciiString aSrcFragGetColor; - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureA) + if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA) { aSrcFragGetColor = pointSpriteAlphaSrc (theBits) + EOL"vec4 getColor(void)" @@ -1898,13 +1927,13 @@ TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TColl EOL" return aColor;" EOL"}"; } - else if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) + else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite) { aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void)" EOL"{" EOL" vec4 aColor = " + theBaseColorSrc + ";" - EOL" aColor = occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ") * aColor;" + EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;" EOL" if (aColor.a <= 0.1) discard;" EOL" return aColor;" EOL"}"; @@ -2062,29 +2091,38 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }"; OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - if ((theBits & OpenGl_PO_Point) != 0) + if ((theBits & OpenGl_PO_IsPoint) != 0) { #if defined(GL_ES_VERSION_2_0) aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; #endif - if ((theBits & OpenGl_PO_HasTextures) != 0) + if ((theBits & OpenGl_PO_PointSprite) != 0) { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 != NULL - && myContext->IsGlGreaterEqual (2, 1)) - { - aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 - } - #endif + #if !defined(GL_ES_VERSION_2_0) + if (myContext->core11 != NULL + && myContext->IsGlGreaterEqual (2, 1)) + { + aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 + } + #endif + aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits); } + + if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + && (theBits & OpenGl_PO_VertColor) == 0) + { + aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }"; + } } else { if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; @@ -2141,7 +2179,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); Standard_Integer aNbLights = 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0); + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty()); aSrcVert = TCollection_AsciiString() + THE_FUNC_transformNormal + EOL @@ -2174,6 +2212,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-"; defaultGlslVersion (aProgramSrc, aProgId, theBits); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -2223,29 +2262,41 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain; TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }"; OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - if ((theBits & OpenGl_PO_Point) != 0) + if ((theBits & OpenGl_PO_IsPoint) != 0) { #if defined(GL_ES_VERSION_2_0) aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; #endif - if ((theBits & OpenGl_PO_HasTextures) != 0) + if ((theBits & OpenGl_PO_PointSprite) != 0) { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 != NULL - && myContext->IsGlGreaterEqual (2, 1)) - { - aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 - } - #endif + #if !defined(GL_ES_VERSION_2_0) + if (myContext->core11 != NULL + && myContext->IsGlGreaterEqual (2, 1)) + { + aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 + } + #endif + aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits); } + + if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + && (theBits & OpenGl_PO_VertColor) == 0) + { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }"; + } } else { if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) { + aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; @@ -2329,7 +2380,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha : EOL"#define getFinalColor getColor"; Standard_Integer aNbLights = 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0); + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty()); aSrcFrag = TCollection_AsciiString() + EOL + aSrcFragExtraOut @@ -2345,6 +2396,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + genLightKey (myLightSourceState.LightSources()) + "-"; defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -2536,6 +2588,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } defaultGlslVersion (aProgramSrc, aName, 0); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -2581,6 +2634,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox() EOL"}"; defaultGlslVersion (aProgramSrc, "bndbox", 0); + aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -2647,3 +2701,33 @@ Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl PushState (theProgram); return isBound; } + +// ======================================================================= +// function : BindMarkerProgram +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures, + Graphic3d_TypeOfShadingModel theShadingModel, + Graphic3d_AlphaMode theAlphaMode, + Standard_Boolean theHasVertColor, + const Handle(OpenGl_ShaderProgram)& theCustomProgram) +{ + if (!theCustomProgram.IsNull() + || myContext->caps->ffpEnable) + { + return bindProgramWithState (theCustomProgram); + } + + Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false); + if (!theTextures.IsNull() + && theTextures->HasPointSprite()) + { + aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite; + } + else + { + aBits |= OpenGl_PO_PointSimple; + } + Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); + return bindProgramWithState (aProgram); +} diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 3fdacc2976..5599136161 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -141,22 +141,11 @@ public: } //! Bind program for point rendering - Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures, - const Graphic3d_TypeOfShadingModel theShadingModel, - const Graphic3d_AlphaMode theAlphaMode, - const Standard_Boolean theHasVertColor, - const Handle(OpenGl_ShaderProgram)& theCustomProgram) - { - if (!theCustomProgram.IsNull() - || myContext->caps->ffpEnable) - { - return bindProgramWithState (theCustomProgram); - } - - const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false) | OpenGl_PO_Point; - Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); - return bindProgramWithState (aProgram); - } + Standard_EXPORT Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures, + Graphic3d_TypeOfShadingModel theShadingModel, + Graphic3d_AlphaMode theAlphaMode, + Standard_Boolean theHasVertColor, + const Handle(OpenGl_ShaderProgram)& theCustomProgram); //! Bind program for rendering alpha-textured font. Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram) @@ -510,10 +499,9 @@ protected: aBits |= OpenGl_PO_TextureEnv; } else if (!theTextures.IsNull() - && !theTextures->IsEmpty() - && !theTextures->First().IsNull()) + && theTextures->HasNonPointSprite()) { - aBits |= theTextures->First()->IsAlpha() ? OpenGl_PO_TextureA : OpenGl_PO_TextureRGB; + aBits |= OpenGl_PO_TextureRGB; } if (theHasVertColor && theInteriorStyle != Aspect_IS_HIDDENLINE) @@ -554,10 +542,11 @@ protected: } //! Prepare standard GLSL program for accessing point sprite alpha. - Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (const Standard_Integer theBits); + Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (Standard_Integer theBits); //! Prepare standard GLSL program for computing point sprite shading. - Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc, const Standard_Integer theBits); + Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, + Standard_Integer theBits); //! Prepare standard GLSL program for textured font. Standard_EXPORT Standard_Boolean prepareStdProgramFont(); diff --git a/src/OpenGl/OpenGl_ShaderObject.cxx b/src/OpenGl/OpenGl_ShaderObject.cxx index 783a032afd..90803f1639 100755 --- a/src/OpenGl/OpenGl_ShaderObject.cxx +++ b/src/OpenGl/OpenGl_ShaderObject.cxx @@ -49,6 +49,21 @@ static TCollection_AsciiString putLineNumbers (const TCollection_AsciiString& th return aResultSource; } +//! Return GLSL shader stage title. +static TCollection_AsciiString getShaderTypeString (GLenum theType) +{ + switch (theType) + { + case GL_VERTEX_SHADER: return "Vertex Shader"; + case GL_FRAGMENT_SHADER: return "Fragment Shader"; + case GL_GEOMETRY_SHADER: return "Geometry Shader"; + case GL_TESS_CONTROL_SHADER: return "Tessellation Control Shader"; + case GL_TESS_EVALUATION_SHADER: return "Tessellation Evaluation Shader"; + case GL_COMPUTE_SHADER: return "Compute Shader"; + } + return "Shader"; +} + // ======================================================================= // function : CreateFromSource // purpose : @@ -211,6 +226,7 @@ OpenGl_ShaderObject::~OpenGl_ShaderObject() // purpose : // ======================================================================= Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theId, const TCollection_AsciiString& theSource, bool theIsVerbose, bool theToPrintSource) @@ -227,7 +243,8 @@ Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Contex { theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, theSource); } - theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Error! Failed to set shader source"); + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error! Failed to set ") + getShaderTypeString (myType) + " [" + theId + "] source"); return false; } @@ -244,7 +261,7 @@ Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Contex aLog = "Compilation log is empty."; } theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, - TCollection_AsciiString ("Failed to compile shader object. Compilation log:\n") + aLog); + TCollection_AsciiString ("Failed to compile ") + getShaderTypeString (myType) + " [" + theId + "]. Compilation log:\n" + aLog); return false; } else if (theCtx->caps->glslWarnings) @@ -255,12 +272,24 @@ Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Contex && !aLog.IsEqual ("No errors.\n")) { theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, - TCollection_AsciiString ("Shader compilation log:\n") + aLog); + getShaderTypeString (myType) + " [" + theId + "] compilation log:\n" + aLog); } } return true; } +// ======================================================================= +// function : DumpSourceCode +// purpose : +// ======================================================================= +void OpenGl_ShaderObject::DumpSourceCode (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theId, + const TCollection_AsciiString& theSource) const +{ + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM, + getShaderTypeString (myType) + " [" + theId + "] source code:\n" + theSource); +} + // ======================================================================= // function : LoadSource // purpose : Loads shader source code @@ -467,7 +496,7 @@ Standard_Boolean OpenGl_ShaderObject::updateDebugDump (const Handle(OpenGl_Conte TCollection_AsciiString aNewSource; if (restoreShaderSource (aNewSource, aFileName)) { - LoadAndCompile (theCtx, aNewSource); + LoadAndCompile (theCtx, theProgramId, aNewSource); return Standard_True; } } diff --git a/src/OpenGl/OpenGl_ShaderObject.hxx b/src/OpenGl/OpenGl_ShaderObject.hxx index 5a2650a6cc..0d90082fb9 100755 --- a/src/OpenGl/OpenGl_ShaderObject.hxx +++ b/src/OpenGl/OpenGl_ShaderObject.hxx @@ -88,14 +88,21 @@ public: //! Wrapper for compiling shader object with verbose printing on error. //! @param theCtx bound OpenGL context + //! @param theId GLSL program id to define file name //! @param theSource source code to load //! @param theIsVerbose flag to print log on error //! @param theToPrintSource flag to print source code on error Standard_EXPORT Standard_Boolean LoadAndCompile (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theId, const TCollection_AsciiString& theSource, bool theIsVerbose = true, bool theToPrintSource = true); + //! Print source code of this shader object to messenger. + Standard_EXPORT void DumpSourceCode (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theId, + const TCollection_AsciiString& theSource) const; + //! Fetches information log of the last compile operation. Standard_EXPORT Standard_Boolean FetchInfoLog (const Handle(OpenGl_Context)& theCtx, TCollection_AsciiString& theLog); diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index b9eff19c9b..9b10c93b86 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -402,6 +402,11 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n"; + if (!myProxy.IsNull() + && myProxy->HasDefaultSampler()) + { + aHeaderConstants += "#define THE_HAS_DEFAULT_SAMPLER\n"; + } const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first + (!aHeaderVer.IsEmpty() ? "\n" : "") @@ -412,7 +417,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& + Shaders_Declarations_glsl // common declarations (global constants and Vertex Shader inputs) + Shaders_DeclarationsImpl_glsl + anIter.Value()->Source(); // the source code itself (defining main() function) - if (!aShader->LoadAndCompile (theCtx, aSource)) + if (!aShader->LoadAndCompile (theCtx, myResourceId, aSource)) { aShader->Release (theCtx.operator->()); return Standard_False; @@ -420,16 +425,6 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& if (theCtx->caps->glslDumpLevel) { - TCollection_AsciiString aShaderTypeMsg; - switch (anIter.Value()->Type()) - { - case Graphic3d_TOS_COMPUTE: { aShaderTypeMsg = "Compute shader source code:\n"; break; } - case Graphic3d_TOS_VERTEX: { aShaderTypeMsg = "Vertex shader source code:\n"; break; } - case Graphic3d_TOS_TESS_CONTROL: { aShaderTypeMsg = "Tesselation control shader source code:\n"; break; } - case Graphic3d_TOS_TESS_EVALUATION: { aShaderTypeMsg = "Tesselation evaluation shader source code:\n"; break; } - case Graphic3d_TOS_GEOMETRY: { aShaderTypeMsg = "Geometry shader source code:\n"; break; } - case Graphic3d_TOS_FRAGMENT: { aShaderTypeMsg = "Fragment shader source code:\n"; break; } - } TCollection_AsciiString anOutputSource = aSource; if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short) { @@ -441,8 +436,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& + aHeaderConstants + anIter.Value()->Source(); } - theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM, - TCollection_ExtendedString (aShaderTypeMsg + anOutputSource)); + aShader->DumpSourceCode (theCtx, myResourceId, anOutputSource); } if (!AttachShader (theCtx, aShader)) @@ -484,6 +478,14 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& { SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0)); } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerBaseColor")) + { + SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_BaseColor)); + } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerPointSprite")) + { + SetUniform (theCtx, aLocSampler, GLint(theCtx->SpriteTextureUnit())); + } const TCollection_AsciiString aSamplerNamePrefix ("occSampler"); const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB); @@ -616,7 +618,7 @@ Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCt aLog = "Linker log is empty."; } theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, - TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog); + TCollection_AsciiString ("Failed to link program object [") + myResourceId + "]! Linker log:\n" + aLog); return false; } else if (theCtx->caps->glslWarnings) @@ -627,7 +629,7 @@ Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCt && !aLog.IsEqual ("No errors.\n")) { theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, - TCollection_AsciiString ("GLSL linker log:\n") + aLog); + TCollection_AsciiString ("GLSL linker log [") + myResourceId +"]:\n" + aLog); } } return true; diff --git a/src/OpenGl/OpenGl_Texture.hxx b/src/OpenGl/OpenGl_Texture.hxx index da9ec7bb78..c077d15edd 100644 --- a/src/OpenGl/OpenGl_Texture.hxx +++ b/src/OpenGl/OpenGl_Texture.hxx @@ -453,6 +453,9 @@ public: //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules. Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE; + //! Returns TRUE for point sprite texture. + virtual bool IsPointSprite() const { return false; } + protected: //! Apply default sampler parameters after texture creation. diff --git a/src/OpenGl/OpenGl_TextureSet.cxx b/src/OpenGl/OpenGl_TextureSet.cxx index 51c3c75300..bc42d126ab 100644 --- a/src/OpenGl/OpenGl_TextureSet.cxx +++ b/src/OpenGl/OpenGl_TextureSet.cxx @@ -28,3 +28,32 @@ bool OpenGl_TextureSet::IsModulate() const || myTextures.First().IsNull() || myTextures.First()->Sampler()->Parameters()->IsModulate(); } + +// ======================================================================= +// function : HasNonPointSprite +// purpose : +// ======================================================================= +bool OpenGl_TextureSet::HasNonPointSprite() const +{ + if (myTextures.IsEmpty()) + { + return false; + } + else if (myTextures.Size() == 1) + { + return !myTextures.First().IsNull() + && !myTextures.First()->IsPointSprite(); + } + return !myTextures.First().IsNull(); +} + +// ======================================================================= +// function : HasPointSprite +// purpose : +// ======================================================================= +bool OpenGl_TextureSet::HasPointSprite() const +{ + return !myTextures.IsEmpty() + && !myTextures.Last().IsNull() + && myTextures.Last()->IsPointSprite(); +} diff --git a/src/OpenGl/OpenGl_TextureSet.hxx b/src/OpenGl/OpenGl_TextureSet.hxx index d7c4c5aedb..748ba7da96 100644 --- a/src/OpenGl/OpenGl_TextureSet.hxx +++ b/src/OpenGl/OpenGl_TextureSet.hxx @@ -75,6 +75,12 @@ public: //! Return the first texture. Handle(OpenGl_Texture)& ChangeFirst() { return myTextures.ChangeFirst(); } + //! Return the last texture. + const Handle(OpenGl_Texture)& Last() const { return myTextures.Last(); } + + //! Return the last texture. + Handle(OpenGl_Texture)& ChangeLast() { return myTextures.ChangeLast(); } + //! Return the texture at specified position within [0, Size()) range. const Handle(OpenGl_Texture)& Value (Standard_Integer theIndex) const { return myTextures.Value (theIndex); } @@ -85,6 +91,18 @@ public: //! or if texture is not set at all. Standard_EXPORT bool IsModulate() const; + //! Return TRUE if other than point sprite textures are defined within point set. + Standard_EXPORT bool HasNonPointSprite() const; + + //! Return TRUE if last texture is a point sprite. + Standard_EXPORT bool HasPointSprite() const; + + //! Nullify all handles. + void InitZero() + { + myTextures.Init (Handle(OpenGl_Texture)()); + } + protected: NCollection_Array1 myTextures; diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 3185033a1c..7245548bea 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -1450,9 +1450,9 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS myPostFSAAShaderSource.SetPrefix (aPrefixString); myOutImageShaderSource.SetPrefix (aPrefixString); - if (!myRaytraceShader->LoadAndCompile (theGlContext, myRaytraceShaderSource.Source()) - || !myPostFSAAShader->LoadAndCompile (theGlContext, myPostFSAAShaderSource.Source()) - || !myOutImageShader->LoadAndCompile (theGlContext, myOutImageShaderSource.Source())) + if (!myRaytraceShader->LoadAndCompile (theGlContext, myRaytraceProgram->ResourceId(), myRaytraceShaderSource.Source()) + || !myPostFSAAShader->LoadAndCompile (theGlContext, myPostFSAAProgram->ResourceId(), myPostFSAAShaderSource.Source()) + || !myOutImageShader->LoadAndCompile (theGlContext, myOutImageProgram->ResourceId(), myOutImageShaderSource.Source())) { return safeFailBack ("Failed to compile ray-tracing fragment shaders", theGlContext); } diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index 2e82f08374..44451b4937 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -305,9 +305,11 @@ const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects() myGlContext->SetShadingMaterial (myAspectsSet, myHighlightStyle); } - if (myAspectsSet->Aspect()->ToMapTexture()) + const Handle(OpenGl_TextureSet)& aTextureSet = myAspectsSet->TextureSet (myGlContext, ToHighlight()); + if (!aTextureSet.IsNull() + || myAspectsSet->Aspect()->ToMapTexture()) { - myGlContext->BindTextures (myAspectsSet->TextureSet (myGlContext)); + myGlContext->BindTextures (aTextureSet); } else { diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index d214e4a403..05eafa88b0 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -139,9 +139,11 @@ vec4 occBackMaterial_Specular(void); //!< Specular reflection float occBackMaterial_Shininess(void); //!< Specular exponent float occBackMaterial_Transparency(void); //!< Transparency coefficient +#ifdef THE_HAS_DEFAULT_SAMPLER #define occActiveSampler occSampler0 //!< alias for backward compatibility #define occSamplerBaseColor occSampler0 //!< alias to a base color texture uniform sampler2D occSampler0; //!< current active sampler; +#endif //! 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? diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index f8de26c38b..39929a58fc 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -142,9 +142,11 @@ static const char Shaders_Declarations_glsl[] = "float occBackMaterial_Shininess(void); //!< Specular exponent\n" "float occBackMaterial_Transparency(void); //!< Transparency coefficient\n" "\n" + "#ifdef THE_HAS_DEFAULT_SAMPLER\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" + "#endif\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" diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index 0c16c2293c..aec48cdc60 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -5600,6 +5600,7 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, Standard_Boolean toRandColors = Standard_False; Standard_Boolean hasNormals = Standard_True; Standard_Boolean isSetArgNorm = Standard_False; + Standard_Boolean hasUV = Standard_False; for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter) { Standard_CString anArg = theArgs[anArgIter]; @@ -5633,9 +5634,27 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, isSetArgNorm = Standard_True; hasNormals = Standard_False; } + else if (aFlag == "-uv" + || aFlag == "-texels") + { + hasUV = Standard_True; + } } Standard_CString aName = theArgs[1]; + Graphic3d_ArrayFlags aFlags = Graphic3d_ArrayFlags_None; + if (hasNormals) + { + aFlags |= Graphic3d_ArrayFlags_VertexNormal; + } + if (toRandColors) + { + aFlags |= Graphic3d_ArrayFlags_VertexColor; + } + if (hasUV) + { + aFlags |= Graphic3d_ArrayFlags_VertexTexel; + } // generate arbitrary set of points Handle(Graphic3d_ArrayOfPoints) anArrayPoints; @@ -5668,7 +5687,7 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, return 1; } - anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, toRandColors, hasNormals); + anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags); for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current()); @@ -5714,6 +5733,11 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, { anArrayPoints->SetVertexNormal (anIndexOfPoint, aNormals (aNodeIter)); } + if (hasUV + && aTriangulation->HasUVNodes()) + { + anArrayPoints->SetVertexTexel (anIndexOfPoint, aTriangulation->UVNode (aNodeIter)); + } } } } @@ -5737,7 +5761,7 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, gp_Pnt aCenter(aCenterX, aCenterY, aCenterZ); - anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, toRandColors, hasNormals); + anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags); for (Standard_Integer aPntIt = 0; aPntIt < aNbPoints; ++aPntIt) { Standard_Real anAlpha = (Standard_Real (rand() % 2000) / 1000.0) * M_PI; @@ -5762,6 +5786,11 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI, { anArrayPoints->SetVertexNormal (anIndexOfPoint, aDir); } + if (hasUV) + { + anArrayPoints->SetVertexTexel (anIndexOfPoint, gp_Pnt2d (anAlpha / 2.0 * M_PI, + aBeta / 2.0 * M_PI)); + } } } @@ -6367,12 +6396,12 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) __FILE__, VVertexMode, group); theCommands.Add ("vpointcloud", - "vpointcloud name shape [-randColor] [-normals] [-noNormals]" + "vpointcloud name shape [-randColor] [-normals] [-noNormals] [-uv]" "\n\t\t: Create an interactive object for arbitary set of points" "\n\t\t: from triangulated shape." "\n" "vpointcloud name x y z r npts {surface|volume}\n" - " ... [-randColor] [-normals] [-noNormals]" + " ... [-randColor] [-normals] [-noNormals] [-uv]" "\n\t\t: Create arbitrary set of points (npts) randomly distributed" "\n\t\t: on spheric surface or within spheric volume (x y z r)." "\n\t\t:" diff --git a/tests/v3d/point_cloud/sphere b/tests/v3d/point_cloud/sphere index 70dd27a1e3..bcd3d98ded 100644 --- a/tests/v3d/point_cloud/sphere +++ b/tests/v3d/point_cloud/sphere @@ -22,6 +22,16 @@ vdump $::imagedir/${::casename}_green.png vpointcloud p s -randcolors vdump $::imagedir/${::casename}_rand.png +# texture mapping +vpointcloud p s -normals -uv +vtexture p 0 +vaspects p -shadingModel GOURAUD +vdump $::imagedir/${::casename}_tex3.png +vaspects p -shadingModel PHONG +vdump $::imagedir/${::casename}_tex2.png +vaspects p -shadingModel UNLIT +vdump $::imagedir/${::casename}_tex1.png + # mode with normals vpointcloud p s -normals vsetmaterial p COPPER