diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 494616ae23..44b8a46a05 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -31,6 +31,17 @@ Graphic3d_Group_2.cxx Graphic3d_Group_8.cxx Graphic3d_Group_10.cxx Graphic3d_Structure.pxx +Graphic3d_ShaderObject.hxx +Graphic3d_ShaderObject.cxx +Graphic3d_ShaderProgram.hxx +Graphic3d_ShaderProgram.cxx +Graphic3d_ShaderVariable.hxx +Graphic3d_ShaderVariable.cxx +Graphic3d_ShaderVariable.lxx +Graphic3d_ShaderObject_Handle.hxx +Graphic3d_ShaderProgram_Handle.hxx +Graphic3d_ShaderVariable_Handle.hxx +Graphic3d_TypeOfShaderObject.hxx Graphic3d_DataStructure.pxx Graphic3d_StructureManager.pxx Graphic3d.edl @@ -57,4 +68,4 @@ Graphic3d_ClipPlane.hxx Graphic3d_ClipPlane.cxx Graphic3d_ClipPlane_Handle.hxx Graphic3d_SetOfHClipPlane.hxx -Graphic3d_SetOfHClipPlane_Handle.hxx \ No newline at end of file +Graphic3d_SetOfHClipPlane_Handle.hxx diff --git a/src/Graphic3d/Graphic3d.cdl b/src/Graphic3d/Graphic3d.cdl index aa39c28450..e7cd6326c0 100755 --- a/src/Graphic3d/Graphic3d.cdl +++ b/src/Graphic3d/Graphic3d.cdl @@ -584,6 +584,9 @@ is imported NListOfHAsciiString; ---Category: Instantiated classes + imported ShaderProgram_Handle; + ---Category: Instantiated classes + imported SetOfHClipPlane; ---Category: Instantiated classes -- Set of handles on clip planes diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.cdl b/src/Graphic3d/Graphic3d_AspectFillArea3d.cdl index fa18c378ee..7aeb9d0880 100755 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.cdl +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.cdl @@ -42,14 +42,16 @@ class AspectFillArea3d from Graphic3d inherits AspectFillArea from Aspect uses - Color from Quantity, - Ratio from Quantity, + Color from Quantity, + Ratio from Quantity, - TypeOfLine from Aspect, - InteriorStyle from Aspect, + TypeOfLine from Aspect, + InteriorStyle from Aspect, - MaterialAspect from Graphic3d, - TextureMap from Graphic3d + MaterialAspect from Graphic3d, + TextureMap from Graphic3d, + + ShaderProgram_Handle from Graphic3d is @@ -189,6 +191,12 @@ is -- Consult OpenGL reference for details (glPolygonOffset function description). ---Category: Methods to modify the class definition + SetShaderProgram ( me : mutable; + theProgram : ShaderProgram_Handle from Graphic3d ); + ---Level: Public + ---Purpose: Sets up OpenGL/GLSL shader program. + ---Category: Methods to modify the class definition + ---------------------------- -- Category: Inquire methods ---------------------------- @@ -244,9 +252,12 @@ is aUnits : out ShortReal from Standard ); ---Level: Public ---Purpose: Returns current polygon offsets settings. - ---Category: Inquire methods - - + ---Category: Inquire methods + + ShaderProgram ( me ) + returns ShaderProgram_Handle from Graphic3d; + ---C++: return const & + -- fields @@ -290,4 +301,6 @@ fields MyPolygonOffsetFactor : ShortReal from Standard; MyPolygonOffsetUnits : ShortReal from Standard; + MyShaderProgram : ShaderProgram_Handle from Graphic3d; + end AspectFillArea3d; diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx index b5ec0539d9..1c9ea073b8 100755 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx @@ -180,3 +180,13 @@ void Graphic3d_AspectFillArea3d::PolygonOffsets(Standard_Integer& aMode, aFactor = MyPolygonOffsetFactor; aUnits = MyPolygonOffsetUnits; } + +void Graphic3d_AspectFillArea3d::SetShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProgram) +{ + MyShaderProgram = theProgram; +} + +const Handle(Graphic3d_ShaderProgram)& Graphic3d_AspectFillArea3d::ShaderProgram() const +{ + return MyShaderProgram; +} diff --git a/src/Graphic3d/Graphic3d_AspectLine3d.cdl b/src/Graphic3d/Graphic3d_AspectLine3d.cdl index a96f3e9b55..4f5d288c34 100755 --- a/src/Graphic3d/Graphic3d_AspectLine3d.cdl +++ b/src/Graphic3d/Graphic3d_AspectLine3d.cdl @@ -29,9 +29,9 @@ class AspectLine3d from Graphic3d inherits AspectLine from Aspect uses - Color from Quantity, - - TypeOfLine from Aspect + Color from Quantity, + TypeOfLine from Aspect, + ShaderProgram_Handle from Graphic3d is @@ -58,9 +58,16 @@ is -- factor to this nominal line width. -- The supported linewidths vary by 1-pixel units. --- + SetShaderProgram ( me : mutable; + theProgram : ShaderProgram_Handle from Graphic3d ); + ---Level: Public + ---Purpose: Sets up OpenGL/GLSL shader program. --- fields + ShaderProgram ( me ) + returns ShaderProgram_Handle from Graphic3d; + ---C++: return const & + +fields -- -- Class : Graphic3d_AspectLine3d @@ -75,4 +82,6 @@ is -- defined by AspectLine. -- + MyShaderProgram : ShaderProgram_Handle from Graphic3d; + end AspectLine3d; diff --git a/src/Graphic3d/Graphic3d_AspectLine3d.cxx b/src/Graphic3d/Graphic3d_AspectLine3d.cxx index 7628e3657b..b66d6fac01 100755 --- a/src/Graphic3d/Graphic3d_AspectLine3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectLine3d.cxx @@ -58,3 +58,13 @@ Graphic3d_AspectLine3d::Graphic3d_AspectLine3d () { // initialisation of AspectLine with AColor, AType, AWidth. Graphic3d_AspectLine3d::Graphic3d_AspectLine3d (const Quantity_Color& AColor, const Aspect_TypeOfLine AType, const Standard_Real AWidth):Aspect_AspectLine (AColor, AType, AWidth) {} + +void Graphic3d_AspectLine3d::SetShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProgram) +{ + MyShaderProgram = theProgram; +} + +const Handle(Graphic3d_ShaderProgram)& Graphic3d_AspectLine3d::ShaderProgram() const +{ + return MyShaderProgram; +} diff --git a/src/Graphic3d/Graphic3d_AspectMarker3d.cdl b/src/Graphic3d/Graphic3d_AspectMarker3d.cdl index c33e785545..7f53fffdd0 100755 --- a/src/Graphic3d/Graphic3d_AspectMarker3d.cdl +++ b/src/Graphic3d/Graphic3d_AspectMarker3d.cdl @@ -32,11 +32,12 @@ class AspectMarker3d from Graphic3d inherits AspectMarker from Aspect uses - Color from Quantity, - TypeOfMarker from Aspect, - HArray1OfByte from TColStd, - PixMap_Handle from Image, - MarkerImage_Handle from Graphic3d + Color from Quantity, + TypeOfMarker from Aspect, + HArray1OfByte from TColStd, + PixMap_Handle from Image, + MarkerImage_Handle from Graphic3d, + ShaderProgram_Handle from Graphic3d is @@ -89,6 +90,15 @@ is theHeight : Integer from Standard; theTexture: HArray1OfByte from TColStd ) is static; + SetShaderProgram ( me : mutable; + theProgram : ShaderProgram_Handle from Graphic3d ); + ---Level: Public + ---Purpose: Sets up OpenGL/GLSL shader program. + + ShaderProgram ( me ) + returns ShaderProgram_Handle from Graphic3d; + ---C++: return const & + fields -- @@ -105,4 +115,6 @@ fields myMarkerImage : MarkerImage_Handle from Graphic3d is protected; +MyShaderProgram : ShaderProgram_Handle from Graphic3d; + end AspectMarker3d; diff --git a/src/Graphic3d/Graphic3d_AspectMarker3d.cxx b/src/Graphic3d/Graphic3d_AspectMarker3d.cxx index fa602f5d03..c5850435e9 100755 --- a/src/Graphic3d/Graphic3d_AspectMarker3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectMarker3d.cxx @@ -99,3 +99,21 @@ void Graphic3d_AspectMarker3d::SetBitMap (const Standard_Integer theWidth, myMarkerImage.Nullify(); myMarkerImage = new Graphic3d_MarkerImage (theTextureBitMap, theWidth, theHeight); } + +// ======================================================================= +// function : SetShaderProgram +// purpose : +// ======================================================================= +void Graphic3d_AspectMarker3d::SetShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProgram) +{ + MyShaderProgram = theProgram; +} + +// ======================================================================= +// function : ShaderProgram +// purpose : +// ======================================================================= +const Handle(Graphic3d_ShaderProgram)& Graphic3d_AspectMarker3d::ShaderProgram() const +{ + return MyShaderProgram; +} diff --git a/src/Graphic3d/Graphic3d_AspectText3d.cdl b/src/Graphic3d/Graphic3d_AspectText3d.cdl index e20cb2d886..758ebf25e6 100755 --- a/src/Graphic3d/Graphic3d_AspectText3d.cdl +++ b/src/Graphic3d/Graphic3d_AspectText3d.cdl @@ -36,11 +36,12 @@ class AspectText3d from Graphic3d inherits TShared uses - Color from Quantity, - TypeOfStyleText from Aspect, - TypeOfDisplayText from Aspect, - AsciiString from TCollection, - FontAspect from Font + Color from Quantity, + TypeOfStyleText from Aspect, + TypeOfDisplayText from Aspect, + AsciiString from TCollection, + FontAspect from Font, + ShaderProgram_Handle from Graphic3d raises @@ -178,11 +179,10 @@ is ---Level: Public ---Purpose: Returns text FontAspect - - - - - + SetShaderProgram ( me : mutable; + theProgram : ShaderProgram_Handle from Graphic3d ); + ---Level: Public + ---Purpose: Sets up OpenGL/GLSL shader program. ---------------------------- -- Category: Inquire methods @@ -245,7 +245,11 @@ is ---Purpose: Returns the current values of the group . ---Category: Inquire methods --- + ShaderProgram ( me ) + returns ShaderProgram_Handle from Graphic3d; + ---C++: return const & + +-- fields @@ -292,4 +296,6 @@ fields -- the variable turning FontAspect of the text MyTextFontAspect : FontAspect from Font; + MyShaderProgram : ShaderProgram_Handle from Graphic3d; + end AspectText3d; diff --git a/src/Graphic3d/Graphic3d_AspectText3d.cxx b/src/Graphic3d/Graphic3d_AspectText3d.cxx index 687da55f1b..77905c1cd1 100755 --- a/src/Graphic3d/Graphic3d_AspectText3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectText3d.cxx @@ -253,5 +253,12 @@ void Graphic3d_AspectText3d::Values ( Quantity_Color& AColor, } +void Graphic3d_AspectText3d::SetShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProgram) +{ + MyShaderProgram = theProgram; +} - +const Handle(Graphic3d_ShaderProgram)& Graphic3d_AspectText3d::ShaderProgram() const +{ + return MyShaderProgram; +} diff --git a/src/Graphic3d/Graphic3d_CGroup.hxx b/src/Graphic3d/Graphic3d_CGroup.hxx index 2ce7a2f790..c9619927b2 100755 --- a/src/Graphic3d/Graphic3d_CGroup.hxx +++ b/src/Graphic3d/Graphic3d_CGroup.hxx @@ -23,6 +23,7 @@ #include #include #include +#include class Graphic3d_CStructure; @@ -80,6 +81,8 @@ public: float PolygonOffsetFactor; float PolygonOffsetUnits; + Handle(Graphic3d_ShaderProgram) ShaderProgram; + }; class CALL_DEF_CONTEXTMARKER @@ -104,6 +107,7 @@ public: Aspect_TypeOfMarker MarkerType; Standard_ShortReal Scale; Handle(Graphic3d_MarkerImage) MarkerImage; + Handle(Graphic3d_ShaderProgram) ShaderProgram; }; diff --git a/src/Graphic3d/Graphic3d_Group_8.cxx b/src/Graphic3d/Graphic3d_Group_8.cxx index 5e93b1a4d0..9528958e23 100755 --- a/src/Graphic3d/Graphic3d_Group_8.cxx +++ b/src/Graphic3d/Graphic3d_Group_8.cxx @@ -46,6 +46,7 @@ #include #include #include +#include //-Methods, in order @@ -68,13 +69,14 @@ void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectLin MyCGroup.ContextLine.Width = float (AWidth); MyCGroup.ContextLine.IsDef = 1; + MyCGroup.ContextLine.ShaderProgram = CTX->ShaderProgram(); + int noinsert = 1; MyGraphicDriver->LineContextGroup (MyCGroup, noinsert); MyCGroup.ContextLine.IsSet = 1; Update (); - } void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& CTX) { @@ -277,13 +279,14 @@ void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectFil MyCGroup.ContextFillArea.PolygonOffsetUnits = aPolyUnits; // OCC4895 SAN 22/03/04 High-level interface for controlling polygon offsets + MyCGroup.ContextFillArea.ShaderProgram = CTX->ShaderProgram(); + int noinsert = 1; MyGraphicDriver->FaceContextGroup (MyCGroup, noinsert); MyCGroup.ContextFillArea.IsSet = 1; - Update (); - + Update(); } void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& theCtx) @@ -306,6 +309,8 @@ void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectMar MyCGroup.ContextMarker.Scale = Standard_ShortReal (aScale); MyCGroup.ContextMarker.MarkerImage = theCtx->GetMarkerImage(); + MyCGroup.ContextMarker.ShaderProgram = theCtx->ShaderProgram(); + int noinsert = 1; MyGraphicDriver->MarkerContextGroup (MyCGroup, noinsert); @@ -350,6 +355,8 @@ void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectTex MyCGroup.ContextText.TextAngle = float (ATextAngle); MyCGroup.ContextText.TextFontAspect = (int)ATextFontAspect; + MyCGroup.ContextText.ShaderProgram = CTX->ShaderProgram(); + MyCGroup.ContextText.IsDef = 1; int noinsert = 1; @@ -358,7 +365,6 @@ void Graphic3d_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectTex MyCGroup.ContextText.IsSet = 1; Update (); - } void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& CTX) { @@ -380,13 +386,14 @@ void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& MyCGroup.ContextLine.Width = float (AWidth); MyCGroup.ContextLine.IsDef = 1; + MyCGroup.ContextLine.ShaderProgram = CTX->ShaderProgram(); + int noinsert = 0; MyGraphicDriver->LineContextGroup (MyCGroup, noinsert); MyCGroup.ContextLine.IsSet = 1; Update (); - } void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& CTX) { @@ -584,13 +591,14 @@ void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectFillArea MyCGroup.ContextFillArea.PolygonOffsetUnits = (Standard_ShortReal)aPolyUnits; // OCC4895 SAN 22/03/04 High-level interface for controlling polygon offsets + MyCGroup.ContextFillArea.ShaderProgram = CTX->ShaderProgram(); + int noinsert = 0; MyGraphicDriver->FaceContextGroup (MyCGroup, noinsert); MyCGroup.ContextFillArea.IsSet = 1; Update (); - } void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& thCtx) @@ -613,6 +621,8 @@ void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d MyCGroup.ContextMarker.Scale = Standard_ShortReal (aScale); MyCGroup.ContextMarker.MarkerImage = thCtx->GetMarkerImage(); + MyCGroup.ContextMarker.ShaderProgram = thCtx->ShaderProgram(); + int noinsert = 0; MyGraphicDriver->MarkerContextGroup (MyCGroup, noinsert); @@ -658,13 +668,14 @@ void Graphic3d_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectText3d)& MyCGroup.ContextText.TextFontAspect = (int)ATextFontAspect; MyCGroup.ContextText.IsDef = 1; + MyCGroup.ContextText.ShaderProgram = CTX->ShaderProgram(); + int noinsert = 0; MyGraphicDriver->TextContextGroup (MyCGroup, noinsert); MyCGroup.ContextText.IsSet = 1; - Update (); - + Update(); } Standard_Boolean Graphic3d_Group::IsGroupPrimitivesAspectSet (const Graphic3d_GroupAspect theAspect) const { diff --git a/src/Graphic3d/Graphic3d_ShaderObject.cxx b/src/Graphic3d/Graphic3d_ShaderObject.cxx new file mode 100644 index 0000000000..f83ab1002c --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderObject.cxx @@ -0,0 +1,96 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include +#include +#include +#include +#include + +namespace +{ + static volatile Standard_Integer THE_SHADER_OBJECT_COUNTER = 0; +}; + +IMPLEMENT_STANDARD_HANDLE (Graphic3d_ShaderObject, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderObject, Standard_Transient) + +// ======================================================================= +// function : Graphic3d_ShaderObject +// purpose : Creates a shader object from specified file +// ======================================================================= +Graphic3d_ShaderObject::Graphic3d_ShaderObject (const Graphic3d_TypeOfShaderObject theType) +: myType (theType) +{ + myID = TCollection_AsciiString ("Graphic3d_ShaderObject_") + + TCollection_AsciiString (Standard_Atomic_Increment (&THE_SHADER_OBJECT_COUNTER)); +} + +// ======================================================================= +// function : CreatFromFile +// purpose : Creates new shader object from specified file +// ======================================================================= +Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromFile (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& thePath) +{ + Handle(Graphic3d_ShaderObject) aShader = new Graphic3d_ShaderObject (theType); + aShader->myPath = thePath; + + OSD_File aFile (thePath); + if (!aFile.Exists()) + { + return NULL; + } + + aFile.Open (OSD_ReadOnly, OSD_Protection()); + aFile.Read (aShader->mySource, aFile.Size()); + aFile.Close(); + + return aShader; +} + +// ======================================================================= +// function : CreatFromSource +// purpose : Creates new shader object from specified source +// ======================================================================= +Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromSource (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& theSource) +{ + Handle(Graphic3d_ShaderObject) aShader = new Graphic3d_ShaderObject (theType); + aShader->mySource = theSource; + return aShader; +} + +// ======================================================================= +// function : ~Graphic3d_ShaderObject +// purpose : Releases resources of shader object +// ======================================================================= +Graphic3d_ShaderObject::~Graphic3d_ShaderObject() +{ + // +} + +// ======================================================================= +// function : IsDone +// purpose : Checks if the shader object is valid or not +// ======================================================================= +Standard_Boolean Graphic3d_ShaderObject::IsDone() const +{ + return !mySource.IsEmpty(); +} diff --git a/src/Graphic3d/Graphic3d_ShaderObject.hxx b/src/Graphic3d/Graphic3d_ShaderObject.hxx new file mode 100644 index 0000000000..0f63f7fafb --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderObject.hxx @@ -0,0 +1,80 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Graphic3d_ShaderObject_HeaderFile +#define _Graphic3d_ShaderObject_HeaderFile + +#include + +#include +#include + +//! This class is responsible for managing shader objects. +class Graphic3d_ShaderObject : public Standard_Transient +{ +private: + + //! Creates new shader object of specified type. + Standard_EXPORT Graphic3d_ShaderObject (const Graphic3d_TypeOfShaderObject theType); + +public: + + //! Releases resources of shader object. + Standard_EXPORT virtual ~Graphic3d_ShaderObject(); + + //! Checks if the shader object is valid or not. + Standard_EXPORT virtual Standard_Boolean IsDone() const; + + //! Returns the full path to the shader source. + const OSD_Path& Path() const { return myPath; } + + //! Returns the source code of the shader object. + const TCollection_AsciiString& Source() const { return mySource; } + + //! Returns type of the shader object. + Graphic3d_TypeOfShaderObject Type() const { return myType; } + + //! Returns unique ID used to manage resource in graphic driver. + const TCollection_AsciiString& GetId() const { return myID; } + + //! Creates new shader object from specified file. + Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromFile (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& thePath); + + //! Creates new shader object from specified source. + Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromSource (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& theSource); + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_ShaderObject) + +protected: + + TCollection_AsciiString myID; //!< the ID of shader object + TCollection_AsciiString mySource; //!< the source code of shader object + OSD_Path myPath; //!< the path to shader source (may be empty) + +private: + + //! The type of shader object. + Graphic3d_TypeOfShaderObject myType; +}; + +#endif diff --git a/src/Graphic3d/Graphic3d_ShaderObject_Handle.hxx b/src/Graphic3d/Graphic3d_ShaderObject_Handle.hxx new file mode 100644 index 0000000000..1b8295e419 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderObject_Handle.hxx @@ -0,0 +1,30 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_Graphic3d_ShaderObject_HeaderFile +#define _Handle_Graphic3d_ShaderObject_HeaderFile + +#include + +class Graphic3d_ShaderObject; +DEFINE_STANDARD_HANDLE (Graphic3d_ShaderObject, Standard_Transient) + +typedef Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject_Handle; + +#endif diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx new file mode 100644 index 0000000000..29aa9c73e0 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -0,0 +1,132 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include +#include + +#include +#include +#include + +namespace +{ + static volatile Standard_Integer THE_PROGRAM_OBJECT_COUNTER = 0; +}; + +IMPLEMENT_STANDARD_HANDLE (Graphic3d_ShaderProgram, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderProgram, Standard_Transient) + +// ======================================================================= +// function : Graphic3d_ShaderProgram +// purpose : Creates new empty program object +// ======================================================================= +Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() +{ + myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_") + + TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER)); +} + +// ======================================================================= +// function : ~Graphic3d_ShaderProgram +// purpose : Releases resources of program object +// ======================================================================= +Graphic3d_ShaderProgram::~Graphic3d_ShaderProgram() +{ + Destroy(); +} + +// ======================================================================= +// function : Destroy +// purpose : Releases resources of program object +// ======================================================================= +void Graphic3d_ShaderProgram::Destroy() const +{ } + +// ======================================================================= +// function : IsDone +// purpose : Checks if the program object is valid or not +// ======================================================================= +Standard_Boolean Graphic3d_ShaderProgram::IsDone() const +{ + if (myShaderObjects.IsEmpty()) + { + return Standard_False; + } + + for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next()) + { + if (!anIt.Value()->IsDone()) + return Standard_False; + } + + return Standard_True; +} + +// ======================================================================= +// function : AttachShader +// purpose : Attaches shader object to the program object +// ======================================================================= +Standard_Boolean Graphic3d_ShaderProgram::AttachShader (const Handle(Graphic3d_ShaderObject)& theShader) +{ + if (theShader.IsNull()) + { + return Standard_False; + } + + for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next()) + { + if (anIt.Value() == theShader) + return Standard_False; + } + + myShaderObjects.Append (theShader); + return Standard_True; +} + +// ======================================================================= +// function : DetachShader +// purpose : Detaches shader object from the program object +// ======================================================================= +Standard_Boolean Graphic3d_ShaderProgram::DetachShader (const Handle(Graphic3d_ShaderObject)& theShader) +{ + if (theShader.IsNull()) + { + return Standard_False; + } + + for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next()) + { + if (anIt.Value() == theShader) + { + myShaderObjects.Remove (anIt); + return Standard_True; + } + } + + return Standard_False; +} + +// ======================================================================= +// function : ClearVariables +// purpose : Removes all custom uniform variables from the program +// ======================================================================= +void Graphic3d_ShaderProgram::ClearVariables() +{ + myVariables.Clear(); +} diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx new file mode 100644 index 0000000000..ac816f5395 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -0,0 +1,104 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Graphic3d_ShaderProgram_HeaderFile +#define _Graphic3d_ShaderProgram_HeaderFile + +#include +#include +#include +#include + +//! List of shader objects. +typedef NCollection_Sequence Graphic3d_ShaderObjectList; + +//! List of custom uniform shader variables. +typedef NCollection_Sequence Graphic3d_ShaderVariableList; + +//! This class is responsible for managing shader programs. +class Graphic3d_ShaderProgram : public Standard_Transient +{ +public: + + //! Creates new empty program object. + Standard_EXPORT Graphic3d_ShaderProgram(); + + //! Releases resources of program object. + Standard_EXPORT virtual ~Graphic3d_ShaderProgram(); + + //! Releases resources of program object. + Standard_EXPORT void Destroy() const; + + //! Checks if the program object is valid or not. + Standard_EXPORT virtual Standard_Boolean IsDone() const; + + //! Returns unique ID used to manage resource in graphic driver. + const TCollection_AsciiString& GetId() const { return myID; } + + //! Attaches shader object to the program object. + Standard_EXPORT Standard_Boolean AttachShader (const Handle(Graphic3d_ShaderObject)& theShader); + + //! Detaches shader object from the program object. + Standard_EXPORT Standard_Boolean DetachShader (const Handle(Graphic3d_ShaderObject)& theShader); + + //! Returns list of attached shader objects. + const Graphic3d_ShaderObjectList& ShaderObjects() const { return myShaderObjects; } + + //! Returns list of custom uniform variables. + const Graphic3d_ShaderVariableList& Variables() const { return myVariables; } + + //! Pushes custom uniform variable to the program. + template + Standard_Boolean PushVariable (const TCollection_AsciiString& theName, + const T& theValue); + + //! Removes all custom uniform variables from the program. + Standard_EXPORT void ClearVariables(); + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_ShaderProgram) + +private: + + TCollection_AsciiString myID; //!< The unique identifier of program object. + Graphic3d_ShaderObjectList myShaderObjects; //!< the list of attached shader objects. + Graphic3d_ShaderVariableList myVariables; //!< the list of custom uniform variables. + +}; + +// ======================================================================= +// function : PushVariable +// purpose : Pushes custom uniform variable to the program +// ======================================================================= +template inline +Standard_Boolean Graphic3d_ShaderProgram::PushVariable (const TCollection_AsciiString& theName, + const T& theValue) +{ + Handle(Graphic3d_ShaderVariable) aVariable = Graphic3d_ShaderVariable::Create (theName, theValue); + if (aVariable.IsNull() || !aVariable->IsDone()) + { + return Standard_False; + } + + myVariables.Append (aVariable); + return Standard_True; +} + +#endif diff --git a/src/Graphic3d/Graphic3d_ShaderProgram_Handle.hxx b/src/Graphic3d/Graphic3d_ShaderProgram_Handle.hxx new file mode 100644 index 0000000000..f75f8fce35 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderProgram_Handle.hxx @@ -0,0 +1,30 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_Graphic3d_ShaderProgram_HeaderFile +#define _Handle_Graphic3d_ShaderProgram_HeaderFile + +#include + +class Graphic3d_ShaderProgram; +DEFINE_STANDARD_HANDLE (Graphic3d_ShaderProgram, Standard_Transient) + +typedef Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderProgram_Handle; + +#endif diff --git a/src/Graphic3d/Graphic3d_ShaderVariable.cxx b/src/Graphic3d/Graphic3d_ShaderVariable.cxx new file mode 100644 index 0000000000..f11661c0ee --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderVariable.cxx @@ -0,0 +1,93 @@ +// Created on: 2013-09-25 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include + +#include + +IMPLEMENT_STANDARD_HANDLE (Graphic3d_ShaderVariable, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderVariable, Standard_Transient) + +// +// Specific instantiations of struct templates to avoid compilation warnings +// +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; +template struct Graphic3d_UniformValue; + +// ======================================================================= +// function : ~Graphic3d_ValueInterface +// purpose : Releases memory resources of variable value +// ======================================================================= +Graphic3d_ValueInterface::~Graphic3d_ValueInterface() +{ + // +} + +// ======================================================================= +// function : Graphic3d_ShaderVariable +// purpose : Creates new abstract shader variable +// ======================================================================= +Graphic3d_ShaderVariable::Graphic3d_ShaderVariable (const TCollection_AsciiString& theName) +: myName (theName), + myValue (NULL) +{ + // +} + +// ======================================================================= +// function : ~Graphic3d_ShaderVariableBase +// purpose : Releases resources of shader variable +// ======================================================================= +Graphic3d_ShaderVariable::~Graphic3d_ShaderVariable() +{ + delete myValue; +} + +// ======================================================================= +// function : IsDone +// purpose : Checks if the shader variable is valid or not +// ======================================================================= +Standard_Boolean Graphic3d_ShaderVariable::IsDone() const +{ + return !myName.IsEmpty() && (myValue != NULL); +} + +// ======================================================================= +// function : Name +// purpose : Returns name of shader variable +// ======================================================================= +const TCollection_AsciiString& Graphic3d_ShaderVariable::Name() const +{ + return myName; +} + +// ======================================================================= +// function : Value +// purpose : Returns interface of shader variable value +// ======================================================================= +Graphic3d_ValueInterface* Graphic3d_ShaderVariable::Value() +{ + return myValue; +} diff --git a/src/Graphic3d/Graphic3d_ShaderVariable.hxx b/src/Graphic3d/Graphic3d_ShaderVariable.hxx new file mode 100644 index 0000000000..5770c592ba --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderVariable.hxx @@ -0,0 +1,171 @@ +// Created on: 2013-09-25 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Graphic3d_ShaderVariable_HeaderFile +#define _Graphic3d_ShaderVariable_HeaderFile + +#include +#include +#include + +#include + +//! Interface for generic variable value. +struct Graphic3d_ValueInterface +{ + //! Releases memory resources of variable value. + Standard_EXPORT virtual ~Graphic3d_ValueInterface(); + + //! Returns unique identifier of value type. + virtual Standard_Size TypeID() const = 0; + + //! Returns variable value casted to specified type. + template T& As(); + + //! Returns variable value casted to specified type. + template const T& As() const; +}; + +//! Generates unique type identifier for variable value. +template +struct Graphic3d_UniformValueTypeID { + /* Not implemented */ +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +template<> +struct Graphic3d_UniformValueTypeID { + static const Standard_Size ID = __LINE__; +}; + +//! Describes specific value of custom uniform variable. +template +struct Graphic3d_UniformValue : public Graphic3d_ValueInterface +{ + //! Creates new variable value. + Graphic3d_UniformValue (const T& theValue) : Value (theValue) { } + + //! Returns unique identifier of value type. + virtual Standard_Size TypeID() const; + + //! Value of custom uniform variable. + T Value; +}; + +//! Integer uniform value. +typedef Graphic3d_UniformValue Graphic3d_UniformInt; + +//! Integer uniform 2D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec2i; + +//! Integer uniform 3D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec3i; + +//! Integer uniform 4D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec4i; + +//! Floating-point uniform value. +typedef Graphic3d_UniformValue Graphic3d_UniformFloat; + +//! Floating-point uniform 2D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec2; + +//! Floating-point uniform 3D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec3; + +//! Floating-point uniform 4D vector. +typedef Graphic3d_UniformValue Graphic3d_UniformVec4; + +//! Describes custom uniform shader variable. +class Graphic3d_ShaderVariable : public Standard_Transient +{ +public: + + //! Releases resources of shader variable. + Standard_EXPORT virtual ~Graphic3d_ShaderVariable(); + + //! Returns name of shader variable. + Standard_EXPORT const TCollection_AsciiString& Name() const; + + //! Checks if the shader variable is valid or not. + Standard_EXPORT Standard_Boolean IsDone() const; + + //! Returns interface of shader variable value. + Standard_EXPORT Graphic3d_ValueInterface* Value(); + + //! Creates new initialized shader variable. + template + static Graphic3d_ShaderVariable* Create (const TCollection_AsciiString& theName, + const T& theValue); + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_ShaderVariable) + +protected: + + //! Creates new uninitialized shader variable. + Standard_EXPORT Graphic3d_ShaderVariable (const TCollection_AsciiString& theName); + +protected: + + //! The name of uniform shader variable. + TCollection_AsciiString myName; + + //! The generic value of shader variable. + Graphic3d_ValueInterface* myValue; +}; + +#include + +#endif // _Graphic3d_ShaderVariable_HeaderFile diff --git a/src/Graphic3d/Graphic3d_ShaderVariable.lxx b/src/Graphic3d/Graphic3d_ShaderVariable.lxx new file mode 100644 index 0000000000..1ebb05917b --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderVariable.lxx @@ -0,0 +1,63 @@ +// Created on: 2013-09-25 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +// ======================================================================= +// function : As +// purpose : Returns variable value casted to specified type +// ======================================================================= +template inline +T& Graphic3d_ValueInterface::As() +{ + Graphic3d_UniformValue* aPtr = dynamic_cast*> (this); + return aPtr->Value; +} + +// ======================================================================= +// function : As +// purpose : Returns variable value casted to specified type +// ======================================================================= +template inline +const T& Graphic3d_ValueInterface::As() const +{ + const Graphic3d_UniformValue* aPtr = dynamic_cast*> (this); + return aPtr->Value; +} + +// ======================================================================= +// function : TypeID +// purpose : Returns unique identifier of value type +// ======================================================================= +template inline +Standard_Size Graphic3d_UniformValue::TypeID() const +{ + return Graphic3d_UniformValueTypeID::ID; +} + +// ======================================================================= +// function : Create +// purpose : Creates initialized shader variable +// ======================================================================= +template inline +Graphic3d_ShaderVariable* Graphic3d_ShaderVariable::Create (const TCollection_AsciiString& theName, + const T& theValue) +{ + Graphic3d_ShaderVariable* theVariable = new Graphic3d_ShaderVariable (theName); + theVariable->myValue = new Graphic3d_UniformValue (theValue); + return theVariable; +} diff --git a/src/Graphic3d/Graphic3d_ShaderVariable_Handle.hxx b/src/Graphic3d/Graphic3d_ShaderVariable_Handle.hxx new file mode 100644 index 0000000000..2961cb9191 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderVariable_Handle.hxx @@ -0,0 +1,28 @@ +// Created on: 2013-09-25 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_Graphic3d_ShaderVariable_HeaderFile +#define _Handle_Graphic3d_ShaderVariable_HeaderFile + +#include + +class Graphic3d_ShaderVariable; +DEFINE_STANDARD_HANDLE (Graphic3d_ShaderVariable, Standard_Transient) + +#endif \ No newline at end of file diff --git a/src/Graphic3d/Graphic3d_TypeOfShaderObject.hxx b/src/Graphic3d/Graphic3d_TypeOfShaderObject.hxx new file mode 100644 index 0000000000..e0ceb5e6d6 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TypeOfShaderObject.hxx @@ -0,0 +1,30 @@ +// Created on: 2013-09-20 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Graphic3d_TypeOfShaderObject_HeaderFile +#define _Graphic3d_TypeOfShaderObject_HeaderFile + +//! Type of the shader object (may be extended). +enum Graphic3d_TypeOfShaderObject +{ + Graphic3d_TOS_VERTEX, + Graphic3d_TOS_FRAGMENT +}; + +#endif diff --git a/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx b/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx index 032468f85b..49b3bcd0bd 100755 --- a/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx +++ b/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx @@ -19,6 +19,7 @@ #ifndef InterfaceGraphic_Graphic3dHeader #define InterfaceGraphic_Graphic3dHeader +#include #include #include @@ -326,17 +327,19 @@ typedef struct { /* CONTEXTE LIGNE */ -typedef struct { - - int IsDef; - - int IsSet; - - CALL_DEF_COLOR Color; - - int LineType; - - float Width; +typedef struct +{ + int IsDef; + + int IsSet; + + CALL_DEF_COLOR Color; + + int LineType; + + float Width; + + Handle(Graphic3d_ShaderProgram) ShaderProgram; } CALL_DEF_CONTEXTLINE; @@ -373,25 +376,25 @@ typedef struct { /* CONTEXTE TEXT */ -typedef struct { - - int IsDef; - - int IsSet; - - const char* Font; - - float Space; - - float Expan; - - CALL_DEF_COLOR Color; - - int Style; - - int DisplayType; - - CALL_DEF_COLOR ColorSubTitle; +typedef struct +{ + int IsDef; + + int IsSet; + + const char* Font; + + float Space; + + float Expan; + + CALL_DEF_COLOR Color; + + int Style; + + int DisplayType; + + CALL_DEF_COLOR ColorSubTitle; int TextZoomable; @@ -399,6 +402,7 @@ typedef struct { int TextFontAspect; + Handle(Graphic3d_ShaderProgram) ShaderProgram; } CALL_DEF_CONTEXTTEXT; diff --git a/src/NCollection/FILES b/src/NCollection/FILES index 8011e6edea..60e5de999e 100755 --- a/src/NCollection/FILES +++ b/src/NCollection/FILES @@ -92,3 +92,5 @@ NCollection_DefineAlloc.hxx NCollection_Vec2.hxx NCollection_Vec3.hxx NCollection_Vec4.hxx + +NCollection_Mat4.hxx diff --git a/src/NCollection/NCollection_Mat4.hxx b/src/NCollection/NCollection_Mat4.hxx new file mode 100644 index 0000000000..babf3e85c4 --- /dev/null +++ b/src/NCollection/NCollection_Mat4.hxx @@ -0,0 +1,424 @@ +// Created on: 2013-05-30 +// Created by: Anton POLETAEV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 65 (the "License") You may not use the content of this file +// except in compliance with the License Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file +// +// The Initial Developer of the Original Code is Open CASCADE SAS, having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement Please see the License for the specific terms +// and conditions governing the rights and limitations under the License +// +// The code was inspired by "sView" project by +// Kirill GAVRILOV: https://github.com/gkv311/sview. +// Files: StGLMatrix.hxx, StGLMatrix.cxx. +// Copyright (c) 2010-2013 Kirill Gavrilov + +#ifndef _NCollection_Mat4_HeaderFile +#define _NCollection_Mat4_HeaderFile + +#include + +//! Generic matrix of 4 x 4 elements. +//! To be used in conjunction with NCollection_Vec4 entities. +//! Originally introduced for 3D space projection and orientation +//! operations. +template +class NCollection_Mat4 +{ + +public: + + //! Get number of rows. + //! @return number of rows. + static size_t Rows() + { + return 4; + } + + //! Get number of columns. + //! @retur number of columns. + static size_t Cols() + { + return 4; + } + + //! Empty constructor. + //! Construct the zero matrix. + NCollection_Mat4() + { + InitIdentity(); + } + + //! Copy constructor. + //! @param theOther [in] the matrix to copy values from. + NCollection_Mat4 (const NCollection_Mat4& theOther) + { + std::memcpy (this, &theOther, sizeof (NCollection_Mat4)); + } + + //! Assignment operator. + //! @param theOther [in] the matrix to copy values from. + const NCollection_Mat4& operator= (const NCollection_Mat4& theOther) + { + std::memcpy (this, &theOther, sizeof (NCollection_Mat4)); + return *this; + } + + //! Get element at the specified row and column. + //! @param theRow [in] the row.to address. + //! @param theCol [in] the column to address. + //! @return the value of the addressed element. + Element_t GetValue (const size_t theRow, const size_t theCol) const + { + return myMat[theCol * 4 + theRow]; + } + + //! Access element at the specified row and column. + //! @param theRow [in] the row.to access. + //! @param theCol [in] the column to access. + //! @return reference on the matrix element. + Element_t& ChangeValue (const size_t theRow, const size_t theCol) + { + return myMat[theCol * 4 + theRow]; + } + + //! Set value for the element specified by row and columns. + //! @param theRow [in] the row to change. + //! @param theCol [in] the column to change. + //! @param theValue [in] the value to set.s + void SetValue (const size_t theRow, + const size_t theCol, + const Element_t theValue) + { + myMat[theCol * 4 + theRow] = theValue; + } + + //! Get vector of elements for the specified row. + //! @param theRow [in] the row to access. + //! @return vector of elements. + NCollection_Vec4 GetRow (const size_t theRow) const + { + return NCollection_Vec4 (GetValue (theRow, 0), + GetValue (theRow, 1), + GetValue (theRow, 2), + GetValue (theRow, 3)); + } + + //! Change first 3 row values by the passed vector. + //! @param theRow [in] the row to change. + //! @param theVec [in] the vector of values. + void SetRow (const size_t theRow, const NCollection_Vec3& theVec) + { + SetValue (theRow, 0, theVec.x()); + SetValue (theRow, 1, theVec.y()); + SetValue (theRow, 2, theVec.z()); + } + + //! Set row values by the passed 4 element vector. + //! @param theRow [in] the row to change. + //! @param theVec [in] the vector of values. + void SetRow (const size_t theRow, const NCollection_Vec4& theVec) + { + SetValue (theRow, 0, theVec.x()); + SetValue (theRow, 1, theVec.y()); + SetValue (theRow, 2, theVec.z()); + SetValue (theRow, 3, theVec.w()); + } + + //! Get vector of elements for the specified column. + //! @param theCol [in] the column to access. + //! @return vector of elements. + NCollection_Vec4 GetColumn (const size_t theCol) const + { + return NCollection_Vec4 (GetValue (0, theCol), + GetValue (1, theCol), + GetValue (2, theCol), + GetValue (3, theCol)); + } + + //! Change first 3 column values by the passed vector. + //! @param theCol [in] the column to change. + //! @param theVec [in] the vector of values. + void SetColumn (const size_t theCol, + const NCollection_Vec3& theVec) + { + SetValue (0, theCol, theVec.x()); + SetValue (1, theCol, theVec.y()); + SetValue (2, theCol, theVec.z()); + } + + //! Set column values by the passed 4 element vector. + //! @param theCol [in] the column to change. + //! @param theVec [in] the vector of values. + void SetColumn (const size_t theCol, + const NCollection_Vec4& theVec) + { + SetValue (0, theCol, theVec.x()); + SetValue (1, theCol, theVec.y()); + SetValue (2, theCol, theVec.z()); + SetValue (3, theCol, theVec.w()); + } + + //! Get vector of diagonal elements. + //! \return vector of diagonal elements. + NCollection_Vec4 GetDiagonal() const + { + return NCollection_Vec4 (GetValue (0, 0), + GetValue (1, 1), + GetValue (2, 2), + GetValue (3, 3)); + } + + //! Change first 3 elements of the diagonal matrix. + //! @param theVec the vector of values. + void SetDiagonal (const NCollection_Vec3& theVec) + { + SetValue (0, 0, theVec.x()); + SetValue (1, 1, theVec.y()); + SetValue (2, 2, theVec.z()); + } + + //! Set diagonal elements of the matrix by the passed vector. + //! @param theVec [in] the vector of values. + void SetDiagonal (const NCollection_Vec4& theVec) + { + SetValue (0, 0, theVec.x()); + SetValue (1, 1, theVec.y()); + SetValue (2, 2, theVec.z()); + SetValue (3, 3, theVec.w()); + } + + //! Initialize the identity matrix. + void InitIdentity() + { + static const Element_t anIdentity[] = + {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + std::memcpy (this, anIdentity, sizeof (NCollection_Mat4)); + } + + //! Raw access to the data (for OpenGL exchange). + const Element_t* GetData() const { return myMat; } + operator const Element_t*() const { return myMat; } + operator Element_t*() { return myMat; } + + //! Multiply by the vector (M * V). + //! @param theVec [in] the vector to multiply. + NCollection_Vec4 operator* (const NCollection_Vec4& theVec) const + { + return NCollection_Vec4 ( + GetValue (0, 0) * theVec.x() + GetValue (0, 1) * theVec.y() + GetValue (0, 2) * theVec.z() + GetValue (0, 3) * theVec.w(), + GetValue (1, 0) * theVec.x() + GetValue (1, 1) * theVec.y() + GetValue (1, 2) * theVec.z() + GetValue (1, 3) * theVec.w(), + GetValue (2, 0) * theVec.x() + GetValue (2, 1) * theVec.y() + GetValue (2, 2) * theVec.z() + GetValue (2, 3) * theVec.w(), + GetValue (3, 0) * theVec.x() + GetValue (3, 1) * theVec.y() + GetValue (3, 2) * theVec.z() + GetValue (3, 3) * theVec.w()); + } + + //! Compute matrix multiplication product: A * B. + //! @param theMatA [in] the matrix "A". + //! @param theMatB [in] the matrix "B". + NCollection_Mat4 Multiply (const NCollection_Mat4& theMatA, + const NCollection_Mat4& theMatB) + { + NCollection_Mat4 aMatRes; + + size_t aInputElem; + for (size_t aResElem = 0; aResElem < 16; ++aResElem) + { + aMatRes[aResElem] = (Element_t )0; + for (aInputElem = 0; aInputElem < 4; ++aInputElem) + { + aMatRes[aResElem] += theMatA.GetValue(aResElem % 4, aInputElem) + * theMatB.GetValue(aInputElem, aResElem / 4); + } + } + + return aMatRes; + } + + //! Compute matrix multiplication. + //! @param theMat [in] the matrix to multiply. + void Multiply (const NCollection_Mat4& theMat) + { + *this = Multiply(*this, theMat); + } + + //! Multiply by the another matrix. + //! @param theMat [in] the other matrix. + NCollection_Mat4& operator*= (const NCollection_Mat4& theMat) + { + Multiply (theMat); + return *this; + } + + //! Compute matrix multiplication product. + //! @param theMat [in] the other matrix. + //! @return result of multiplication. + NCollection_Mat4 operator* (const NCollection_Mat4& theMat) const + { + return Mutiplied (theMat); + } + + //! Compute matrix multiplication product. + //! @param theMat [in] the other matrix. + //! @return result of multiplication. + NCollection_Mat4 Multiplied (const NCollection_Mat4& theMat) const + { + NCollection_Mat4 aTempMat (*this); + aTempMat *= theMat; + return aTempMat; + } + + //! Compute per-component multiplication. + //! @param theFactor [in] the scale factor. + void Multiply (const Element_t theFactor) + { + for (size_t i = 0; i < 16; ++i) + { + myMat[i] *= theFactor; + } + } + + //! Compute per-element multiplication. + //! @param theFactor [in] the scale factor. + NCollection_Mat4& operator*=(const Element_t theFactor) + { + Multiply (theFactor); + return *this; + } + + //! Compute per-element multiplication. + //! @param theFactor [in] the scale factor. + //! @return the result of multiplicaton. + NCollection_Mat4 operator* (const Element_t theFactor) const + { + return Multiplied (theFactor); + } + + //! Compute per-element multiplication. + //! @param theFactor [in] the scale factor. + //! @return the result of multiplicaton. + NCollection_Mat4 Multiplied (const Element_t theFactor) const + { + NCollection_Mat4 aTempMat (*this); + aTempMat *= theFactor; + return aTempMat; + } + + //! Translate the matrix on the passed vector. + //! @param theVec [in] the translation vector. + void Translate (const NCollection_Vec3& theVec) + { + NCollection_Mat4 aTempMat; + aTempMat.SetColumn (3, theVec); + this->Multiply (aTempMat); + } + + //! Compute inverted matrix. + //! @param theOutMx [out] the inverted matrix. + //! @return true if reversion success. + bool Inverted (NCollection_Mat4& theOutMx) const + { + Element_t* inv = theOutMx.myMat; + + // use short-cut for better readability + const Element_t* m = myMat; + + inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) - + m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) - + m[13] * (m[ 7] * m[10] - m[ 6] * m[11]); + + inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) - + m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) - + m[13] * (m[ 2] * m[11] - m[ 3] * m[10]); + + inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) - + m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) - + m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]); + + inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) - + m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) - + m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]); + + inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) - + m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) - + m[12] * (m[ 6] * m[11] - m[ 7] * m[10]); + + inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) - + m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) - + m[12] * (m[ 3] * m[10] - m[ 2] * m[11]); + + inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) - + m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) - + m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]); + + inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) - + m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) - + m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]); + + inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) - + m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) - + m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]); + + inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) - + m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) - + m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]); + + inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) - + m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) - + m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]); + + inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) - + m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) - + m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]); + + inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) - + m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) - + m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]); + + inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) - + m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) - + m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]); + + inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) - + m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) - + m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]); + + inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) - + m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) - + m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]); + + Element_t aDet = m[0] * inv[ 0] + + m[1] * inv[ 4] + + m[2] * inv[ 8] + + m[3] * inv[12]; + + if (aDet == 0) + return false; + + aDet = (Element_t) 1. / aDet; + + for (int i = 0; i < 16; ++i) + inv[i] *= aDet; + + return true; + } + +private: + + Element_t myMat[16]; + +}; + +#endif // _NCollection_Matrix_H__ diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 65ba3e5a06..57ae623767 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -120,5 +120,16 @@ OpenGl_CappingAlgo.hxx OpenGl_CappingAlgo.cxx OpenGl_CappingPlaneResource.hxx OpenGl_CappingPlaneResource.cxx -OpenGl_ClippingState.hxx -OpenGl_ClippingState.cxx +OpenGl_Clipping.hxx +OpenGl_Clipping.cxx +OpenGl_ShaderObject.hxx +OpenGl_ShaderObject.cxx +OpenGl_ShaderProgram.hxx +OpenGl_ShaderProgram.cxx +OpenGl_ShaderManager.hxx +OpenGl_ShaderManager.cxx +OpenGl_ShaderStates.hxx +OpenGl_ShaderStates.cxx +Handle_OpenGl_ShaderObject.hxx +Handle_OpenGl_ShaderProgram.hxx +Handle_OpenGl_ShaderManager.hxx diff --git a/src/OpenGl/Handle_OpenGl_ShaderManager.hxx b/src/OpenGl/Handle_OpenGl_ShaderManager.hxx new file mode 100644 index 0000000000..5f5f4bd883 --- /dev/null +++ b/src/OpenGl/Handle_OpenGl_ShaderManager.hxx @@ -0,0 +1,26 @@ +// Created on: 2013-09-26 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_OpenGl_ShaderManager_HeaderFile +#define _Handle_OpenGl_ShaderManager_HeaderFile + +class OpenGl_ShaderManager; +DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient) + +#endif diff --git a/src/OpenGl/Handle_OpenGl_ShaderObject.hxx b/src/OpenGl/Handle_OpenGl_ShaderObject.hxx new file mode 100644 index 0000000000..109b02ab21 --- /dev/null +++ b/src/OpenGl/Handle_OpenGl_ShaderObject.hxx @@ -0,0 +1,28 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_OpenGl_ShaderObject_Header +#define _Handle_OpenGl_ShaderObject_Header + +#include + +class OpenGl_ShaderObject; +DEFINE_STANDARD_HANDLE(OpenGl_ShaderObject, OpenGl_Resource) + +#endif diff --git a/src/OpenGl/Handle_OpenGl_ShaderProgram.hxx b/src/OpenGl/Handle_OpenGl_ShaderProgram.hxx new file mode 100644 index 0000000000..a8c1d29027 --- /dev/null +++ b/src/OpenGl/Handle_OpenGl_ShaderProgram.hxx @@ -0,0 +1,28 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Handle_OpenGl_ShaderProgram_Header +#define _Handle_OpenGl_ShaderProgram_Header + +#include + +class OpenGl_ShaderProgram; +DEFINE_STANDARD_HANDLE(OpenGl_ShaderProgram, OpenGl_Resource) + +#endif diff --git a/src/OpenGl/OpenGl_AspectFace.cxx b/src/OpenGl/OpenGl_AspectFace.cxx index 41f72e217e..a9a7483e03 100644 --- a/src/OpenGl/OpenGl_AspectFace.cxx +++ b/src/OpenGl/OpenGl_AspectFace.cxx @@ -17,22 +17,24 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. +#include +#include + #include +#include +#include +#include #include #include -#include -#include #include +#include #include #include #include -#include - namespace { - static OPENGL_SURF_PROP THE_DEFAULT_MATERIAL = { 0.2F, 0.8F, 0.1F, 0.0F, // amb, diff, spec, emsv @@ -48,7 +50,6 @@ namespace static TEL_POFFSET_PARAM THE_DEFAULT_POFFSET = { Aspect_POM_Fill, 1.0F, 0.0F }; static const TCollection_AsciiString THE_EMPTY_KEY; - }; // ======================================================================= @@ -130,11 +131,7 @@ OpenGl_AspectFace::OpenGl_AspectFace() myIntFront (THE_DEFAULT_MATERIAL), myIntBack (THE_DEFAULT_MATERIAL), myPolygonOffset (THE_DEFAULT_POFFSET), - myDoTextureMap (false), - myTextureMap(), - myIsTextureInit (Standard_False), - myTextureRes(), - myTextureId() + myDoTextureMap (false) {} // ======================================================================= @@ -208,12 +205,6 @@ void OpenGl_AspectFace::SetAspect (const CALL_DEF_CONTEXTFILLAREA& theAspect) myIntBack.matcol.rgb[2] = (float )theAspect.BackIntColor.b; myIntBack.matcol.rgb[3] = 1.0f; - myDoTextureMap = (theAspect.Texture.doTextureMap != 0); - myTextureMap = theAspect.Texture.TextureMap; - - const TCollection_AsciiString& aNewKey = myTextureMap.IsNull() ? THE_EMPTY_KEY : myTextureMap->GetId(); - myIsTextureInit = (!aNewKey.IsEmpty() && myTextureId == aNewKey); - //TelPolygonOffset myPolygonOffset.mode = (Aspect_PolygonOffsetMode )theAspect.PolygonOffsetMode; myPolygonOffset.factor = theAspect.PolygonOffsetFactor; @@ -226,6 +217,28 @@ void OpenGl_AspectFace::SetAspect (const CALL_DEF_CONTEXTFILLAREA& theAspect) anEdgeAspect.LineType = (Aspect_TypeOfLine )theAspect.LineType; anEdgeAspect.Width = (float )theAspect.Width; myAspectEdge.SetAspect (anEdgeAspect); + + myDoTextureMap = (theAspect.Texture.doTextureMap != 0); + + // update texture binding + myTexture = theAspect.Texture.TextureMap; + + const TCollection_AsciiString& aTextureKey = myTexture.IsNull() ? THE_EMPTY_KEY : myTexture->GetId(); + + if (aTextureKey.IsEmpty() || myResources.TextureId != aTextureKey) + { + myResources.ResetTexture(); + } + + // update shader program binding + myShaderProgram = theAspect.ShaderProgram; + + const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId(); + + if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey) + { + myResources.ResetShader(); + } } // ======================================================================= @@ -363,6 +376,8 @@ void OpenGl_AspectFace::SetAspect (const Handle(Graphic3d_AspectFillArea3d)& the aFaceContext.PolygonOffsetFactor = (Standard_ShortReal)aPolyFactor; aFaceContext.PolygonOffsetUnits = (Standard_ShortReal)aPolyUnits; + aFaceContext.ShaderProgram = theAspect->ShaderProgram(); + SetAspect (aFaceContext); } @@ -381,66 +396,110 @@ void OpenGl_AspectFace::Render (const Handle(OpenGl_Workspace)& theWorkspace) co // ======================================================================= void OpenGl_AspectFace::Release (const Handle(OpenGl_Context)& theContext) { - if (!myTextureRes.IsNull()) + if (!myResources.Texture.IsNull()) { if (!theContext.IsNull()) { - if (myTextureId.IsEmpty()) + if (myResources.TextureId.IsEmpty()) { - theContext->DelayedRelease (myTextureRes); + theContext->DelayedRelease (myResources.Texture); } else { - myTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call - theContext->ReleaseResource (myTextureId); + myResources.Texture.Nullify(); // we need nullify all handles before ReleaseResource() call + theContext->ReleaseResource (myResources.TextureId); } } - myTextureRes.Nullify(); + myResources.Texture.Nullify(); } - myTextureId.Clear(); + myResources.TextureId.Clear(); + myResources.ResetTexture(); + + if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull()) + { + theContext->ShaderManager()->Unregister (myResources.ShaderProgram); + } + myResources.ShaderProgramId.Clear(); + myResources.ResetShader(); } // ======================================================================= -// function : buildTexure +// function : BuildTexture // purpose : // ======================================================================= -void OpenGl_AspectFace::buildTexture (const Handle(OpenGl_Workspace)& theWorkspace) const +void OpenGl_AspectFace::Resources::BuildTexture (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_TextureMap)& theTexture) { - const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); + const Handle(OpenGl_Context)& aContext = theWS->GetGlContext(); - const TCollection_AsciiString& aNewKey = myTextureMap.IsNull() ? THE_EMPTY_KEY : myTextureMap->GetId(); - if (aNewKey.IsEmpty() || myTextureId != aNewKey) + // release old texture resource + if (!Texture.IsNull()) { - if (!myTextureRes.IsNull()) + if (TextureId.IsEmpty()) { - if (myTextureId.IsEmpty()) - { - aContext->DelayedRelease (myTextureRes); - myTextureRes.Nullify(); - } - else - { - myTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call - aContext->ReleaseResource (myTextureId); - } + aContext->DelayedRelease (Texture); + Texture.Nullify(); } - myTextureId = aNewKey; - - if (!myTextureMap.IsNull()) + else { - if (aNewKey.IsEmpty() || !aContext->GetResource (aNewKey, myTextureRes)) + Texture.Nullify(); // we need nullify all handles before ReleaseResource() call + aContext->ReleaseResource (TextureId); + } + } + + TextureId = theTexture.IsNull() ? THE_EMPTY_KEY : theTexture->GetId(); + + if (!theTexture.IsNull()) + { + if (TextureId.IsEmpty() || !aContext->GetResource (TextureId, Texture)) + { + Texture = new OpenGl_Texture (theTexture->GetParams()); + Handle(Image_PixMap) anImage = theTexture->GetImage(); + if (!anImage.IsNull()) { - myTextureRes = new OpenGl_Texture (myTextureMap->GetParams()); - Handle(Image_PixMap) anImage = myTextureMap->GetImage(); - if (!anImage.IsNull()) - { - myTextureRes->Init (aContext, *anImage.operator->(), myTextureMap->Type()); - } - if (!aNewKey.IsEmpty()) - { - aContext->ShareResource (aNewKey, myTextureRes); - } + Texture->Init (aContext, *anImage.operator->(), theTexture->Type()); + } + if (!TextureId.IsEmpty()) + { + aContext->ShareResource (TextureId, Texture); } } } } + +// ======================================================================= +// function : BuildShader +// purpose : +// ======================================================================= +void OpenGl_AspectFace::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_ShaderProgram)& theShader) +{ + const Handle(OpenGl_Context)& aContext = theWS->GetGlContext(); + + if (!aContext->IsGlGreaterEqual (2, 0)) + return; + + // release old shader program resources + if (!ShaderProgram.IsNull()) + { + aContext->ShaderManager()->Unregister (ShaderProgram); + } + + ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId(); + + if (!theShader.IsNull()) + { + if (!aContext->GetResource (ShaderProgramId, ShaderProgram)) + { + ShaderProgram = aContext->ShaderManager()->Create (theShader); + if (!ShaderProgramId.IsEmpty()) + { + aContext->ShareResource (ShaderProgramId, ShaderProgram); + } + } + } + else + { + ShaderProgram.Nullify(); + } +} diff --git a/src/OpenGl/OpenGl_AspectFace.hxx b/src/OpenGl/OpenGl_AspectFace.hxx index 9174122f46..18b640f4cd 100644 --- a/src/OpenGl/OpenGl_AspectFace.hxx +++ b/src/OpenGl/OpenGl_AspectFace.hxx @@ -24,13 +24,15 @@ #include #include +#include +#include +#include #include #include -#include -#include #include -#include +#include +#include #define OPENGL_AMBIENT_MASK (1<<0) #define OPENGL_DIFFUSE_MASK (1<<1) @@ -180,22 +182,35 @@ public: return myDoTextureMap; } - //! @return texture map. - const Handle(OpenGl_Texture)& TextureRes (const Handle(OpenGl_Workspace)& theWorkspace) const - { - if (!myIsTextureInit) - { - buildTexture (theWorkspace); - myIsTextureInit = Standard_True; - } - - return myTextureRes; - } - //! @return texture mapping parameters. const Handle(Graphic3d_TextureParams)& TextureParams() const { - return myTextureMap->GetParams(); + return myTexture->GetParams(); + } + + //! @return texture map. + const Handle(OpenGl_Texture)& TextureRes (const Handle(OpenGl_Workspace)& theWorkspace) const + { + if (!myResources.IsTextureReady()) + { + myResources.BuildTexture (theWorkspace, myTexture); + myResources.SetTextureReady(); + } + + return myResources.Texture; + } + + //! Init and return OpenGl shader program resource. + //! @return shader program resource. + const Handle(OpenGl_ShaderProgram)& ShaderProgramRes (const Handle(OpenGl_Workspace)& theWorkspace) const + { + if (!myResources.IsShaderReady()) + { + myResources.BuildShader (theWorkspace, myShaderProgram); + myResources.SetShaderReady(); + } + + return myResources.ShaderProgram; } virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; @@ -203,7 +218,6 @@ public: protected: - void buildTexture (const Handle(OpenGl_Workspace)& theWorkspace) const; void convertMaterial (const CALL_DEF_MATERIAL& theMat, OPENGL_SURF_PROP& theSurf); @@ -218,13 +232,40 @@ protected: //! @name ordinary aspect properties OPENGL_SURF_PROP myIntBack; TEL_POFFSET_PARAM myPolygonOffset; bool myDoTextureMap; - Handle(Graphic3d_TextureMap) myTextureMap; + Handle(Graphic3d_TextureMap) myTexture; + Handle(Graphic3d_ShaderProgram) myShaderProgram; -protected: //! @name OpenGl resources +protected: - mutable Standard_Boolean myIsTextureInit; - mutable Handle(OpenGl_Texture) myTextureRes; - mutable TCollection_AsciiString myTextureId; + //! OpenGl resources + mutable struct Resources + { + public: + Resources() + : myIsTextureReady (Standard_False), + myIsShaderReady (Standard_False) {} + + Standard_Boolean IsTextureReady() const { return myIsTextureReady; } + Standard_Boolean IsShaderReady () const { return myIsShaderReady; } + void SetTextureReady() { myIsTextureReady = Standard_True; } + void SetShaderReady () { myIsShaderReady = Standard_True; } + void ResetTexture() { myIsTextureReady = Standard_False; } + void ResetShader () { myIsShaderReady = Standard_False; } + + void BuildTexture (const Handle(OpenGl_Workspace)& theWS, const Handle(Graphic3d_TextureMap)& theTexture); + void BuildShader (const Handle(OpenGl_Workspace)& theWS, const Handle(Graphic3d_ShaderProgram)& theShader); + + Handle(OpenGl_Texture) Texture; + TCollection_AsciiString TextureId; + Handle(OpenGl_ShaderProgram) ShaderProgram; + TCollection_AsciiString ShaderProgramId; + + private: + + Standard_Boolean myIsTextureReady; + Standard_Boolean myIsShaderReady; + + } myResources; protected: diff --git a/src/OpenGl/OpenGl_AspectLine.cxx b/src/OpenGl/OpenGl_AspectLine.cxx index 189c48539b..a347949188 100644 --- a/src/OpenGl/OpenGl_AspectLine.cxx +++ b/src/OpenGl/OpenGl_AspectLine.cxx @@ -17,29 +17,44 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. +#include + #include +#include +#include +#include #include -static const TEL_COLOUR myDefaultColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }}; - -/*----------------------------------------------------------------------*/ +namespace +{ + static const TEL_COLOUR myDefaultColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }}; + static const TCollection_AsciiString THE_EMPTY_KEY; +}; +// ======================================================================= +// function : OpenGl_AspectLine +// purpose : +// ======================================================================= OpenGl_AspectLine::OpenGl_AspectLine () : myColor(myDefaultColor), myType(Aspect_TOL_SOLID), myWidth(1.0F) {} -/*----------------------------------------------------------------------*/ - +// ======================================================================= +// function : OpenGl_AspectLine +// purpose : +// ======================================================================= OpenGl_AspectLine::OpenGl_AspectLine (const OpenGl_AspectLine &AnOther) : myColor(AnOther.myColor), myType(AnOther.myType), myWidth(AnOther.myWidth) {} -/*----------------------------------------------------------------------*/ - +// ======================================================================= +// function : SetAspect +// purpose : +// ======================================================================= void OpenGl_AspectLine::SetAspect (const CALL_DEF_CONTEXTLINE &theAspect) { myColor.rgb[0] = (float) theAspect.Color.r; @@ -48,16 +63,74 @@ void OpenGl_AspectLine::SetAspect (const CALL_DEF_CONTEXTLINE &theAspect) myColor.rgb[3] = 1.0f; myType = (Aspect_TypeOfLine) theAspect.LineType; myWidth = (float) theAspect.Width; + + // update resource bindings + myShaderProgram = theAspect.ShaderProgram; + + const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId(); + + if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey) + { + myResources.ResetShader(); + } } -/*----------------------------------------------------------------------*/ - +// ======================================================================= +// function : Render +// purpose : +// ======================================================================= void OpenGl_AspectLine::Render (const Handle(OpenGl_Workspace) &theWorkspace) const { theWorkspace->SetAspectLine (this); } -void OpenGl_AspectLine::Release (const Handle(OpenGl_Context)&) +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void OpenGl_AspectLine::Release (const Handle(OpenGl_Context)& theContext) { - // + if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull()) + { + theContext->ShaderManager()->Unregister (myResources.ShaderProgram); + } + myResources.ShaderProgramId.Clear(); + myResources.ResetShader(); +} + +// ======================================================================= +// function : BuildShader +// purpose : +// ======================================================================= +void OpenGl_AspectLine::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_ShaderProgram)& theShader) +{ + const Handle(OpenGl_Context)& aContext = theWS->GetGlContext(); + + if (!aContext->IsGlGreaterEqual (2, 0)) + return; + + // release old shader program resources + if (!ShaderProgram.IsNull()) + { + aContext->ShaderManager()->Unregister (ShaderProgram); + } + + ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId(); + + if (!theShader.IsNull()) + { + if (!aContext->GetResource (ShaderProgramId, ShaderProgram)) + { + ShaderProgram = aContext->ShaderManager()->Create (theShader); + if (!ShaderProgramId.IsEmpty()) + { + aContext->ShareResource (ShaderProgramId, ShaderProgram); + } + } + } + else + { + ShaderProgram.Nullify(); + } } diff --git a/src/OpenGl/OpenGl_AspectLine.hxx b/src/OpenGl/OpenGl_AspectLine.hxx index 3f2d4479a8..c192ba7ded 100644 --- a/src/OpenGl/OpenGl_AspectLine.hxx +++ b/src/OpenGl/OpenGl_AspectLine.hxx @@ -20,9 +20,13 @@ #ifndef _OpenGl_AspectLine_Header #define _OpenGl_AspectLine_Header +#include + #include #include +#include + #include class OpenGl_AspectLine : public OpenGl_Element @@ -38,14 +42,51 @@ class OpenGl_AspectLine : public OpenGl_Element Aspect_TypeOfLine Type() const { return myType; } float Width() const { return myWidth; } + //! Init and return OpenGl shader program resource. + //! @return shader program resource. + const Handle(OpenGl_ShaderProgram)& ShaderProgramRes (const Handle(OpenGl_Workspace)& theWorkspace) const + { + if (!myResources.IsShaderReady()) + { + myResources.BuildShader (theWorkspace, myShaderProgram); + myResources.SetShaderReady(); + } + + return myResources.ShaderProgram; + } + virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; virtual void Release (const Handle(OpenGl_Context)& theContext); - protected: +protected: - TEL_COLOUR myColor; - Aspect_TypeOfLine myType; - float myWidth; + TEL_COLOUR myColor; + Aspect_TypeOfLine myType; + float myWidth; + Handle(Graphic3d_ShaderProgram) myShaderProgram; + +protected: + + //! OpenGl resources + mutable struct Resources + { + public: + Resources() : myIsShaderReady (Standard_False) {} + + Standard_Boolean IsShaderReady() const { return myIsShaderReady; } + void SetShaderReady() { myIsShaderReady = Standard_True; } + void ResetShader () { myIsShaderReady = Standard_False; } + + void BuildShader (const Handle(OpenGl_Workspace)& theWS, const Handle(Graphic3d_ShaderProgram)& theShader); + + Handle(OpenGl_ShaderProgram) ShaderProgram; + TCollection_AsciiString ShaderProgramId; + + private: + + Standard_Boolean myIsShaderReady; + + } myResources; public: DEFINE_STANDARD_ALLOC diff --git a/src/OpenGl/OpenGl_AspectMarker.cxx b/src/OpenGl/OpenGl_AspectMarker.cxx index 2de0f836e7..78a077d834 100644 --- a/src/OpenGl/OpenGl_AspectMarker.cxx +++ b/src/OpenGl/OpenGl_AspectMarker.cxx @@ -21,14 +21,21 @@ #include #include #include +#include +#include #include #include #include +#include #include #include -static const TEL_COLOUR myDefaultColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }}; +namespace +{ + static const TEL_COLOUR myDefaultColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }}; + static const TCollection_AsciiString THE_EMPTY_KEY; +}; // Following Section relates to default markers @@ -1448,11 +1455,9 @@ OpenGl_AspectMarker::OpenGl_AspectMarker() : myColor (myDefaultColor), myType (Aspect_TOM_PLUS), myScale (1.0f), - myMarkerImage(), myMarkerSize (1.0f), - mySpriteKey (""), - mySpriteAKey (""), - myIsSpriteInit (Standard_False) + myMarkerImage(), + myShaderProgram() {} // ======================================================================= @@ -1468,94 +1473,164 @@ void OpenGl_AspectMarker::SetAspect (const CALL_DEF_CONTEXTMARKER& theAspect) myMarkerImage = theAspect.MarkerImage; myType = theAspect.MarkerType; myScale = myMarkerSize = theAspect.Scale; + myShaderProgram = theAspect.ShaderProgram; - // check that the resources need to be renewed - TCollection_AsciiString aNewKey, aNewKeyA; - resourceKeys (myMarkerImage, myType, myScale, myColor, aNewKey, aNewKeyA); - myIsSpriteInit = !aNewKey.IsEmpty() && mySpriteKey == aNewKey; - myIsSpriteInit &= !aNewKeyA.IsEmpty() && mySpriteAKey == aNewKeyA; + // update sprite resource bindings + TCollection_AsciiString aSpriteKey = THE_EMPTY_KEY; + TCollection_AsciiString aSpriteAKey = THE_EMPTY_KEY; + myResources.SpriteKeys (myMarkerImage, myType, myScale, myColor, aSpriteKey, aSpriteAKey); + + if (aSpriteKey.IsEmpty() || myResources.SpriteKey != aSpriteKey) + { + myResources.ResetSprite(); + } + if (aSpriteAKey.IsEmpty() || myResources.SpriteAKey != aSpriteAKey) + { + myResources.ResetSprite(); + } + + // update shader program resource bindings + const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId(); + + if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey) + { + myResources.ResetShader(); + } } // ======================================================================= -// function : buildSprites +// function : Render // purpose : // ======================================================================= -void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorkspace) const +void OpenGl_AspectMarker::Render (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + theWorkspace->SetAspectMarker (this); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void OpenGl_AspectMarker::Release (const Handle(OpenGl_Context)& theCtx) +{ + if (!myResources.Sprite.IsNull()) + { + if (!theCtx.IsNull()) + { + if (myResources.SpriteKey.IsEmpty()) + { + theCtx->DelayedRelease (myResources.Sprite); + theCtx->DelayedRelease (myResources.SpriteA); + } + else + { + 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); + } + } + myResources.Sprite.Nullify(); + myResources.SpriteA.Nullify(); + } + myResources.SpriteKey.Clear(); + myResources.SpriteAKey.Clear(); + myResources.ResetSprite(); + + if (!myResources.ShaderProgram.IsNull() && !theCtx.IsNull()) + { + theCtx->ShaderManager()->Unregister (myResources.ShaderProgram); + } + myResources.ShaderProgramId.Clear(); + myResources.ResetShader(); +} + +// ======================================================================= +// function : BuildSprites +// purpose : +// ======================================================================= +void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Workspace)& theWorkspace, + const Handle(Graphic3d_MarkerImage)& theMarkerImage, + const Aspect_TypeOfMarker theType, + const Standard_ShortReal theScale, + const TEL_COLOUR& theColor, + Standard_ShortReal& theMarkerSize) { const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); - TCollection_AsciiString aNewKey, aNewKeyA; - resourceKeys (myMarkerImage, myType, myMarkerSize, myColor, aNewKey, aNewKeyA); + // generate key for shared resource + TCollection_AsciiString aNewKey = THE_EMPTY_KEY; + TCollection_AsciiString aNewKeyA = THE_EMPTY_KEY; + SpriteKeys (theMarkerImage, theType, theScale, theColor, aNewKey, aNewKeyA); // release old shared resources - const Standard_Boolean aNewResource = aNewKey.IsEmpty() || mySpriteKey != aNewKey; + const Standard_Boolean aNewResource = aNewKey.IsEmpty() || SpriteKey != aNewKey; if (aNewResource) { - if (!mySprite.IsNull()) + if (!Sprite.IsNull()) { - if (mySpriteKey.IsEmpty()) + if (SpriteKey.IsEmpty()) { - aContext->DelayedRelease (mySprite); - mySprite.Nullify(); + aContext->DelayedRelease (Sprite); + Sprite.Nullify(); } else { - mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call - aContext->ReleaseResource (mySpriteKey); + Sprite.Nullify(); // we need nullify all handles before ReleaseResource() call + aContext->ReleaseResource (SpriteKey); } } - mySpriteKey = aNewKey; + SpriteKey = aNewKey; } - if (aNewKeyA.IsEmpty() - || mySpriteAKey != aNewKeyA) + if (aNewKeyA.IsEmpty() || SpriteAKey != aNewKeyA) { - if (!mySpriteA.IsNull()) + if (!SpriteA.IsNull()) { - if (mySpriteAKey.IsEmpty()) + if (SpriteAKey.IsEmpty()) { - aContext->DelayedRelease (mySpriteA); - mySpriteA.Nullify(); + aContext->DelayedRelease (SpriteA); + SpriteA.Nullify(); } else { - mySpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call - aContext->ReleaseResource (mySpriteKey); + SpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call + aContext->ReleaseResource (SpriteKey); } } - mySpriteAKey = aNewKeyA; + SpriteAKey = aNewKeyA; } - if (myType == Aspect_TOM_POINT + if (theType == Aspect_TOM_POINT || !aNewResource - || (myType == Aspect_TOM_USERDEFINED && myMarkerImage.IsNull())) + || (theType == Aspect_TOM_USERDEFINED && theMarkerImage.IsNull())) { // nothing to do - just simple point return; } if (!aNewKey.IsEmpty() - && aContext->GetResource (aNewKeyA, mySpriteA) // alpha sprite could be shared - && aContext->GetResource (aNewKey, mySprite)) + && aContext->GetResource (aNewKeyA, SpriteA) // alpha sprite could be shared + && aContext->GetResource (aNewKey, Sprite)) { // reuse shared resource - if (!mySprite->IsDisplayList()) + if (!Sprite->IsDisplayList()) { - myMarkerSize = Standard_ShortReal (Max (mySprite->SizeX(), mySprite->SizeY())); + theMarkerSize = Standard_ShortReal (Max (Sprite->SizeX(), Sprite->SizeY())); } return; } - const bool hadAlreadyAlpha = !mySpriteA.IsNull(); + const bool hadAlreadyAlpha = !SpriteA.IsNull(); if (!hadAlreadyAlpha) { - mySpriteA = new OpenGl_PointSprite(); + SpriteA = new OpenGl_PointSprite(); } - mySprite = new OpenGl_PointSprite(); + Sprite = new OpenGl_PointSprite(); if (!aNewKey.IsEmpty()) { - aContext->ShareResource (aNewKey, mySprite); + aContext->ShareResource (aNewKey, Sprite); if (!hadAlreadyAlpha) { - aContext->ShareResource (aNewKeyA, mySpriteA); + aContext->ShareResource (aNewKeyA, SpriteA); } } @@ -1567,9 +1642,9 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks Handle(Graphic3d_MarkerImage) aNewMarkerImage; Handle(Image_PixMap) anImage, anImageA; - if (myType == Aspect_TOM_USERDEFINED && !myMarkerImage.IsNull()) + if (theType == Aspect_TOM_USERDEFINED && !theMarkerImage.IsNull()) { - aNewMarkerImage = myMarkerImage; + aNewMarkerImage = theMarkerImage; anImage = aNewMarkerImage->GetImage(); } else @@ -1579,14 +1654,14 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks Handle(Graphic3d_MarkerImage) aMarkerImage1, aMarkerImage2; const Standard_ShortReal aDelta = 0.1F; - Standard_ShortReal aScale = myScale; + Standard_ShortReal aScale = theScale; Standard_ShortReal aLimit = 0.0F; - switch (myType) + switch (theType) { case Aspect_TOM_O_POINT: { - const Standard_Integer aSize = myScale > 7 ? 7 : (Standard_Integer )(myScale + 0.5F); + const Standard_Integer aSize = theScale > 7 ? 7 : (Standard_Integer )(theScale + 0.5F); const Standard_Integer aNumOfBytes = (aSize / 8 + (aSize % 8 ? 1 : 0)) * aSize; aBitMap = new TColStd_HArray1OfByte (0, aNumOfBytes - 1); for (Standard_Integer anIter = 0; anIter < aBitMap->Length(); anIter++) @@ -1601,10 +1676,10 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks { // For this type of markers we merge two base bitmaps into one // For example Aspect_TOM_O_PLUS = Aspect_TOM_O + Aspect_TOM_PLUS - aMarkerImage1 = GetTextureImage (Aspect_TOM_O, myScale); - if (myType != Aspect_TOM_O_POINT) + aMarkerImage1 = GetTextureImage (Aspect_TOM_O, theScale); + if (theType != Aspect_TOM_O_POINT) { - aMarkerImage2 = GetTextureImage (Aspect_TypeOfMarker (myType - Aspect_TOM_O_POINT), myScale); + aMarkerImage2 = GetTextureImage (Aspect_TypeOfMarker (theType - Aspect_TOM_O_POINT), theScale); } anImage = MergeImages (aMarkerImage1->GetImage(), aMarkerImage2->GetImage()); aNewMarkerImage = new Graphic3d_MarkerImage (anImage); @@ -1630,10 +1705,10 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks GetMarkerBitMapParam (Aspect_TOM_O, aScale, aWidth, aHeight, anOffset, aNumOfBytes); const Standard_ShortReal aDelta = 0.1f; - NCollection_Vec4 aColor (Standard_Real (myColor.rgb[0]), - Standard_Real (myColor.rgb[1]), - Standard_Real (myColor.rgb[2]), - Standard_Real (myColor.rgb[3])); + NCollection_Vec4 aColor (Standard_Real (theColor.rgb[0]), + Standard_Real (theColor.rgb[1]), + Standard_Real (theColor.rgb[2]), + Standard_Real (theColor.rgb[3])); const Standard_Integer aSize = Max (aWidth + 2, aHeight + 2); // includes extra margin anImage = new Image_PixMap(); @@ -1679,27 +1754,27 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks } default: { - aNewMarkerImage = GetTextureImage (myType, myScale); + aNewMarkerImage = GetTextureImage (theType, theScale); anImage = aNewMarkerImage->GetImage(); break; } } } - myMarkerSize = Max ((Standard_ShortReal )anImage->Width(),(Standard_ShortReal )anImage->Height()); + theMarkerSize = Max ((Standard_ShortReal )anImage->Width(),(Standard_ShortReal )anImage->Height()); - mySprite->Init (aContext, *anImage.operator->(), Graphic3d_TOT_2D); + Sprite->Init (aContext, *anImage.operator->(), Graphic3d_TOT_2D); if (!hadAlreadyAlpha) { if (anImageA.IsNull() - && mySprite->GetFormat() != GL_ALPHA8 + && Sprite->GetFormat() != GL_ALPHA8 && !aNewMarkerImage.IsNull()) { anImageA = aNewMarkerImage->GetImageAlpha(); } if (!anImageA.IsNull()) { - mySpriteA->Init (aContext, *anImageA.operator->(), Graphic3d_TOT_2D); + SpriteA->Init (aContext, *anImageA.operator->(), Graphic3d_TOT_2D); } } } @@ -1707,15 +1782,15 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks { // Creating list with bitmap for using it in compatibility mode GLuint aBitmapList = glGenLists (1); - mySprite->SetDisplayList (aContext, aBitmapList); + Sprite->SetDisplayList (aContext, aBitmapList); Standard_Integer aWidth, aHeight, anOffset, aNumOfBytes; - if (myType == Aspect_TOM_USERDEFINED && !myMarkerImage.IsNull()) + if (theType == Aspect_TOM_USERDEFINED && !theMarkerImage.IsNull()) { // Reading user defined marker - Handle(TColStd_HArray1OfByte) aBitMap = myMarkerImage->GetBitMapArray(); + Handle(TColStd_HArray1OfByte) aBitMap = theMarkerImage->GetBitMapArray(); Standard_Byte* aBitMapArray = new Standard_Byte[aBitMap->Length()]; - myMarkerImage->GetTextureSize (aWidth, aHeight); + theMarkerImage->GetTextureSize (aWidth, aHeight); // We should pass bitmap to glBitmap with reversed line order as it draws it from // bottom to top @@ -1742,11 +1817,11 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks { // Creating list for default marker const Standard_ShortReal aDelta = 0.1f; - Standard_ShortReal aScale = myScale; + Standard_ShortReal aScale = theScale; Standard_ShortReal aLimit = 0.0f; glNewList (aBitmapList, GL_COMPILE); - switch (myType) + switch (theType) { case Aspect_TOM_O_PLUS: case Aspect_TOM_O_STAR: @@ -1754,10 +1829,10 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks { // For this type of markers we merge two base bitmaps into one // For example Aspect_TOM_O_PLUS = Aspect_TOM_O + Aspect_TOM_PLUS - GetMarkerBitMapParam (Aspect_TOM_O, myScale, aWidth, aHeight, anOffset, aNumOfBytes); + GetMarkerBitMapParam (Aspect_TOM_O, theScale, aWidth, aHeight, anOffset, aNumOfBytes); glBitmap ((GLsizei )aWidth, (GLsizei )aHeight, (GLfloat )(0.5f * aWidth), (GLfloat )(0.5f * aHeight), 0.f, 0.f, (const GLubyte* )&OpenGl_AspectMarker_myMarkerRaster[anOffset]); - GetMarkerBitMapParam (Aspect_TypeOfMarker (myType - Aspect_TOM_O_POINT), myScale, aWidth, aHeight, anOffset, aNumOfBytes); + GetMarkerBitMapParam (Aspect_TypeOfMarker (theType - Aspect_TOM_O_POINT), theScale, aWidth, aHeight, anOffset, aNumOfBytes); glBitmap ((GLsizei )aWidth, (GLsizei )aHeight, (GLfloat )(0.5f * aWidth), (GLfloat )(0.5f * aHeight), 0.f, 0.f, (const GLubyte* )&OpenGl_AspectMarker_myMarkerRaster[anOffset]); break; @@ -1765,10 +1840,10 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks case Aspect_TOM_BALL: { const Standard_ShortReal aDelta = 0.1f; - NCollection_Vec4 aColor (Standard_Real (myColor.rgb[0]), - Standard_Real (myColor.rgb[1]), - Standard_Real (myColor.rgb[2]), - Standard_Real (myColor.rgb[3])); + NCollection_Vec4 aColor (Standard_Real (theColor.rgb[0]), + Standard_Real (theColor.rgb[1]), + Standard_Real (theColor.rgb[2]), + Standard_Real (theColor.rgb[3])); // we draw a set of circles while (aScale >= 1.0f) @@ -1805,7 +1880,7 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks } default: { - GetMarkerBitMapParam (myType, myScale, aWidth, aHeight, anOffset, aNumOfBytes); + GetMarkerBitMapParam (theType, theScale, aWidth, aHeight, anOffset, aNumOfBytes); glBitmap ((GLsizei )aWidth, (GLsizei )aHeight, 0.5f * GLfloat(aWidth), 0.5f * GLfloat(aHeight), 0.0f, 0.0f, (const GLubyte* )&OpenGl_AspectMarker_myMarkerRaster[anOffset]); break; @@ -1816,16 +1891,53 @@ void OpenGl_AspectMarker::buildSprites (const Handle(OpenGl_Workspace)& theWorks } } +// ======================================================================= +// function : BuildShader +// purpose : +// ======================================================================= +void OpenGl_AspectMarker::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_ShaderProgram)& theShader) +{ + const Handle(OpenGl_Context)& aContext = theWS->GetGlContext(); + + if (!aContext->IsGlGreaterEqual (2, 0)) + return; + + // release old shader program resources + if (!ShaderProgram.IsNull()) + { + aContext->ShaderManager()->Unregister (ShaderProgram); + } + + ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId(); + + if (!theShader.IsNull()) + { + if (!aContext->GetResource (ShaderProgramId, ShaderProgram)) + { + ShaderProgram = aContext->ShaderManager()->Create (theShader); + if (!ShaderProgramId.IsEmpty()) + { + aContext->ShareResource (ShaderProgramId, ShaderProgram); + } + } + } + else + { + ShaderProgram.Nullify(); + } +} + // ======================================================================= // function : resourceKeys // purpose : // ======================================================================= -void OpenGl_AspectMarker::resourceKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage, - const Aspect_TypeOfMarker theType, - const Standard_ShortReal theScale, - const TEL_COLOUR& theColor, - TCollection_AsciiString& theKey, - TCollection_AsciiString& theKeyA) const +void OpenGl_AspectMarker::Resources::SpriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage, + const Aspect_TypeOfMarker theType, + const Standard_ShortReal theScale, + const TEL_COLOUR& theColor, + TCollection_AsciiString& theKey, + TCollection_AsciiString& theKeyA) { // generate key for shared resource if (theType == Aspect_TOM_USERDEFINED) @@ -1856,42 +1968,3 @@ void OpenGl_AspectMarker::resourceKeys (const Handle(Graphic3d_MarkerImage)& the } } } - -// ======================================================================= -// function : Render -// purpose : -// ======================================================================= -void OpenGl_AspectMarker::Render (const Handle(OpenGl_Workspace)& theWorkspace) const -{ - theWorkspace->SetAspectMarker (this); -} - -// ======================================================================= -// function : Release -// purpose : -// ======================================================================= -void OpenGl_AspectMarker::Release (const Handle(OpenGl_Context)& theCtx) -{ - if (!mySprite.IsNull()) - { - if (!theCtx.IsNull()) - { - if (mySpriteKey.IsEmpty()) - { - theCtx->DelayedRelease (mySprite); - theCtx->DelayedRelease (mySpriteA); - } - else - { - mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call - mySpriteA.Nullify(); - theCtx->ReleaseResource (mySpriteKey, Standard_True); - theCtx->ReleaseResource (mySpriteAKey, Standard_True); - } - } - mySprite.Nullify(); - mySpriteA.Nullify(); - } - mySpriteKey.Clear(); - mySpriteAKey.Clear(); -} diff --git a/src/OpenGl/OpenGl_AspectMarker.hxx b/src/OpenGl/OpenGl_AspectMarker.hxx index 0a3eb8b8cc..7477e047df 100644 --- a/src/OpenGl/OpenGl_AspectMarker.hxx +++ b/src/OpenGl/OpenGl_AspectMarker.hxx @@ -27,6 +27,7 @@ #include #include +#include #include @@ -65,58 +66,106 @@ public: //! Init and return OpenGl point sprite resource. //! @return point sprite texture. - const Handle(OpenGl_PointSprite)& Sprite (const Handle(OpenGl_Workspace)& theWorkspace) const + const Handle(OpenGl_PointSprite)& SpriteRes (const Handle(OpenGl_Workspace)& theWorkspace) const { - if (!myIsSpriteInit) + if (!myResources.IsSpriteReady()) { - buildSprites (theWorkspace); - myIsSpriteInit = Standard_True; + myResources.BuildSprites (theWorkspace, myMarkerImage, myType, myScale, myColor, myMarkerSize); + myResources.SetSpriteReady(); } - return mySprite; + return myResources.Sprite; } //! Init and return OpenGl highlight point sprite resource. //! @return point sprite texture for highlight. - const Handle(OpenGl_PointSprite)& SpriteHighlight (const Handle(OpenGl_Workspace)& theWorkspace) const + const Handle(OpenGl_PointSprite)& SpriteHighlightRes (const Handle(OpenGl_Workspace)& theWorkspace) const { - if (!myIsSpriteInit) + if (!myResources.IsSpriteReady()) { - buildSprites (theWorkspace); - myIsSpriteInit = Standard_True; + myResources.BuildSprites (theWorkspace, myMarkerImage, myType, myScale, myColor, myMarkerSize); + myResources.SetSpriteReady(); } - return mySpriteA; + return myResources.SpriteA; + } + + //! Init and return OpenGl shader program resource. + //! @return shader program resource. + const Handle(OpenGl_ShaderProgram)& ShaderProgramRes (const Handle(OpenGl_Workspace)& theWorkspace) const + { + if (!myResources.IsShaderReady()) + { + myResources.BuildShader (theWorkspace, myShaderProgram); + myResources.SetShaderReady(); + } + + return myResources.ShaderProgram; } virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; virtual void Release (const Handle(OpenGl_Context)& theContext); -protected: +protected: //! @name ordinary aspect properties - void buildSprites (const Handle(OpenGl_Workspace)& theWorkspace) const; - void resourceKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage, + TEL_COLOUR myColor; + Aspect_TypeOfMarker myType; + Standard_ShortReal myScale; + mutable Standard_ShortReal myMarkerSize; + Handle(Graphic3d_MarkerImage) myMarkerImage; + Handle(Graphic3d_ShaderProgram) myShaderProgram; + +protected: //! @name OpenGl resources + + //! OpenGl resources + mutable struct Resources + { + public: + + Resources() : + SpriteKey (""), + SpriteAKey (""), + myIsSpriteReady (Standard_False), + myIsShaderReady (Standard_False) {} + + Standard_Boolean IsSpriteReady() const { return myIsSpriteReady; } + Standard_Boolean IsShaderReady() const { return myIsShaderReady; } + void SetSpriteReady() { myIsSpriteReady = Standard_True; } + void SetShaderReady() { myIsShaderReady = Standard_True; } + void ResetSprite () { myIsSpriteReady = Standard_False; } + void ResetShader () { myIsShaderReady = Standard_False; } + + void BuildSprites (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_MarkerImage)& theMarkerImage, + const Aspect_TypeOfMarker theType, + const Standard_ShortReal theScale, + const TEL_COLOUR& theColor, + Standard_ShortReal& theMarkerSize); + + void BuildShader (const Handle(OpenGl_Workspace)& theWS, const Handle(Graphic3d_ShaderProgram)& theShader); + + void SpriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage, const Aspect_TypeOfMarker theType, const Standard_ShortReal theScale, const TEL_COLOUR& theColor, TCollection_AsciiString& theKey, - TCollection_AsciiString& theKeyA) const; + TCollection_AsciiString& theKeyA); -protected: //! @name ordinary aspect properties + Handle(OpenGl_PointSprite) Sprite; + TCollection_AsciiString SpriteKey; - TEL_COLOUR myColor; - Aspect_TypeOfMarker myType; - Standard_ShortReal myScale; - Handle(Graphic3d_MarkerImage) myMarkerImage; + Handle(OpenGl_PointSprite) SpriteA; + TCollection_AsciiString SpriteAKey; -protected: //! @name OpenGl resources + Handle(OpenGl_ShaderProgram) ShaderProgram; + TCollection_AsciiString ShaderProgramId; - mutable Standard_ShortReal myMarkerSize; - mutable TCollection_AsciiString mySpriteKey; - mutable TCollection_AsciiString mySpriteAKey; - mutable Standard_Boolean myIsSpriteInit; - mutable Handle(OpenGl_PointSprite) mySprite; //!< normal sprite - mutable Handle(OpenGl_PointSprite) mySpriteA; //!< extra alpha-only sprite for RGB sprites + private: + + Standard_Boolean myIsSpriteReady; + Standard_Boolean myIsShaderReady; + + } myResources; public: diff --git a/src/OpenGl/OpenGl_AspectText.cxx b/src/OpenGl/OpenGl_AspectText.cxx index 8cf3e6ce8f..482a374e5f 100644 --- a/src/OpenGl/OpenGl_AspectText.cxx +++ b/src/OpenGl/OpenGl_AspectText.cxx @@ -17,12 +17,18 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. +#include + #include +#include #include +#include +#include namespace { static const TEL_COLOUR TheDefaultColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }}; + static const TCollection_AsciiString THE_EMPTY_KEY; }; // ======================================================================= @@ -37,7 +43,8 @@ OpenGl_AspectText::OpenGl_AspectText() myStyleType (Aspect_TOST_NORMAL), myDisplayType (Aspect_TODT_NORMAL), myFontAspect (Font_FA_Regular), - myZoomable (false) + myZoomable (false), + myShaderProgram() { // } @@ -58,6 +65,7 @@ OpenGl_AspectText::~OpenGl_AspectText() void OpenGl_AspectText::SetAspect (const CALL_DEF_CONTEXTTEXT& theAspect) { myFont = theAspect.Font; + myColor.rgb[0] = (float )theAspect.Color.r; myColor.rgb[1] = (float )theAspect.Color.g; myColor.rgb[2] = (float )theAspect.Color.b; @@ -66,11 +74,22 @@ void OpenGl_AspectText::SetAspect (const CALL_DEF_CONTEXTTEXT& theAspect) mySubtitleColor.rgb[1] = (float )theAspect.ColorSubTitle.g; mySubtitleColor.rgb[2] = (float )theAspect.ColorSubTitle.b; mySubtitleColor.rgb[3] = 1.0f; + myAngle = (float )theAspect.TextAngle; myStyleType = (Aspect_TypeOfStyleText )theAspect.Style; myDisplayType = (Aspect_TypeOfDisplayText )theAspect.DisplayType; myFontAspect = (Font_FontAspect )theAspect.TextFontAspect; myZoomable = (theAspect.TextZoomable != 0); + + // update resource bindings + myShaderProgram = theAspect.ShaderProgram; + + const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId(); + + if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey) + { + myResources.ResetShader(); + } } // ======================================================================= @@ -86,7 +105,49 @@ void OpenGl_AspectText::Render (const Handle(OpenGl_Workspace)& theWorkspace) co // function : Release // purpose : // ======================================================================= -void OpenGl_AspectText::Release (const Handle(OpenGl_Context)&) +void OpenGl_AspectText::Release (const Handle(OpenGl_Context)& theContext) { - // + if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull()) + { + theContext->ShaderManager()->Unregister (myResources.ShaderProgram); + } + myResources.ShaderProgramId.Clear(); + myResources.ResetShader(); +} + +// ======================================================================= +// function : BuildShader +// purpose : +// ======================================================================= +void OpenGl_AspectText::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS, + const Handle(Graphic3d_ShaderProgram)& theShader) +{ + const Handle(OpenGl_Context)& aContext = theWS->GetGlContext(); + + if (!aContext->IsGlGreaterEqual (2, 0)) + return; + + // release old shader program resources + if (!ShaderProgram.IsNull()) + { + aContext->ShaderManager()->Unregister (ShaderProgram); + } + + ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId(); + + if (!theShader.IsNull()) + { + if (!aContext->GetResource (ShaderProgramId, ShaderProgram)) + { + ShaderProgram = aContext->ShaderManager()->Create (theShader); + if (!ShaderProgramId.IsEmpty()) + { + aContext->ShareResource (ShaderProgramId, ShaderProgram); + } + } + } + else + { + ShaderProgram.Nullify(); + } } diff --git a/src/OpenGl/OpenGl_AspectText.hxx b/src/OpenGl/OpenGl_AspectText.hxx index b0f3a7db7d..e426ae6b2c 100644 --- a/src/OpenGl/OpenGl_AspectText.hxx +++ b/src/OpenGl/OpenGl_AspectText.hxx @@ -28,6 +28,7 @@ #include #include +#include //! Text representation parameters class OpenGl_AspectText : public OpenGl_Element @@ -118,19 +119,56 @@ public: return mySubtitleColor; } + //! Init and return OpenGl shader program resource. + //! @return shader program resource. + const Handle(OpenGl_ShaderProgram)& ShaderProgramRes (const Handle(OpenGl_Workspace)& theWorkspace) const + { + if (!myResources.IsShaderReady()) + { + myResources.BuildShader (theWorkspace, myShaderProgram); + myResources.SetShaderReady(); + } + + return myResources.ShaderProgram; + } + virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; virtual void Release (const Handle(OpenGl_Context)& theContext); protected: - TCollection_AsciiString myFont; - TEL_COLOUR myColor; - TEL_COLOUR mySubtitleColor; - float myAngle; - Aspect_TypeOfStyleText myStyleType; - Aspect_TypeOfDisplayText myDisplayType; - Font_FontAspect myFontAspect; - bool myZoomable; + TCollection_AsciiString myFont; + TEL_COLOUR myColor; + TEL_COLOUR mySubtitleColor; + float myAngle; + Aspect_TypeOfStyleText myStyleType; + Aspect_TypeOfDisplayText myDisplayType; + Font_FontAspect myFontAspect; + bool myZoomable; + Handle(Graphic3d_ShaderProgram) myShaderProgram; + +protected: + + //! OpenGl resources + mutable struct Resources + { + public: + Resources() : myIsShaderReady (Standard_False) {} + + Standard_Boolean IsShaderReady() const { return myIsShaderReady; } + void SetShaderReady() { myIsShaderReady = Standard_True; } + void ResetShader () { myIsShaderReady = Standard_False; } + + void BuildShader (const Handle(OpenGl_Workspace)& theWS, const Handle(Graphic3d_ShaderProgram)& theShader); + + Handle(OpenGl_ShaderProgram) ShaderProgram; + TCollection_AsciiString ShaderProgramId; + + private: + + Standard_Boolean myIsShaderReady; + + } myResources; public: diff --git a/src/OpenGl/OpenGl_ClippingState.cxx b/src/OpenGl/OpenGl_Clipping.cxx similarity index 88% rename from src/OpenGl/OpenGl_ClippingState.cxx rename to src/OpenGl/OpenGl_Clipping.cxx index 25c7b0fc7c..c8e7e6b409 100644 --- a/src/OpenGl/OpenGl_ClippingState.cxx +++ b/src/OpenGl/OpenGl_Clipping.cxx @@ -17,7 +17,7 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#include +#include #include #include @@ -30,7 +30,7 @@ namespace // function : OpenGl_ClippingState // purpose : // ======================================================================= -OpenGl_ClippingState::OpenGl_ClippingState () +OpenGl_Clipping::OpenGl_Clipping () : myPlanes(), myPlaneStates(), myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE5)) @@ -40,7 +40,7 @@ OpenGl_ClippingState::OpenGl_ClippingState () // function : Init // purpose : // ======================================================================= -void OpenGl_ClippingState::Init (const Standard_Integer theMaxPlanes) +void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes) { myPlanes.Clear(); myPlaneStates.Clear(); @@ -53,9 +53,9 @@ void OpenGl_ClippingState::Init (const Standard_Integer theMaxPlanes) // function : Add // purpose : // ======================================================================= -void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, - const EquationCoords& theCoordSpace, - const Handle(OpenGl_Workspace)& theWS) +void OpenGl_Clipping::Add (Graphic3d_SetOfHClipPlane& thePlanes, + const EquationCoords& theCoordSpace, + const Handle(OpenGl_Workspace)& theWS) { GLint aMatrixMode; glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); @@ -90,7 +90,7 @@ void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, // function : Add // purpose : // ======================================================================= -void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace) +void OpenGl_Clipping::Add (Graphic3d_SetOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace) { Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes); while (aPlaneIt.More() && myEmptyPlaneIds->Available() > 0) @@ -121,7 +121,7 @@ void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, const Equa // function : Remove // purpose : // ======================================================================= -void OpenGl_ClippingState::Remove (const Graphic3d_SetOfHClipPlane& thePlanes) +void OpenGl_Clipping::Remove (const Graphic3d_SetOfHClipPlane& thePlanes) { Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes); for (; aPlaneIt.More(); aPlaneIt.Next()) @@ -159,7 +159,7 @@ void OpenGl_ClippingState::Remove (const Graphic3d_SetOfHClipPlane& thePlanes) // function : SetEnabled // purpose : // ======================================================================= -void OpenGl_ClippingState::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane, +void OpenGl_Clipping::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane, const Standard_Boolean theIsEnabled) { if (!Contains (thePlane)) diff --git a/src/OpenGl/OpenGl_ClippingState.hxx b/src/OpenGl/OpenGl_Clipping.hxx similarity index 97% rename from src/OpenGl/OpenGl_ClippingState.hxx rename to src/OpenGl/OpenGl_Clipping.hxx index 5b087c1582..e84be9d6c0 100644 --- a/src/OpenGl/OpenGl_ClippingState.hxx +++ b/src/OpenGl/OpenGl_Clipping.hxx @@ -17,8 +17,8 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#ifndef _OpenGl_ClippingState_H__ -#define _OpenGl_ClippingState_H__ +#ifndef _OpenGl_Clipping_H__ +#define _OpenGl_Clipping_H__ #include #include @@ -34,7 +34,7 @@ //! clipping planes and provides method to change clippings in context. The methods //! should be executed within OpenGl context associated with instance of this //! class. -class OpenGl_ClippingState +class OpenGl_Clipping { public: @@ -48,7 +48,7 @@ public: public: //! @name general methods //! Default constructor. - Standard_EXPORT OpenGl_ClippingState(); + Standard_EXPORT OpenGl_Clipping(); //! Initialize. //! @param theMaxPlanes [in] number of clipping planes supported by OpenGl context. @@ -209,8 +209,8 @@ private: private: //! Copying allowed only within Handles - OpenGl_ClippingState (const OpenGl_ClippingState& ); - OpenGl_ClippingState& operator= (const OpenGl_ClippingState& ); + OpenGl_Clipping (const OpenGl_Clipping& ); + OpenGl_Clipping& operator= (const OpenGl_Clipping& ); }; #endif diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 4862cf325e..85f7481f1e 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -30,8 +30,10 @@ #include #include #include +#include #include + #include #include @@ -88,7 +90,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) extGS (NULL), extBgra(Standard_False), extAnis(Standard_False), - extPDS(Standard_False), + extPDS (Standard_False), atiMem (Standard_False), nvxMem (Standard_False), mySharedResources (new OpenGl_ResourcesMap()), @@ -117,6 +119,8 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) // (depends on renderer). myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); #endif + + myShaderManager = new OpenGl_ShaderManager (this); } // ======================================================================= @@ -487,7 +491,7 @@ void OpenGl_Context::readGlVersion() GLint aMajor = 0, aMinor = 0; glGetIntegerv (GL_MAJOR_VERSION, &aMajor); glGetIntegerv (GL_MINOR_VERSION, &aMinor); - // glGetError() sometimes does not report an error here even if + // glGetError() sometimes does not report an error here even if // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants. // This happens on some rendereres like e.g. Cygwin MESA. // Thus checking additionally if GL has put anything to @@ -816,7 +820,7 @@ void OpenGl_Context::init() && FindProcShort (myGlCore20, glLoadTransposeMatrixd) && FindProcShort (myGlCore20, glMultTransposeMatrixf) && FindProcShort (myGlCore20, glMultTransposeMatrixd); - + // Check if OpenGL 1.4 core functionality is actually present Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4) && FindProcShort (myGlCore20, glBlendFuncSeparate) diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 4ecd9289f2..d69c472d05 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ #include #include #include -#include +#include //! Forward declarations struct OpenGl_GlCore12; @@ -248,10 +249,13 @@ public: Standard_EXPORT void ReleaseDelayed(); //! @return tool for management of clippings within this context. - inline OpenGl_ClippingState& ChangeClipping() { return myClippingState; } + inline OpenGl_Clipping& ChangeClipping() { return myClippingState; } //! @return tool for management of clippings within this context. - inline const OpenGl_ClippingState& Clipping() const { return myClippingState; } + inline const OpenGl_Clipping& Clipping() const { return myClippingState; } + + //! @return tool for management of shader programs within this context. + inline const Handle(OpenGl_ShaderManager)& ShaderManager() const { return myShaderManager; } public: @@ -350,7 +354,7 @@ private: // context info Handle(OpenGl_DelayReleaseMap) myDelayed; //!< shared resources for delayed release Handle(OpenGl_ResourcesQueue) myReleaseQueue; //!< queue of resources for delayed clean up - OpenGl_ClippingState myClippingState; //!< state of clip planes + OpenGl_Clipping myClippingState; //!< state of clip planes void* myGlLibHandle; //!< optional handle to GL library OpenGl_GlCore20* myGlCore20; //!< common structure for GL core functions upto 2.0 @@ -362,6 +366,8 @@ private: // context info Standard_Boolean myIsFeedback; //!< flag indicates GL_FEEDBACK mode Standard_Boolean myIsInitialized; //!< flag indicates initialization state + Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs + private: //! Copying allowed only within Handles diff --git a/src/OpenGl/OpenGl_GraphicDriver_Layer.cxx b/src/OpenGl/OpenGl_GraphicDriver_Layer.cxx index 33b977e282..fcadda9a19 100755 --- a/src/OpenGl/OpenGl_GraphicDriver_Layer.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver_Layer.cxx @@ -38,7 +38,6 @@ struct OpenGl_LAYER_PROP int NbPoints; int LineType; float LineWidth; - OpenGl_AspectText AspectText; OpenGl_TextParam TextParam; }; @@ -67,11 +66,11 @@ static OpenGl_LAYER_PROP TheLayerProp; /*----------------------------------------------------------------------*/ -void InitLayerProp (const int AListId) +void InitLayerProp (const int theListId) { - TheLayerProp.ListId = AListId; + TheLayerProp.ListId = theListId; - if (AListId) + if (theListId) { TheLayerProp.Color = myDefaultColor; TheLayerProp.NbPoints = 0; @@ -115,7 +114,7 @@ void OpenGl_GraphicDriver::BeginLayer (const Aspect_CLayer2d& ACLayer) call_def_ptrLayer ptrLayer = (call_def_ptrLayer) ACLayer.ptrLayer; if (!ptrLayer) return; - InitLayerProp(ptrLayer->listIndex); + InitLayerProp (ptrLayer->listIndex); if (!TheLayerProp.ListId) return; glNewList (TheLayerProp.ListId, GL_COMPILE); @@ -140,7 +139,7 @@ void OpenGl_GraphicDriver::ClearLayer (const Aspect_CLayer2d& ACLayer) { if (!ACLayer.ptrLayer) return; - InitLayerProp(ACLayer.ptrLayer->listIndex); + InitLayerProp (ACLayer.ptrLayer->listIndex); if (!TheLayerProp.ListId) return; glNewList (TheLayerProp.ListId, GL_COMPILE); diff --git a/src/OpenGl/OpenGl_Group.cxx b/src/OpenGl/OpenGl_Group.cxx index 38d2d8332c..5c6a63ce4d 100644 --- a/src/OpenGl/OpenGl_Group.cxx +++ b/src/OpenGl/OpenGl_Group.cxx @@ -27,11 +27,12 @@ // purpose : // ======================================================================= OpenGl_Group::OpenGl_Group () -: myAspectLine(NULL), - myAspectFace(NULL), - myAspectMarker(NULL), - myAspectText(NULL), - myFirst(NULL), myLast(NULL) +: myAspectLine (NULL), + myAspectFace (NULL), + myAspectMarker (NULL), + myAspectText (NULL), + myFirst (NULL), + myLast (NULL) { } diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index f806cc7754..ceda9b74dd 100755 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -17,19 +17,44 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#include -#include - -#include - #include +#include #include +#include #include +#include +#include +#include #include #include #include +namespace +{ + template + void BindProgramWithMaterial (const Handle(OpenGl_Workspace)& theWS, + const T* theAspect) + { + const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext(); + const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS); + if (aProgram.IsNull()) + { + OpenGl_ShaderProgram::Unbind (aCtx); + return; + } + aProgram->BindWithVariables (aCtx); + + const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram); + if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect) + { + aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, theAspect); + } + + aCtx->ShaderManager()->PushState (aProgram); + } +} + // ======================================================================= // function : clearMemoryOwn // purpose : @@ -409,10 +434,15 @@ void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeCo if (myDrawMode > GL_LINE_STRIP) { anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge()); - theWorkspace->AspectLine (Standard_True); + const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True); glPushAttrib (GL_POLYGON_BIT); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + + if (aGlContext->IsGlGreaterEqual (2, 0)) + { + BindProgramWithMaterial (theWorkspace, anAspect); + } } Tint i, j, n; @@ -539,7 +569,7 @@ void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWork { const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True); const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->Sprite(theWorkspace); + const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace); const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT); if (aCtx->IsGlGreaterEqual (2, 0) && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList()) @@ -550,8 +580,8 @@ void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWork Handle(OpenGl_Texture) aTextureBack; if (anAspectMarker->Type() != Aspect_TOM_POINT) { - const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlight(theWorkspace)->IsValid()) - ? anAspectMarker->SpriteHighlight(theWorkspace) + const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid()) + ? anAspectMarker->SpriteHighlightRes (theWorkspace) : aSpriteNorm; aTextureBack = theWorkspace->EnableTexture (aSprite); @@ -704,7 +734,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace if (!myIsVboInit && !aCtx->caps->vboDisable && aCtx->core15 != NULL - && (myDrawMode != GL_POINTS || anAspectMarker->Sprite(theWorkspace).IsNull() || !anAspectMarker->Sprite(theWorkspace)->IsDisplayList())) + && (myDrawMode != GL_POINTS || anAspectMarker->SpriteRes (theWorkspace).IsNull() || !anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList())) { if (!BuildVBO (theWorkspace)) { @@ -742,6 +772,29 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace aFrontLightingModel = 0; } + if (aCtx->IsGlGreaterEqual (2, 0)) + { + switch (myPArray->type) + { + case TelPointsArrayType: + { + BindProgramWithMaterial (theWorkspace, anAspectMarker); + break; + } + case TelSegmentsArrayType: + case TelPolylinesArrayType: + { + BindProgramWithMaterial (theWorkspace, anAspectLine); + break; + } + default: // polygonal array + { + BindProgramWithMaterial (theWorkspace, anAspectFace); + break; + } + } + } + DrawArray (aFrontLightingModel, anAspectFace->InteriorStyle(), anAspectFace->Edge(), diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx new file mode 100644 index 0000000000..97b0fbb0ed --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -0,0 +1,759 @@ +// Created on: 2013-09-26 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient) + +// ======================================================================= +// function : OpenGl_ShaderManager +// purpose : Creates new empty shader manager +// ======================================================================= +OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) +: myContext (theContext), + myIsPP (Standard_False) +{ + // +} + +// ======================================================================= +// function : ~OpenGl_ShaderManager +// purpose : Releases resources of shader manager +// ======================================================================= +OpenGl_ShaderManager::~OpenGl_ShaderManager() +{ + myProgramList.Clear(); +} + +// ======================================================================= +// function : Create +// purpose : Creates new shader program +// ======================================================================= +Handle(OpenGl_ShaderProgram) OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxyProgram) +{ + if (theProxyProgram.IsNull()) + { + return NULL; + } + + Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram (theProxyProgram); + if (!aProgram->Initialize (myContext, theProxyProgram->ShaderObjects())) + { + return NULL; + } + + myProgramList.Append (aProgram); + + return aProgram; +} + +// ======================================================================= +// function : Unregister +// purpose : Removes specified shader program from the manager +// ======================================================================= +void OpenGl_ShaderManager::Unregister (Handle(OpenGl_ShaderProgram)& theProgram) +{ + for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) + { + if (anIt.Value() == theProgram) + { + myProgramList.Remove (anIt); + break; + } + } + + const TCollection_AsciiString anID = theProgram->myProxy->GetId(); + if (anID.IsEmpty()) + { + myContext->DelayedRelease (theProgram); + theProgram.Nullify(); + } + else + { + theProgram.Nullify(); + myContext->ReleaseResource (anID); + } +} + +// ======================================================================= +// function : ShaderPrograms +// purpose : Returns list of registered shader programs +// ======================================================================= +const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const +{ + return myProgramList; +} + +// ======================================================================= +// function : Empty +// purpose : Returns true if no program objects are attached +// ======================================================================= +Standard_Boolean OpenGl_ShaderManager::IsEmpty() const +{ + return myProgramList.IsEmpty(); +} + +// ======================================================================= +// function : UpdateLightSourceStateTo +// purpose : Updates state of OCCT light sources +// ======================================================================= +void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights) +{ + myLightSourceState.Set (theLights); + myLightSourceState.Update(); +} + +// ======================================================================= +// function : SetProjectionState +// purpose : Sets new state of OCCT projection transform +// ======================================================================= +void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix) +{ + myProjectionState.Set (theProjectionMatrix); + myProjectionState.Update(); +} + +// ======================================================================= +// function : SetModelWorldState +// purpose : Sets new state of OCCT model-world transform +// ======================================================================= +void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) +{ + myModelWorldState.Set (theModelWorldMatrix); + myModelWorldState.Update(); +} + +// ======================================================================= +// function : SetWorldViewState +// purpose : Sets new state of OCCT world-view transform +// ======================================================================= +void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) +{ + myWorldViewState.Set (theWorldViewMatrix); + myWorldViewState.Update(); +} + +// ======================================================================= +// function : RevertProjectionStateTo +// purpose : Reverts state of OCCT projection transform +// ======================================================================= +void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix) +{ + myProjectionState.Set (theProjectionMatrix); + myProjectionState.Revert(); +} + +// ======================================================================= +// function : RevertModelWorldStateTo +// purpose : Reverts state of OCCT model-world transform +// ======================================================================= +void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) +{ + myModelWorldState.Set (theModelWorldMatrix); + myModelWorldState.Revert(); +} + +// ======================================================================= +// function : RevertWorldViewStateTo +// purpose : Reverts state of OCCT world-view transform +// ======================================================================= +void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) +{ + myWorldViewState.Set (theWorldViewMatrix); + myWorldViewState.Revert(); +} + +// ======================================================================= +// function : LightSourceState +// purpose : Returns current state of OCCT light sources +// ======================================================================= +const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const +{ + return myLightSourceState; +} + +// ======================================================================= +// function : ProjectionState +// purpose : Returns current state of OCCT projection transform +// ======================================================================= +const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const +{ + return myProjectionState; +} + +// ======================================================================= +// function : ModelWorldState +// purpose : Returns current state of OCCT model-world transform +// ======================================================================= +const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const +{ + return myModelWorldState; +} + +// ======================================================================= +// function : WorldViewState +// purpose : Returns current state of OCCT world-view transform +// ======================================================================= +const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const +{ + return myWorldViewState; +} + +// ======================================================================= +// function : PushLightSourceState +// purpose : Pushes state of OCCT light sources to the program +// ======================================================================= +void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)) + { + return; + } + + theProgram->SetUniform (myContext, theProgram->GetStateLocation ( + OpenGl_OCC_LIGHT_SOURCE_COUNT), myLightSourceState.LightSources()->Size()); + + OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); + for (unsigned int anIndex = 0; anIter.More(); anIter.Next()) + { + if (anIndex >= OpenGLMaxLights) + { + break; + } + + const OpenGl_Light& aLight = anIter.Value(); + if (aLight.type == TLightAmbient) + { + OpenGl_Vec3 anAmbient (aLight.col.rgb[0], + aLight.col.rgb[1], + aLight.col.rgb[2]); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT + anIndex), anAmbient); + + anIter.Next(); + if (!anIter.More()) + { + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type)); + break; + } + } + + OpenGl_Vec3 aDiffuse (aLight.col.rgb[0], + aLight.col.rgb[1], + aLight.col.rgb[2]); + + OpenGl_Vec3 aPosition (aLight.type == TLightDirectional ? -aLight.dir[0] : aLight.pos[0], + aLight.type == TLightDirectional ? -aLight.dir[1] : aLight.pos[1], + aLight.type == TLightDirectional ? -aLight.dir[2] : aLight.pos[2]); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type)); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_HEAD + anIndex), aLight.HeadLight); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE + anIndex), aDiffuse); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR + anIndex), aDiffuse); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_POSITION + anIndex), aPosition); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION + anIndex), aLight.atten[0]); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION + anIndex), aLight.atten[1]); + + if (aLight.type == TLightSpot) + { + OpenGl_Vec3 aDirection (aLight.dir[0], + aLight.dir[1], + aLight.dir[2]); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF + anIndex), aLight.angle); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT + anIndex), aLight.shine); + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION + anIndex), aDirection); + } + + ++anIndex; + } + + theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); +} + +// ======================================================================= +// function : PushProjectionState +// purpose : Pushes state of OCCT projection transform to the program +// ======================================================================= +void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE)) + { + return; + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), + myProjectionState.ProjectionMatrix()); + + GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), + myProjectionState.ProjectionMatrix(), true); + + aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); + } + + theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); +} + +// ======================================================================= +// function : PushModelWorldState +// purpose : Pushes state of OCCT model-world transform to the program +// ======================================================================= +void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE)) + { + return; + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), + myModelWorldState.ModelWorldMatrix()); + + GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), + myModelWorldState.ModelWorldMatrix(), true); + + aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); + } + + theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); +} + +// ======================================================================= +// function : PushWorldViewState +// purpose : Pushes state of OCCT world-view transform to the program +// ======================================================================= +void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) + { + return; + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), + myWorldViewState.WorldViewMatrix()); + + GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), + myWorldViewState.WorldViewMatrix(), true); + + aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); + } + + theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); +} + +// ======================================================================= +// function : UpdateClippingState +// purpose : Updates state of OCCT clipping planes +// ======================================================================= +void OpenGl_ShaderManager::UpdateClippingState() +{ + myClippingState.Update(); +} + +// ======================================================================= +// function : RevertClippingState +// purpose : Reverts state of OCCT clipping planes +// ======================================================================= +void OpenGl_ShaderManager::RevertClippingState() +{ + myClippingState.Revert(); +} + +// ======================================================================= +// function : PushClippingState +// purpose : Pushes state of OCCT clipping planes to the program +// ======================================================================= +void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE)) + { + return; + } + + Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); + for (GLuint anIndex = 0; anIter.More(); anIter.Next()) + { + const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); + if (!myContext->Clipping().IsEnabled (aPlane)) + { + continue; + } + + GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_EQUATION + anIndex); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); + theProgram->SetUniform (myContext, aLocation, OpenGl_Vec4 ((float) anEquation.x(), + (float) anEquation.y(), + (float) anEquation.z(), + (float) anEquation.w())); + } + + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_SPACE + anIndex), + myContext->Clipping().GetEquationSpace (aPlane)); + ++anIndex; + } + + theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); +} + +// ======================================================================= +// function : UpdateMaterialStateTo +// purpose : Updates state of OCCT material for specified program +// ======================================================================= +void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_Element* theAspect) +{ + if (myMaterialStates.IsBound (theProgram)) + { + myMaterialStates.ChangeFind (theProgram).Set (theAspect); + } + else + { + myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect)); + } + + myMaterialStates.ChangeFind (theProgram).Update(); +} + +// ======================================================================= +// function : ResetMaterialStates +// purpose : Resets state of OCCT material for all programs +// ======================================================================= +void OpenGl_ShaderManager::ResetMaterialStates() +{ + for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) + { + anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0); + } +} + +// ======================================================================= +// function : MaterialState +// purpose : Returns state of OCCT material for specified program +// ======================================================================= +const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (!myMaterialStates.IsBound (theProgram)) + return NULL; + + return &myMaterialStates.Find (theProgram); +} + +namespace +{ + +static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f); + +// ======================================================================= +// function : PushAspectFace +// purpose : +// ======================================================================= +static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_AspectFace* theAspect) +{ + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), + theAspect->DoTextureMap()); + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), + 0 /* GL_TEXTURE0 */); + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), + theAspect->DistinguishingMode()); + + for (int anIndex = 0; anIndex < 2; ++anIndex) + { + const OPENGL_SURF_PROP& aProperties = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack(); + GLint aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT + anIndex); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + OpenGl_Vec4 anAmbient (aProperties.ambcol.rgb[0] * aProperties.amb, + aProperties.ambcol.rgb[1] * aProperties.amb, + aProperties.ambcol.rgb[2] * aProperties.amb, + aProperties.ambcol.rgb[3] * aProperties.amb); + theProgram->SetUniform (theCtx, aLocation, anAmbient); + } + + aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE + anIndex); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + OpenGl_Vec4 aDiffuse (aProperties.difcol.rgb[0] * aProperties.diff, + aProperties.difcol.rgb[1] * aProperties.diff, + aProperties.difcol.rgb[2] * aProperties.diff, + aProperties.difcol.rgb[3] * aProperties.diff); + theProgram->SetUniform (theCtx, aLocation, aDiffuse); + } + + aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR + anIndex); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + OpenGl_Vec4 aSpecular (aProperties.speccol.rgb[0] * aProperties.spec, + aProperties.speccol.rgb[1] * aProperties.spec, + aProperties.speccol.rgb[2] * aProperties.spec, + aProperties.speccol.rgb[3] * aProperties.spec); + theProgram->SetUniform (theCtx, aLocation, aSpecular); + } + + aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION + anIndex); + if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) + { + OpenGl_Vec4 anEmission (aProperties.emscol.rgb[0] * aProperties.emsv, + aProperties.emscol.rgb[1] * aProperties.emsv, + aProperties.emscol.rgb[2] * aProperties.emsv, + aProperties.emscol.rgb[3] * aProperties.emsv); + theProgram->SetUniform (theCtx, aLocation, anEmission); + } + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SHININESS + anIndex), + aProperties.shine); + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY + anIndex), + aProperties.trans); + } +} + +// ======================================================================= +// function : PushAspectLine +// purpose : +// ======================================================================= +static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_AspectLine* theAspect) +{ + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); + + const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], + theAspect->Color().rgb[1], + theAspect->Color().rgb[2], + theAspect->Color().rgb[3]); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), + aDiffuse); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), + 0.0f); +} + +// ======================================================================= +// function : PushAspectText +// purpose : +// ======================================================================= +static void PushAspectText (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_AspectText* theAspect) +{ + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); + + OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], + theAspect->Color().rgb[1], + theAspect->Color().rgb[2], + theAspect->Color().rgb[3]); + if (theAspect->DisplayType() == Aspect_TODT_DEKALE + || theAspect->DisplayType() == Aspect_TODT_SUBTITLE) + { + aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0], + theAspect->SubtitleColor().rgb[1], + theAspect->SubtitleColor().rgb[2], + theAspect->SubtitleColor().rgb[3]); + } + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), + aDiffuse); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), + 0.0f); +} + +// ======================================================================= +// function : PushAspectMarker +// purpose : +// ======================================================================= +static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_AspectMarker* theAspect) +{ + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); + + const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], + theAspect->Color().rgb[1], + theAspect->Color().rgb[2], + theAspect->Color().rgb[3]); + + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), + aDiffuse); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), + THE_COLOR_BLACK_VEC4); + theProgram->SetUniform (theCtx, + theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), + 0.0f); +} + +}; // nameless namespace + +// ======================================================================= +// function : PushMaterialState +// purpose : Pushes current state of OCCT material to the program +// ======================================================================= +void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + if (!myMaterialStates.IsBound (theProgram)) + { + return; + } + + const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram); + if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE)) + { + return; + } + + if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace)) + { + PushAspectFace (myContext, theProgram, dynamic_cast (aState.Aspect())); + } + else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine)) + { + PushAspectLine (myContext, theProgram, dynamic_cast (aState.Aspect())); + } + else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText)) + { + PushAspectText (myContext, theProgram, dynamic_cast (aState.Aspect())); + } + else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker)) + { + PushAspectMarker (myContext, theProgram, dynamic_cast (aState.Aspect())); + } + + theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index()); +} + +// ======================================================================= +// function : PushWorldViewState +// purpose : Pushes state of OCCT graphics parameters to the program +// ======================================================================= +void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const +{ + PushClippingState (theProgram); + PushMaterialState (theProgram); + PushWorldViewState (theProgram); + PushModelWorldState (theProgram); + PushProjectionState (theProgram); + PushLightSourceState (theProgram); +} \ No newline at end of file diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx new file mode 100644 index 0000000000..b3ddf2239a --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -0,0 +1,169 @@ +// Created on: 2013-09-26 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _OpenGl_ShaderManager_HeaderFile +#define _OpenGl_ShaderManager_HeaderFile + +#include + +#include +#include + +#include +#include +#include + +//! List of shader programs. +typedef NCollection_Sequence OpenGl_ShaderProgramList; + +//! Map to declare per-program states of OCCT materials. +typedef NCollection_DataMap OpenGl_MaterialStates; + +//! This class is responsible for managing shader programs. +class OpenGl_ShaderManager : public Standard_Transient +{ + friend class OpenGl_ShaderProgram; + +public: + + //! Creates new empty shader manager. + Standard_EXPORT OpenGl_ShaderManager (OpenGl_Context* theContext); + + //! Releases resources of shader manager. + Standard_EXPORT virtual ~OpenGl_ShaderManager(); + + //! Creates new shader program. + Standard_EXPORT Handle(OpenGl_ShaderProgram) Create (const Handle(Graphic3d_ShaderProgram)& theProxyProgram = NULL); + + //! Unregisters specified shader program. + Standard_EXPORT void Unregister (Handle(OpenGl_ShaderProgram)& theProgram); + + //! Returns list of registered shader programs. + Standard_EXPORT const OpenGl_ShaderProgramList& ShaderPrograms() const; + + //! Returns true if no program objects are registered in the manager. + Standard_EXPORT Standard_Boolean IsEmpty() const; + + DEFINE_STANDARD_RTTI (OpenGl_ShaderManager) + +protected: + + OpenGl_MaterialStates myMaterialStates; //!< Per-program state of OCCT material + OpenGl_ProjectionState myProjectionState; //!< State of OCCT projection transformation + OpenGl_ModelWorldState myModelWorldState; //!< State of OCCT model-world transformation + OpenGl_WorldViewState myWorldViewState; //!< State of OCCT world-view transformation + OpenGl_LightSourceState myClippingState; //!< State of OCCT clipping planes + OpenGl_LightSourceState myLightSourceState; //!< State of OCCT light sources + +public: + + //! Returns current state of OCCT light sources. + Standard_EXPORT const OpenGl_LightSourceState& LightSourceState() const; + + //! Updates state of OCCT light sources. + Standard_EXPORT void UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights); + + //! Pushes current state of OCCT light sources to specified program. + Standard_EXPORT void PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Returns current state of OCCT projection transform. + Standard_EXPORT const OpenGl_ProjectionState& ProjectionState() const; + + //! Updates state of OCCT projection transform. + Standard_EXPORT void UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix); + + //! Reverts state of OCCT projection transform. + Standard_EXPORT void RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix); + + //! Pushes current state of OCCT projection transform to specified program. + Standard_EXPORT void PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Returns current state of OCCT model-world transform. + Standard_EXPORT const OpenGl_ModelWorldState& ModelWorldState() const; + + //! Updates state of OCCT model-world transform. + Standard_EXPORT void UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix); + + //! Reverts state of OCCT model-world transform. + Standard_EXPORT void RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix); + + //! Pushes current state of OCCT model-world transform to specified program. + Standard_EXPORT void PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Returns current state of OCCT world-view transform. + Standard_EXPORT const OpenGl_WorldViewState& WorldViewState() const; + + //! Updates state of OCCT world-view transform. + Standard_EXPORT void UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix); + + //! Reverts state of OCCT world-view transform. + Standard_EXPORT void RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix); + + //! Pushes current state of OCCT world-view transform to specified program. + Standard_EXPORT void PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Updates state of OCCT clipping planes. + Standard_EXPORT void UpdateClippingState(); + + //! Reverts state of OCCT clipping planes. + Standard_EXPORT void RevertClippingState(); + + //! Pushes current state of OCCT clipping planes to specified program. + Standard_EXPORT void PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Resets state of OCCT material for all programs. + Standard_EXPORT void ResetMaterialStates(); + + //! Updates state of OCCT material for specified program. + Standard_EXPORT void UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, + const OpenGl_Element* theAspect); + + //! Pushes current state of OCCT material to specified program. + Standard_EXPORT void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + + //! Returns current state of OCCT material for specified program. + Standard_EXPORT const OpenGl_MaterialState* MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +public: + + //! Pushes current state of OCCT graphics parameters to specified program. + Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const; + +protected: + + OpenGl_ShaderProgramList myProgramList; //!< The list of shader programs + OpenGl_Context* myContext; //!< The OpenGL context + +private: + + Standard_Boolean myIsPP; //!< Is any program object bound (programmable pipeline)? + +}; + +#endif // _OpenGl_ShaderManager_HeaderFile diff --git a/src/OpenGl/OpenGl_ShaderObject.cxx b/src/OpenGl/OpenGl_ShaderObject.cxx new file mode 100644 index 0000000000..9537ccd070 --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderObject.cxx @@ -0,0 +1,147 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderObject, OpenGl_Resource) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderObject, OpenGl_Resource) + +// ======================================================================= +// function : OpenGl_ShaderObject +// purpose : Creates uninitialized shader object +// ======================================================================= +OpenGl_ShaderObject::OpenGl_ShaderObject (GLenum theType) +: myType (theType), + myShaderID (NO_SHADER) +{ + // +} + +// ======================================================================= +// function : ~OpenGl_ShaderObject +// purpose : Releases resources of shader object +// ======================================================================= +OpenGl_ShaderObject::~OpenGl_ShaderObject() +{ + Release (NULL); +} + +// ======================================================================= +// function : LoadSource +// purpose : Loads shader source code +// ======================================================================= +Standard_Boolean OpenGl_ShaderObject::LoadSource (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theSource) +{ + if (myShaderID == NO_SHADER) + { + return Standard_False; + } + + const GLchar* aLines = theSource.ToCString(); + theCtx->core20->glShaderSource (myShaderID, 1, &aLines, NULL); + return Standard_True; +} + +// ======================================================================= +// function : Compile +// purpose : Compiles the shader object +// ======================================================================= +Standard_Boolean OpenGl_ShaderObject::Compile (const Handle(OpenGl_Context)& theCtx) +{ + if (myShaderID == NO_SHADER) + { + return Standard_False; + } + + // Try to compile shader + theCtx->core20->glCompileShader (myShaderID); + + // Check compile status + GLint aStatus = GL_FALSE; + theCtx->core20->glGetShaderiv (myShaderID, GL_COMPILE_STATUS, &aStatus); + return aStatus != GL_FALSE; +} + +// ======================================================================= +// function : FetchInfoLog +// purpose : Fetches information log of the last compile operation +// ======================================================================= +Standard_Boolean OpenGl_ShaderObject::FetchInfoLog (const Handle(OpenGl_Context)& theCtx, + TCollection_AsciiString& theLog) +{ + if (myShaderID == NO_SHADER) + { + return Standard_False; + } + + // Load information log of the compiler + GLint aLength = 0; + theCtx->core20->glGetShaderiv (myShaderID, GL_INFO_LOG_LENGTH, &aLength); + if (aLength > 0) + { + GLchar* aLog = (GLchar*) alloca (aLength); + memset (aLog, 0, aLength); + theCtx->core20->glGetShaderInfoLog (myShaderID, aLength, NULL, aLog); + theLog = aLog; + } + + return Standard_True; +} + +// ======================================================================= +// function : Create +// purpose : Creates new empty shader object of specified type +// ======================================================================= +Standard_Boolean OpenGl_ShaderObject::Create (const Handle(OpenGl_Context)& theCtx) +{ + if (myShaderID == NO_SHADER + && theCtx->core20 != NULL) + { + myShaderID = theCtx->core20->glCreateShader (myType); + } + + return myShaderID != NO_SHADER; +} + +// ======================================================================= +// function : Release +// purpose : Destroys shader object +// ======================================================================= +void OpenGl_ShaderObject::Release (const OpenGl_Context* theCtx) +{ + if (myShaderID == NO_SHADER) + { + return; + } + + Standard_ASSERT_RETURN (theCtx != NULL, + "OpenGl_ShaderObject destroyed without GL context! Possible GPU memory leakage...",); + + if (theCtx->core20 != NULL) + { + theCtx->core20->glDeleteShader (myShaderID); + } + myShaderID = NO_SHADER; +} diff --git a/src/OpenGl/OpenGl_ShaderObject.hxx b/src/OpenGl/OpenGl_ShaderObject.hxx new file mode 100644 index 0000000000..8f72b4bdde --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderObject.hxx @@ -0,0 +1,81 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _OpenGl_ShaderObject_Header +#define _OpenGl_ShaderObject_Header + +#include +#include +#include +#include + +//! Wrapper for OpenGL shader object. +class OpenGl_ShaderObject : public OpenGl_Resource +{ + +public: + + //! Non-valid shader name. + static const GLuint NO_SHADER = 0; + +public: + + //! Creates uninitialized shader object. + Standard_EXPORT OpenGl_ShaderObject (GLenum theType); + + //! Releases resources of shader object. + Standard_EXPORT virtual ~OpenGl_ShaderObject(); + + //! Loads shader source code. + Standard_EXPORT Standard_Boolean LoadSource (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theSource); + + //! Compiles the shader object. + Standard_EXPORT Standard_Boolean Compile (const Handle(OpenGl_Context)& theCtx); + + //! Initializes (loads and compiles) shader object with the specified description. + Standard_EXPORT Standard_Boolean Initialize (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_ShaderObject)& theShader); + + //! Fetches information log of the last compile operation. + Standard_EXPORT Standard_Boolean FetchInfoLog (const Handle(OpenGl_Context)& theCtx, + TCollection_AsciiString& theLog); + + //! Creates new empty shader object of specified type. + Standard_EXPORT Standard_Boolean Create (const Handle(OpenGl_Context)& theCtx); + + //! Destroys shader object. + Standard_EXPORT virtual void Release (const OpenGl_Context* theCtx); + + //! Returns type of shader object. + GLenum Type() const { return myType; } + +protected: + + GLenum myType; //!< Type of OpenGL shader object + GLuint myShaderID; //!< Handle of OpenGL shader object + +public: + + DEFINE_STANDARD_RTTI (OpenGl_ShaderObject) + friend class OpenGl_ShaderProgram; + +}; + +#endif // _OpenGl_ShaderObject_Header diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx new file mode 100644 index 0000000000..8aee2a7fc2 --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -0,0 +1,1129 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include +#include + +#include +#include +#include + +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource) + +OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector(); + +// Declare OCCT-specific OpenGL/GLSL shader variables +Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] = +{ + /* OpenGl_OCC_MODEL_WORLD_MATRIX */ "occModelWorldMatrix", + /* OpenGl_OCC_WORLD_VIEW_MATRIX */ "occWorldViewMatrix", + /* OpenGl_OCC_PROJECTION_MATRIX */ "occProjectionMatrix", + /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE */ "occModelWorldMatrixInverse", + /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE */ "occWorldViewMatrixInverse", + /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE */ "occProjectionMatrixInverse", + /* OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE */ "occModelWorldMatrixTranspose", + /* OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE */ "occWorldViewMatrixTranspose", + /* OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE */ "occProjectionMatrixTranspose", + /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE */ "occModelWorldMatrixInverseTranspose", + /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE */ "occWorldViewMatrixInverseTranspose", + /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE */ "occProjectionMatrixInverseTranspose", + + /* OpenGl_OCC_CLIP_PLANE_0_EQUATION */ "occClipPlanes[0].Equation", + /* OpenGl_OCC_CLIP_PLANE_1_EQUATION */ "occClipPlanes[1].Equation", + /* OpenGl_OCC_CLIP_PLANE_2_EQUATION */ "occClipPlanes[2].Equation", + /* OpenGl_OCC_CLIP_PLANE_3_EQUATION */ "occClipPlanes[3].Equation", + /* OpenGl_OCC_CLIP_PLANE_4_EQUATION */ "occClipPlanes[4].Equation", + /* OpenGl_OCC_CLIP_PLANE_5_EQUATION */ "occClipPlanes[5].Equation", + /* OpenGl_OCC_CLIP_PLANE_6_EQUATION */ "occClipPlanes[6].Equation", + /* OpenGl_OCC_CLIP_PLANE_7_EQUATION */ "occClipPlanes[7].Equation", + + /* OpenGl_OCC_CLIP_PLANE_0_SPACE */ "occClipPlanes[0].Space", + /* OpenGl_OCC_CLIP_PLANE_1_SPACE */ "occClipPlanes[1].Space", + /* OpenGl_OCC_CLIP_PLANE_2_SPACE */ "occClipPlanes[2].Space", + /* OpenGl_OCC_CLIP_PLANE_3_SPACE */ "occClipPlanes[3].Space", + /* OpenGl_OCC_CLIP_PLANE_4_SPACE */ "occClipPlanes[4].Space", + /* OpenGl_OCC_CLIP_PLANE_5_SPACE */ "occClipPlanes[5].Space", + /* OpenGl_OCC_CLIP_PLANE_6_SPACE */ "occClipPlanes[6].Space", + /* OpenGl_OCC_CLIP_PLANE_7_SPACE */ "occClipPlanes[7].Space", + + /* OpenGl_OCC_LIGHT_SOURCE_COUNT */ "occLightSourcesCount", + + /* OpenGl_OCC_LIGHT_SOURCE_0_TYPE */ "occLightSources[0].Type", + /* OpenGl_OCC_LIGHT_SOURCE_1_TYPE */ "occLightSources[1].Type", + /* OpenGl_OCC_LIGHT_SOURCE_2_TYPE */ "occLightSources[2].Type", + /* OpenGl_OCC_LIGHT_SOURCE_3_TYPE */ "occLightSources[3].Type", + /* OpenGl_OCC_LIGHT_SOURCE_4_TYPE */ "occLightSources[4].Type", + /* OpenGl_OCC_LIGHT_SOURCE_5_TYPE */ "occLightSources[5].Type", + /* OpenGl_OCC_LIGHT_SOURCE_6_TYPE */ "occLightSources[6].Type", + /* OpenGl_OCC_LIGHT_SOURCE_7_TYPE */ "occLightSources[7].Type", + + /* OpenGl_OCC_LIGHT_SOURCE_0_HEAD */ "occLightSources[0].Head", + /* OpenGl_OCC_LIGHT_SOURCE_1_HEAD */ "occLightSources[1].Head", + /* OpenGl_OCC_LIGHT_SOURCE_2_HEAD */ "occLightSources[2].Head", + /* OpenGl_OCC_LIGHT_SOURCE_3_HEAD */ "occLightSources[3].Head", + /* OpenGl_OCC_LIGHT_SOURCE_4_HEAD */ "occLightSources[4].Head", + /* OpenGl_OCC_LIGHT_SOURCE_5_HEAD */ "occLightSources[5].Head", + /* OpenGl_OCC_LIGHT_SOURCE_6_HEAD */ "occLightSources[6].Head", + /* OpenGl_OCC_LIGHT_SOURCE_7_HEAD */ "occLightSources[7].Head", + + /* OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT */ "occLightSources[0].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_1_AMBIENT */ "occLightSources[1].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_2_AMBIENT */ "occLightSources[2].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_3_AMBIENT */ "occLightSources[3].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_4_AMBIENT */ "occLightSources[4].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_5_AMBIENT */ "occLightSources[5].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_6_AMBIENT */ "occLightSources[6].Ambient", + /* OpenGl_OCC_LIGHT_SOURCE_7_AMBIENT */ "occLightSources[7].Ambient", + + /* OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE */ "occLightSources[0].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_1_DIFFUSE */ "occLightSources[1].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_2_DIFFUSE */ "occLightSources[2].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_3_DIFFUSE */ "occLightSources[3].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_4_DIFFUSE */ "occLightSources[4].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_5_DIFFUSE */ "occLightSources[5].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_6_DIFFUSE */ "occLightSources[6].Diffuse", + /* OpenGl_OCC_LIGHT_SOURCE_7_DIFFUSE */ "occLightSources[7].Diffuse", + + /* OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR */ "occLightSources[0].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_1_SPECULAR */ "occLightSources[1].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_2_SPECULAR */ "occLightSources[2].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_3_SPECULAR */ "occLightSources[3].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_4_SPECULAR */ "occLightSources[4].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_5_SPECULAR */ "occLightSources[5].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_6_SPECULAR */ "occLightSources[6].Specular", + /* OpenGl_OCC_LIGHT_SOURCE_7_SPECULAR */ "occLightSources[7].Specular", + + /* OpenGl_OCC_LIGHT_SOURCE_0_POSITION */ "occLightSources[0].Position", + /* OpenGl_OCC_LIGHT_SOURCE_1_POSITION */ "occLightSources[1].Position", + /* OpenGl_OCC_LIGHT_SOURCE_2_POSITION */ "occLightSources[2].Position", + /* OpenGl_OCC_LIGHT_SOURCE_3_POSITION */ "occLightSources[3].Position", + /* OpenGl_OCC_LIGHT_SOURCE_4_POSITION */ "occLightSources[4].Position", + /* OpenGl_OCC_LIGHT_SOURCE_5_POSITION */ "occLightSources[5].Position", + /* OpenGl_OCC_LIGHT_SOURCE_6_POSITION */ "occLightSources[6].Position", + /* OpenGl_OCC_LIGHT_SOURCE_7_POSITION */ "occLightSources[7].Position", + + /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF */ "occLightSources[0].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_CUTOFF */ "occLightSources[1].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_CUTOFF */ "occLightSources[2].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_CUTOFF */ "occLightSources[3].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_CUTOFF */ "occLightSources[4].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_CUTOFF */ "occLightSources[5].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_CUTOFF */ "occLightSources[6].SpotCutoff", + /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_CUTOFF */ "occLightSources[7].SpotCutoff", + + /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT */ "occLightSources[0].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_EXPONENT */ "occLightSources[1].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_EXPONENT */ "occLightSources[2].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_EXPONENT */ "occLightSources[3].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_EXPONENT */ "occLightSources[4].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_EXPONENT */ "occLightSources[5].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_EXPONENT */ "occLightSources[6].SpotExponent", + /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_EXPONENT */ "occLightSources[7].SpotExponent", + + /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION */ "occLightSources[0].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_DIRECTION */ "occLightSources[1].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_DIRECTION */ "occLightSources[2].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_DIRECTION */ "occLightSources[3].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_DIRECTION */ "occLightSources[4].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_DIRECTION */ "occLightSources[5].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_DIRECTION */ "occLightSources[6].SpotDirection", + /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_DIRECTION */ "occLightSources[7].SpotDirection", + + /* OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION */ "occLightSources[0].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_1_CONST_ATTENUATION */ "occLightSources[1].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_2_CONST_ATTENUATION */ "occLightSources[2].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_3_CONST_ATTENUATION */ "occLightSources[3].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_4_CONST_ATTENUATION */ "occLightSources[4].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_5_CONST_ATTENUATION */ "occLightSources[5].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_6_CONST_ATTENUATION */ "occLightSources[6].ConstAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_7_CONST_ATTENUATION */ "occLightSources[7].ConstAttenuation", + + /* OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION */ "occLightSources[0].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_1_LINEAR_ATTENUATION */ "occLightSources[1].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_2_LINEAR_ATTENUATION */ "occLightSources[2].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_3_LINEAR_ATTENUATION */ "occLightSources[3].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_4_LINEAR_ATTENUATION */ "occLightSources[4].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_5_LINEAR_ATTENUATION */ "occLightSources[5].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_6_LINEAR_ATTENUATION */ "occLightSources[6].LinearAttenuation", + /* OpenGl_OCC_LIGHT_SOURCE_7_LINEAR_ATTENUATION */ "occLightSources[7].LinearAttenuation", + + /* OpenGl_OCCT_ACTIVE_SAMPLER */ "occActiveSampler", + /* OpenGl_OCCT_TEXTURE_ENABLE */ "occTextureEnable", + /* OpenGl_OCCT_DISTINGUISH_MODE */ "occDistinguishingMode", + /* OpenGl_OCCT_FRONT_MATERIAL_AMBIENT */ "occFrontMaterial.Ambient", + /* OpenGl_OCCT_BACK_MATERIAL_AMBIENT */ "occBackMaterial.Ambient", + /* OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE */ "occFrontMaterial.Diffuse", + /* OpenGl_OCCT_BACK_MATERIAL_DIFFUSE */ "occBackMaterial.Diffuse", + /* OpenGl_OCCT_FRONT_MATERIAL_SPECULAR */ "occFrontMaterial.Specular", + /* OpenGl_OCCT_BACK_MATERIAL_SPECULAR */ "occBackMaterial.Specular", + /* OpenGl_OCCT_FRONT_MATERIAL_EMISSION */ "occFrontMaterial.Emission", + /* OpenGl_OCCT_BACK_MATERIAL_EMISSION */ "occBackMaterial.Emission", + /* OpenGl_OCCT_FRONT_MATERIAL_SHININESS */ "occFrontMaterial.Shininess", + /* OpenGl_OCCT_BACK_MATERIAL_SHININESS */ "occBackMaterial.Shininess", + /* OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY */ "occFrontMaterial.Transparency", + /* OpenGl_OCCT_BACK_MATERIAL_TRANSPARENCY */ "occBackMaterial.Transparency" + +}; + +// ======================================================================= +// function : OpenGl_VariableSetterSelector +// purpose : Creates new variable setter selector +// ======================================================================= +OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector() +{ + // Note: Add new variable setters here + mySetterList = OpenGl_HashMapInitializer::CreateListOf + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()) + (Graphic3d_UniformValueTypeID::ID, new OpenGl_VariableSetter()); +} + +// ======================================================================= +// function : ~OpenGl_VariableSetterSelector +// purpose : Releases memory resources of variable setter selector +// ======================================================================= +OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector() +{ + for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next()) + { + delete anIt.Value(); + } + + mySetterList.Clear(); +} + +// ======================================================================= +// function : Set +// purpose : Sets generic variable to specified shader program +// ======================================================================= +void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_ShaderVariable)& theVariable, + OpenGl_ShaderProgram* theProgram) const +{ + Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()), + "The type of user-defined uniform variable is not supported...", ); + + mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram); +} + +// ======================================================================= +// function : OpenGl_ShaderProgram +// purpose : Creates uninitialized shader program +// ======================================================================= +OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy) +: myProgramID (NO_PROGRAM), + myProxy (theProxy) +{ + memset (myCurrentState, 0, sizeof (myCurrentState)); + for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar) + { + myStateLocations[aVar] = INVALID_LOCATION; + } +} + +// ======================================================================= +// function : Initialize +// purpose : Initializes program object with the list of shader objects +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx, + const Graphic3d_ShaderObjectList& theShaders) +{ + if (theCtx.IsNull() || !Create (theCtx)) + { + return Standard_False; + } + + GLchar *aShaderDir = getenv ("CSF_ShadersDirectory"); + if (aShaderDir == NULL) + { + TCollection_ExtendedString aMsg = "Error! Failed to get OCCT shaders directory"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + return Standard_False; + } + + OSD_File aDeclFile (TCollection_AsciiString (aShaderDir) + "/Declarations.glsl"); + if (!aDeclFile.Exists()) + { + TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + return Standard_False; + } + + TCollection_AsciiString aDeclarations; + + aDeclFile.Open (OSD_ReadOnly, OSD_Protection()); + aDeclFile.Read (aDeclarations, aDeclFile.Size()); + aDeclFile.Close(); + + for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); + anIter.More(); anIter.Next()) + { + if (!anIter.Value()->IsDone()) + { + TCollection_ExtendedString aMsg = "Error! Failed to get shader source"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + return Standard_False; + } + + Handle(OpenGl_ShaderObject) aShader; + + // Note: Add support of other shader types here + switch (anIter.Value()->Type()) + { + case Graphic3d_TOS_VERTEX: + aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER); + break; + case Graphic3d_TOS_FRAGMENT: + aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER); + break; + } + + // Is unsupported shader type? + if (aShader.IsNull()) + { + TCollection_ExtendedString aMsg = "Error! Unsupported shader type"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + return Standard_False; + } + + if (!aShader->Create (theCtx)) + { + return Standard_False; + } + + TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source(); + + if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX) + { + aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource; + } + + if (!aShader->LoadSource (theCtx, aSource)) + { + TCollection_ExtendedString aMsg = "Error! Failed to set shader source"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + return Standard_False; + } + + if (!aShader->Compile (theCtx)) + { + TCollection_ExtendedString aMsg = "Error! Failed to compile shader object"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + if (theCtx->caps->contextDebug) + { + TCollection_AsciiString aLog; + aShader->FetchInfoLog (theCtx, aLog); + if (!aLog.IsEmpty()) + { + std::cout << aLog.ToCString() << std::endl << std::flush; + } + else + { + std::cout << "Information log is empty" << std::endl; + } + } + + return Standard_False; + } + + if (!AttachShader (theCtx, aShader)) + { + return Standard_False; + } + } + + if (!Link (theCtx)) + { + TCollection_ExtendedString aMsg = "Error! Failed to link program object"; + + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, + 0, + GL_DEBUG_SEVERITY_HIGH_ARB, + aMsg); + + if (theCtx->caps->contextDebug) + { + TCollection_AsciiString aLog; + FetchInfoLog (theCtx, aLog); + if (!aLog.IsEmpty()) + { + std::cout << aLog.ToCString() << std::endl; + } + else + { + std::cout << "Information log is empty" << std::endl; + } + } + + return Standard_False; + } + + return Standard_True; +} + +// ======================================================================= +// function : ~OpenGl_ShaderProgram +// purpose : Releases resources of shader program +// ======================================================================= +OpenGl_ShaderProgram::~OpenGl_ShaderProgram() +{ + Release (NULL); +} + +// ======================================================================= +// function : AttachShader +// purpose : Attaches shader object to the program object +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderObject)& theShader) +{ + if (myProgramID == NO_PROGRAM || theShader.IsNull()) + { + return Standard_False; + } + + for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next()) + { + if (theShader == anIter.Value()) + { + return Standard_False; + } + } + + myShaderObjects.Append (theShader); + theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID); + return Standard_True; +} + +// ======================================================================= +// function : DetachShader +// purpose : Detaches shader object to the program object +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderObject)& theShader) +{ + if (myProgramID == NO_PROGRAM + || theShader.IsNull()) + { + return Standard_False; + } + + OpenGl_ShaderList::Iterator anIter (myShaderObjects); + while (anIter.More()) + { + if (theShader == anIter.Value()) + { + myShaderObjects.Remove (anIter); + break; + } + + anIter.Next(); + } + + if (!anIter.More()) + { + return Standard_False; + } + + theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID); + return Standard_True; +} + +// ======================================================================= +// function : Link +// purpose : Links the program object +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx) +{ + if (myProgramID == NO_PROGRAM) + { + return Standard_False; + } + + theCtx->core20->glLinkProgram (myProgramID); + + GLint aStatus = GL_FALSE; + theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus); + + for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar) + { + myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]); + } + + return aStatus != GL_FALSE; +} + +// ======================================================================= +// function : FetchInfoLog +// purpose : Fetches information log of the last link operation +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx, + TCollection_AsciiString& theOutput) +{ + if (myProgramID == NO_PROGRAM) + { + return Standard_False; + } + + GLint aLength = 0; + theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength); + if (aLength > 0) + { + GLchar* aLog = (GLchar*) alloca (aLength); + memset (aLog, 0, aLength); + theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog); + theOutput = aLog; + } + return Standard_True; +} + +// ======================================================================= +// function : Bind +// purpose : Sets the program object as part of current rendering state +// ======================================================================= +void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const +{ + if (myProgramID == NO_PROGRAM) + { + return; + } + + theCtx->core20->glUseProgram (myProgramID); + theCtx->ShaderManager()->myIsPP = Standard_True; +} + +// ======================================================================= +// function : ApplyVariables +// purpose : Fetches uniform variables from proxy shader program +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx) +{ + if (myProxy.IsNull() || myProxy->Variables().IsEmpty()) + { + return Standard_False; + } + + for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next()) + { + mySetterSelector.Set (theCtx, anIter.Value(), this); + } + + myProxy->ClearVariables(); + return Standard_True; +} + +// ======================================================================= +// function : BindWithVariables +// purpose : Binds the program object and applies variables +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx) +{ + Bind (theCtx); + return ApplyVariables (theCtx); +} + +// ======================================================================= +// function : Unbind +// purpose : Reverts to fixed-function graphics pipeline (FFP) +// ======================================================================= +void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx) +{ + if (theCtx->ShaderManager()->myIsPP) + { + theCtx->core20->glUseProgram (NO_PROGRAM); + theCtx->ShaderManager()->myIsPP = Standard_False; + } +} + +// ======================================================================= +// function : ActiveState +// purpose : Returns index of last modification for specified state type +// ======================================================================= +Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const +{ + if (theType < MaxStateTypes) + { + return myCurrentState[theType]; + } + return 0; +} + +// ======================================================================= +// function : UpdateState +// purpose : Updates index of last modification for specified state type +// ======================================================================= +void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType, + const Standard_Size theIndex) +{ + if (theType < MaxStateTypes) + { + myCurrentState[theType] = theIndex; + } +} + +// ======================================================================= +// function : GetUniformLocation +// purpose : Returns location (index) of the specific uniform variable +// ======================================================================= +GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName) const +{ + return myProgramID != NO_PROGRAM + ? theCtx->core20->glGetUniformLocation (myProgramID, theName) + : INVALID_LOCATION; +} + +// ======================================================================= +// function : GetAttributeLocation +// purpose : Returns location (index) of the generic vertex attribute +// ======================================================================= +GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName) const +{ + return myProgramID != NO_PROGRAM + ? theCtx->core20->glGetAttribLocation (myProgramID, theName) + : INVALID_LOCATION; +} + +// ======================================================================= +// function : GetStateLocation +// purpose : Returns location of the OCCT state uniform variable +// ======================================================================= +GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const +{ + if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES) + { + return myStateLocations[theVariable]; + } + return INVALID_LOCATION; +} + +// ======================================================================= +// function : GetUniform +// purpose : Returns the value of the integer uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4i& theValue) const +{ + return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : GetUniform +// purpose : Returns the value of the integer uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + OpenGl_Vec4i& theValue) const +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue); + return Standard_True; +} + +// ======================================================================= +// function : GetUniform +// purpose : Returns the value of the floating-point uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4& theValue) const +{ + return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : GetUniform +// purpose : Returns the value of the floating-point uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + OpenGl_Vec4& theValue) const +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue); + return Standard_True; +} + +// ======================================================================= +// function : GetAttribute +// purpose : Returns the integer vertex attribute +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4i& theValue) const +{ + return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : GetAttribute +// purpose : Returns the integer vertex attribute +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx, + GLint theIndex, + OpenGl_Vec4i& theValue) const +{ + if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue); + return Standard_True; +} + +// ======================================================================= +// function : GetAttribute +// purpose : Returns the floating-point vertex attribute +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4& theValue) const +{ + return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : GetAttribute +// purpose : Returns the floating-point vertex attribute +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx, + GLint theIndex, + OpenGl_Vec4& theValue) const +{ + if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLint theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLint theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform1i (theLocation, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLfloat theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLfloat theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform1f (theLocation, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 2D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec2i& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 2D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec2i& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform2iv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 3D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec3i& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 3D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec3i& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform3iv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 4D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec4i& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform 4D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec4i& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform4iv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 2D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec2& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 2D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec2& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform2fv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 3D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec3& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 3D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec3& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform3fv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec4& theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4D vector +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec4& theValue) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform4fv (theLocation, 1, theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Matrix& theValue, + GLboolean theTranspose) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Matrix& theValue, + GLboolean theTranspose) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const Tmatrix3& theValue, + GLboolean theTranspose) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const Tmatrix3& theValue, + GLboolean theTranspose) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue); + return Standard_True; +} + +// ======================================================================= +// function : SetSampler +// purpose : Specifies the value of the sampler uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const GLenum theTextureUnit) +{ + return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit); +} + +// ======================================================================= +// function : SetSampler +// purpose : Specifies the value of the sampler uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const GLenum theTextureUnit) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform1i (theLocation, theTextureUnit); + return Standard_True; +} + +// ======================================================================= +// function : Create +// purpose : Creates new empty shader program of specified type +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx) +{ + if (myProgramID == NO_PROGRAM + && theCtx->core20 != NULL) + { + myProgramID = theCtx->core20->glCreateProgram(); + } + + return myProgramID != NO_PROGRAM; +} + +// ======================================================================= +// function : Release +// purpose : Destroys shader program +// ======================================================================= +void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx) +{ + if (myProgramID == NO_PROGRAM) + { + return; + } + + Standard_ASSERT_RETURN (theCtx != NULL, + "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",); + + for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next()) + { + anIter.ChangeValue()->Release (theCtx); + anIter.ChangeValue().Nullify(); + } + + if (theCtx->core20 != NULL) + { + theCtx->core20->glDeleteProgram (myProgramID); + } + + myProgramID = NO_PROGRAM; +} diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx new file mode 100644 index 0000000000..a38f845dfd --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -0,0 +1,557 @@ +// Created on: 2013-09-19 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _OpenGl_ShaderProgram_Header +#define _OpenGl_ShaderProgram_Header + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +//! The enumeration of OCCT-specific OpenGL/GLSL variables. +enum OpenGl_StateVariable +{ + // OpenGL matrix state + OpenGl_OCC_MODEL_WORLD_MATRIX, + OpenGl_OCC_WORLD_VIEW_MATRIX, + OpenGl_OCC_PROJECTION_MATRIX, + OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE, + OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE, + OpenGl_OCC_PROJECTION_MATRIX_INVERSE, + OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE, + OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE, + OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE, + OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE, + OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE, + OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE, + + // OpenGL clip planes state + OpenGl_OCC_CLIP_PLANE_0_EQUATION, + OpenGl_OCC_CLIP_PLANE_1_EQUATION, + OpenGl_OCC_CLIP_PLANE_2_EQUATION, + OpenGl_OCC_CLIP_PLANE_3_EQUATION, + OpenGl_OCC_CLIP_PLANE_4_EQUATION, + OpenGl_OCC_CLIP_PLANE_5_EQUATION, + OpenGl_OCC_CLIP_PLANE_6_EQUATION, + OpenGl_OCC_CLIP_PLANE_7_EQUATION, + OpenGl_OCC_CLIP_PLANE_0_SPACE, + OpenGl_OCC_CLIP_PLANE_1_SPACE, + OpenGl_OCC_CLIP_PLANE_2_SPACE, + OpenGl_OCC_CLIP_PLANE_3_SPACE, + OpenGl_OCC_CLIP_PLANE_4_SPACE, + OpenGl_OCC_CLIP_PLANE_5_SPACE, + OpenGl_OCC_CLIP_PLANE_6_SPACE, + OpenGl_OCC_CLIP_PLANE_7_SPACE, + + OpenGl_OCC_LIGHT_SOURCE_COUNT, + + // OpenGL light state + OpenGl_OCC_LIGHT_SOURCE_0_TYPE, + OpenGl_OCC_LIGHT_SOURCE_1_TYPE, + OpenGl_OCC_LIGHT_SOURCE_2_TYPE, + OpenGl_OCC_LIGHT_SOURCE_3_TYPE, + OpenGl_OCC_LIGHT_SOURCE_4_TYPE, + OpenGl_OCC_LIGHT_SOURCE_5_TYPE, + OpenGl_OCC_LIGHT_SOURCE_6_TYPE, + OpenGl_OCC_LIGHT_SOURCE_7_TYPE, + OpenGl_OCC_LIGHT_SOURCE_0_HEAD, + OpenGl_OCC_LIGHT_SOURCE_1_HEAD, + OpenGl_OCC_LIGHT_SOURCE_2_HEAD, + OpenGl_OCC_LIGHT_SOURCE_3_HEAD, + OpenGl_OCC_LIGHT_SOURCE_4_HEAD, + OpenGl_OCC_LIGHT_SOURCE_5_HEAD, + OpenGl_OCC_LIGHT_SOURCE_6_HEAD, + OpenGl_OCC_LIGHT_SOURCE_7_HEAD, + OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_1_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_2_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_3_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_4_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_5_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_6_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_7_AMBIENT, + OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_1_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_2_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_3_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_4_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_5_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_6_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_7_DIFFUSE, + OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_1_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_2_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_3_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_4_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_5_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_6_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_7_SPECULAR, + OpenGl_OCC_LIGHT_SOURCE_0_POSITION, + OpenGl_OCC_LIGHT_SOURCE_1_POSITION, + OpenGl_OCC_LIGHT_SOURCE_2_POSITION, + OpenGl_OCC_LIGHT_SOURCE_3_POSITION, + OpenGl_OCC_LIGHT_SOURCE_4_POSITION, + OpenGl_OCC_LIGHT_SOURCE_5_POSITION, + OpenGl_OCC_LIGHT_SOURCE_6_POSITION, + OpenGl_OCC_LIGHT_SOURCE_7_POSITION, + OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_1_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_2_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_3_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_4_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_5_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_6_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_7_SPOT_CUTOFF, + OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_1_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_2_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_3_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_4_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_5_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_6_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_7_SPOT_EXPONENT, + OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_1_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_2_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_3_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_4_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_5_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_6_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_7_SPOT_DIRECTION, + OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_1_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_2_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_3_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_4_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_5_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_6_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_7_CONST_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_1_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_2_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_3_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_4_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_5_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_6_LINEAR_ATTENUATION, + OpenGl_OCC_LIGHT_SOURCE_7_LINEAR_ATTENUATION, + + // Material state + OpenGl_OCCT_ACTIVE_SAMPLER, + OpenGl_OCCT_TEXTURE_ENABLE, + OpenGl_OCCT_DISTINGUISH_MODE, + OpenGl_OCCT_FRONT_MATERIAL_AMBIENT, + OpenGl_OCCT_BACK_MATERIAL_AMBIENT, + OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE, + OpenGl_OCCT_BACK_MATERIAL_DIFFUSE, + OpenGl_OCCT_FRONT_MATERIAL_SPECULAR, + OpenGl_OCCT_BACK_MATERIAL_SPECULAR, + OpenGl_OCCT_FRONT_MATERIAL_EMISSION, + OpenGl_OCCT_BACK_MATERIAL_EMISSION, + OpenGl_OCCT_FRONT_MATERIAL_SHININESS, + OpenGl_OCCT_BACK_MATERIAL_SHININESS, + OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY, + OpenGl_OCCT_BACK_MATERIAL_TRANSPARENCY, + + // DON'T MODIFY THIS ITEM (insert new items before it) + OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES +}; + +class OpenGl_ShaderProgram; + +//! Interface for generic setter of user-defined uniform variables. +struct OpenGl_SetterInterface +{ + //! Sets user-defined uniform variable to specified program. + virtual void Set (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_ShaderVariable)& theVariable, + OpenGl_ShaderProgram* theProgram) = 0; + + //! Destructor + virtual ~OpenGl_SetterInterface() {} +}; + +//! List of OpenGL shader objects. +typedef NCollection_Sequence OpenGl_ShaderList; + +//! List of shader variable setters. +typedef NCollection_DataMap OpenGl_SetterList; + +//! Support tool for setting user-defined uniform variables. +class OpenGl_VariableSetterSelector +{ +public: + + //! Creates new setter selector. + OpenGl_VariableSetterSelector(); + + //! Releases memory resources of setter selector. + ~OpenGl_VariableSetterSelector(); + + //! Sets user-defined uniform variable to specified program. + void Set (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_ShaderVariable)& theVariable, + OpenGl_ShaderProgram* theProgram) const; + +private: + + //! List of variable setters. + OpenGl_SetterList mySetterList; +}; + +//! Defines types of uniform state variables. +enum OpenGl_UniformStateType +{ + OpenGl_LIGHT_SOURCES_STATE, + OpenGl_CLIP_PLANES_STATE, + OpenGl_MODEL_WORLD_STATE, + OpenGl_WORLD_VIEW_STATE, + OpenGl_PROJECTION_STATE, + OpenGl_MATERIALS_STATE +}; + +//! Total number of state types. +const int MaxStateTypes = 6; + +//! Wrapper for OpenGL program object. +class OpenGl_ShaderProgram : public OpenGl_Resource +{ + +public: + + //! Non-valid shader name. + static const GLuint NO_PROGRAM = 0; + + //! Invalid location of uniform/attribute variable. + static const GLint INVALID_LOCATION = -1; + + //! List of pre-defined OCCT state uniform variables. + static Standard_CString PredefinedKeywords[OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES]; + +protected: + + //! Creates uninitialized shader program. + Standard_EXPORT OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy = NULL); + + static OpenGl_VariableSetterSelector mySetterSelector; + +public: + + //! Releases resources of shader program. + Standard_EXPORT virtual ~OpenGl_ShaderProgram(); + + //! Creates new empty shader program of specified type. + Standard_EXPORT Standard_Boolean Create (const Handle(OpenGl_Context)& theCtx); + + //! Destroys shader program. + Standard_EXPORT virtual void Release (const OpenGl_Context* theCtx); + + //! Attaches shader object to the program object. + Standard_EXPORT Standard_Boolean AttachShader (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderObject)& theShader); + + //! Detaches shader object to the program object. + Standard_EXPORT Standard_Boolean DetachShader (const Handle(OpenGl_Context)& theCtx, + const Handle(OpenGl_ShaderObject)& theShader); + + //! Initializes program object with the list of shader objects. + Standard_EXPORT Standard_Boolean Initialize (const Handle(OpenGl_Context)& theCtx, + const Graphic3d_ShaderObjectList& theShaders); + + //! Links the program object. + Standard_EXPORT Standard_Boolean Link (const Handle(OpenGl_Context)& theCtx); + + //! Fetches information log of the last link operation. + Standard_EXPORT Standard_Boolean FetchInfoLog (const Handle(OpenGl_Context)& theCtx, + TCollection_AsciiString& theLog); + + //! Fetches uniform variables from proxy shader program. + Standard_EXPORT Standard_Boolean ApplyVariables (const Handle(OpenGl_Context)& theCtx); + + //! Sets the program object as part of current rendering state. + Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx) const; + + //! Binds the program object and applies variables from proxy shader program. + Standard_EXPORT Standard_Boolean BindWithVariables (const Handle(OpenGl_Context)& theCtx); + + //! Reverts to fixed-function graphics pipeline (FFP). + Standard_EXPORT static void Unbind (const Handle(OpenGl_Context)& theCtx); + +private: + + //! Returns index of last modification of variables of specified state type. + Standard_EXPORT Standard_Size ActiveState (const OpenGl_UniformStateType theType) const; + + //! Updates index of last modification of variables of specified state type. + Standard_EXPORT void UpdateState (const OpenGl_UniformStateType theType, + const Standard_Size theIndex); + +public: + + //! Returns location of the specific uniform variable. + Standard_EXPORT GLint GetUniformLocation (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName) const; + + //! Returns index of the generic vertex attribute by variable name. + Standard_EXPORT GLint GetAttributeLocation (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName) const; + + //! Returns location of the OCCT state uniform variable. + Standard_EXPORT GLint GetStateLocation (const GLuint theVariable) const; + +public: + + //! Returns the value of the integer uniform variable. + Standard_EXPORT Standard_Boolean GetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4i& theValue) const; + + Standard_EXPORT Standard_Boolean GetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + OpenGl_Vec4i& theValue) const; + + //! Returns the value of the float uniform variable. + Standard_EXPORT Standard_Boolean GetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4& theValue) const; + + //! Returns the value of the float uniform variable. + Standard_EXPORT Standard_Boolean GetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + OpenGl_Vec4& theValue) const; + +public: + + //! Returns the integer vertex attribute. + Standard_EXPORT Standard_Boolean GetAttribute (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4i& theValue) const; + + //! Returns the integer vertex attribute. + Standard_EXPORT Standard_Boolean GetAttribute (const Handle(OpenGl_Context)& theCtx, + GLint theIndex, + OpenGl_Vec4i& theValue) const; + + //! Returns the float vertex attribute. + Standard_EXPORT Standard_Boolean GetAttribute (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + OpenGl_Vec4& theValue) const; + + //! Returns the float vertex attribute. + Standard_EXPORT Standard_Boolean GetAttribute (const Handle(OpenGl_Context)& theCtx, + GLint theIndex, + OpenGl_Vec4& theValue) const; + +public: + + //! Specifies the value of the integer uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLint theValue); + + //! Specifies the value of the integer uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLint theValue); + + //! Specifies the value of the integer uniform 2D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec2i& theValue); + + //! Specifies the value of the integer uniform 2D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec2i& theValue); + + //! Specifies the value of the integer uniform 3D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec3i& theValue); + + //! Specifies the value of the integer uniform 3D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec3i& theValue); + + //! Specifies the value of the integer uniform 4D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec4i& theValue); + + //! Specifies the value of the integer uniform 4D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec4i& theValue); + +public: + + //! Specifies the value of the float uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLfloat theValue); + + //! Specifies the value of the float uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLfloat theValue); + + //! Specifies the value of the float uniform 2D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec2& theValue); + + //! Specifies the value of the float uniform 2D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec2& theValue); + + //! Specifies the value of the float uniform 3D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec3& theValue); + + //! Specifies the value of the float uniform 3D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec3& theValue); + + //! Specifies the value of the float uniform 4D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Vec4& theValue); + + //! Specifies the value of the float uniform 4D vector. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Vec4& theValue); + +public: + + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Matrix& theValue, + GLboolean theTranspose = GL_FALSE); + + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Matrix& theValue, + GLboolean theTranspose = GL_FALSE); + + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const Tmatrix3& theValue, + GLboolean theTranspose = GL_FALSE); + + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const Tmatrix3& theValue, + GLboolean theTranspose = GL_FALSE); + +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); + + //! Specifies the value of the sampler uniform variable. + Standard_EXPORT Standard_Boolean SetSampler (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const GLenum theTextureUnit); + +protected: + + GLuint myProgramID; //! Handle of OpenGL shader program + OpenGl_ShaderList myShaderObjects; //! List of attached shader objects + Handle(Graphic3d_ShaderProgram) myProxy; //! Proxy shader program (from application layer) + +protected: + + //! Defines last modification for variables of each state type. + Standard_Size myCurrentState[MaxStateTypes]; + + //! Stores locations of OCCT state uniform variables. + GLint myStateLocations[OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES]; + +public: + + DEFINE_STANDARD_RTTI (OpenGl_ShaderProgram) + friend class OpenGl_ShaderManager; + +}; + +template +struct OpenGl_VariableSetter : public OpenGl_SetterInterface +{ + virtual void Set (const Handle(OpenGl_Context)& theCtx, + const Handle(Graphic3d_ShaderVariable)& theVariable, + OpenGl_ShaderProgram* theProgram) + { + theProgram->SetUniform (theCtx, + theVariable->Name().ToCString(), + theVariable->Value()->As()); + } +}; + +namespace OpenGl_HashMapInitializer +{ + template + struct MapListOfType + { + NCollection_DataMap myDictionary; + + MapListOfType (K theKey, V theValue) + { + myDictionary.Bind (theKey, theValue); + } + + MapListOfType& operator() (K theKey, V theValue) + { + myDictionary.Bind (theKey, theValue); + return *this; + } + + operator const NCollection_DataMap& () const + { + return myDictionary; + } + }; + + template + MapListOfType CreateListOf (K theKey, V theValue) + { + return MapListOfType (theKey, theValue); + } +} + +#endif // _OpenGl_ShaderProgram_Header diff --git a/src/OpenGl/OpenGl_ShaderStates.cxx b/src/OpenGl/OpenGl_ShaderStates.cxx new file mode 100644 index 0000000000..d02a80a9e1 --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderStates.cxx @@ -0,0 +1,262 @@ +// Created on: 2013-10-02 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include + +#include + +// ======================================================================= +// function : OpenGl_StateInterface +// purpose : Creates new OCCT state +// ======================================================================= +OpenGl_StateInterface::OpenGl_StateInterface() +: myIndex (0) +{ + // +} + +// ======================================================================= +// function : Index +// purpose : Returns current state index +// ======================================================================= +Standard_Size OpenGl_StateInterface::Index() const +{ + return myIndex; +} + +// ======================================================================= +// function : Update +// purpose : Updates current state +// ======================================================================= +void OpenGl_StateInterface::Update() +{ + ++myIndex; +} + +// ======================================================================= +// function : Revert +// purpose : Reverts current state +// ======================================================================= +void OpenGl_StateInterface::Revert() +{ + if (myIndex > 0) + { + --myIndex; + } +} + +// ======================================================================= +// function : OpenGl_ProjectionState +// purpose : Creates uninitialized projection state +// ======================================================================= +OpenGl_ProjectionState::OpenGl_ProjectionState() +: myInverseNeedUpdate (false) +{ + // +} + +// ======================================================================= +// function : Set +// purpose : Sets new OCCT projection state +// ======================================================================= +void OpenGl_ProjectionState::Set (const Tmatrix3& theProjectionMatrix) +{ + memcpy (myProjectionMatrix, theProjectionMatrix, sizeof (Tmatrix3)); + myInverseNeedUpdate = true; +} + +// ======================================================================= +// function : ProjectionMatrix +// purpose : Returns current projection matrix +// ======================================================================= +const Tmatrix3& OpenGl_ProjectionState::ProjectionMatrix() const +{ + return myProjectionMatrix; +} + +// ======================================================================= +// function : ProjectionMatrixInverse +// purpose : Returns inverse of current projection matrix +// ======================================================================= +const Tmatrix3& OpenGl_ProjectionState::ProjectionMatrixInverse() const +{ + if (!myInverseNeedUpdate) + { + return myProjectionMatrixInverse; + } + + reinterpret_cast*> (*myProjectionMatrix)->Inverted ( + *(reinterpret_cast*> (*myProjectionMatrixInverse))); + return myProjectionMatrixInverse; +} + +// ======================================================================= +// function : OpenGl_ModelWorldState +// purpose : Creates uninitialized model-world state +// ======================================================================= +OpenGl_ModelWorldState::OpenGl_ModelWorldState() +: myInverseNeedUpdate (false) +{ + // +} + +// ======================================================================= +// function : Set +// purpose : Sets new model-world matrix +// ======================================================================= +void OpenGl_ModelWorldState::Set (const Tmatrix3& theModelWorldMatrix) +{ + memcpy (myModelWorldMatrix, theModelWorldMatrix, sizeof (Tmatrix3)); + myInverseNeedUpdate = true; +} + +// ======================================================================= +// function : ModelWorldMatrix +// purpose : Returns current model-world matrix +// ======================================================================= +const Tmatrix3& OpenGl_ModelWorldState::ModelWorldMatrix() const +{ + return myModelWorldMatrix; +} + +// ======================================================================= +// function : ModelWorldMatrixInverse +// purpose : Returns inverse of current model-world matrix +// ======================================================================= +const Tmatrix3& OpenGl_ModelWorldState::ModelWorldMatrixInverse() const +{ + if (!myInverseNeedUpdate) + { + return myModelWorldMatrix; + } + + reinterpret_cast*> (*myModelWorldMatrix)->Inverted ( + *(reinterpret_cast*> (*myModelWorldMatrixInverse))); + return myModelWorldMatrixInverse; +} + +// ======================================================================= +// function : OpenGl_WorldViewState +// purpose : Creates uninitialized world-view state +// ======================================================================= +OpenGl_WorldViewState::OpenGl_WorldViewState() +: myInverseNeedUpdate (false) +{ + // +} + +// ======================================================================= +// function : Set +// purpose : Sets new world-view matrix +// ======================================================================= +void OpenGl_WorldViewState::Set (const Tmatrix3& theWorldViewMatrix) +{ + memcpy (myWorldViewMatrix, theWorldViewMatrix, sizeof (Tmatrix3)); + myInverseNeedUpdate = true; +} + +// ======================================================================= +// function : WorldViewMatrix +// purpose : Returns current world-view matrix +// ======================================================================= +const Tmatrix3& OpenGl_WorldViewState::WorldViewMatrix() const +{ + return myWorldViewMatrix; +} + +// ======================================================================= +// function : WorldViewMatrixInverse +// purpose : Returns inverse of current world-view matrix +// ======================================================================= +const Tmatrix3& OpenGl_WorldViewState::WorldViewMatrixInverse() const +{ + if (!myInverseNeedUpdate) + { + return myWorldViewMatrix; + } + + reinterpret_cast*> (*myWorldViewMatrix)->Inverted ( + *(reinterpret_cast*> (*myWorldViewMatrixInverse))); + return myWorldViewMatrixInverse; +} + +// ======================================================================= +// function : OpenGl_LightSourceState +// purpose : Creates uninitialized state of light sources +// ======================================================================= +OpenGl_LightSourceState::OpenGl_LightSourceState() +: myLightSources (NULL) +{ + // +} + +// ======================================================================= +// function : Set +// purpose : Sets new light sources +// ======================================================================= +void OpenGl_LightSourceState::Set (const OpenGl_ListOfLight* theLightSources) +{ + myLightSources = theLightSources; +} + +// ======================================================================= +// function : LightSources +// purpose : Returns current list of light sources +// ======================================================================= +const OpenGl_ListOfLight* OpenGl_LightSourceState::LightSources() const +{ + return myLightSources; +} + +// ======================================================================= +// function : OpenGl_MaterialState +// purpose : Creates uninitialized material state +// ======================================================================= +OpenGl_MaterialState::OpenGl_MaterialState (const OpenGl_Element* theAspect) +: myAspect (theAspect) +{ + // +} + +// ======================================================================= +// function : Set +// purpose : Sets new material aspect +// ======================================================================= +void OpenGl_MaterialState::Set (const OpenGl_Element* theAspect) +{ + myAspect = theAspect; +} + +// ======================================================================= +// function : Aspect +// purpose : Returns material aspect +// ======================================================================= +const OpenGl_Element* OpenGl_MaterialState::Aspect() const +{ + return myAspect; +} + +// ======================================================================= +// function : OpenGl_ClippingState +// purpose : Creates new clipping state +// ======================================================================= +OpenGl_ClippingState::OpenGl_ClippingState() +{ + // +} diff --git a/src/OpenGl/OpenGl_ShaderStates.hxx b/src/OpenGl/OpenGl_ShaderStates.hxx new file mode 100644 index 0000000000..60731ff4e9 --- /dev/null +++ b/src/OpenGl/OpenGl_ShaderStates.hxx @@ -0,0 +1,178 @@ +// Created on: 2013-10-02 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _OpenGl_State_HeaderFile +#define _OpenGl_State_HeaderFile + +#include + +#include + +#include +#include + +//! Defines interface for OpenGL state. +class OpenGl_StateInterface +{ +public: + + //! Creates new OCCT state. + OpenGl_StateInterface(); + + //! Returns current state index. + Standard_Size Index() const; + + //! Updates current state. + void Update(); + + //! Reverts current state. + void Revert(); + +protected: + + Standard_Size myIndex; //!< Current state index + +}; + +//! Defines state of OCCT projection transformation. +class OpenGl_ProjectionState : public OpenGl_StateInterface +{ +public: + + //! Creates uninitialized projection state. + OpenGl_ProjectionState(); + + //! Sets new projection matrix. + void Set (const Tmatrix3& theProjectionMatrix); + + //! Returns current projection matrix. + const Tmatrix3& ProjectionMatrix() const; + + //! Returns inverse of current projection matrix. + const Tmatrix3& ProjectionMatrixInverse() const; + +private: + + Tmatrix3 myProjectionMatrix; //!< OCCT projection matrix + mutable Tmatrix3 myProjectionMatrixInverse; //!< Inverse of OCCT projection matrix + bool myInverseNeedUpdate; //!< Is inversed matrix outdated? + +}; + +//! Defines state of OCCT model-world transformation. +class OpenGl_ModelWorldState : public OpenGl_StateInterface +{ +public: + + //! Creates uninitialized model-world state. + OpenGl_ModelWorldState(); + + //! Sets new model-world matrix. + void Set (const Tmatrix3& theModelWorldMatrix); + + //! Returns current model-world matrix. + const Tmatrix3& ModelWorldMatrix() const; + + //! Returns inverse of current model-world matrix. + const Tmatrix3& ModelWorldMatrixInverse() const; + +private: + + Tmatrix3 myModelWorldMatrix; //!< OCCT model-world matrix + mutable Tmatrix3 myModelWorldMatrixInverse; //!< Inverse of OCCT model-world matrix + bool myInverseNeedUpdate; //!< Is inversed matrix outdated? + +}; + +//! Defines state of OCCT world-view transformation. +class OpenGl_WorldViewState : public OpenGl_StateInterface +{ +public: + + //! Creates uninitialized world-view state. + OpenGl_WorldViewState(); + + //! Sets new world-view matrix. + void Set (const Tmatrix3& theWorldViewMatrix); + + //! Returns current world-view matrix. + const Tmatrix3& WorldViewMatrix() const; + + //! Returns inverse of current world-view matrix. + const Tmatrix3& WorldViewMatrixInverse() const; + +private: + + Tmatrix3 myWorldViewMatrix; //!< OCCT world-view matrix + mutable Tmatrix3 myWorldViewMatrixInverse; //!< Inverse of OCCT world-view matrix + bool myInverseNeedUpdate; //!< Is inversed matrix outdated? + +}; + +//! Defines state of OCCT light sources. +class OpenGl_LightSourceState : public OpenGl_StateInterface +{ +public: + + //! Creates uninitialized state of light sources. + OpenGl_LightSourceState(); + + //! Sets new light sources. + void Set (const OpenGl_ListOfLight* theLightSources); + + //! Returns current list of light sources. + const OpenGl_ListOfLight* LightSources() const; + +private: + + const OpenGl_ListOfLight* myLightSources; //!< List of OCCT light sources + +}; + +//! Defines generic state of OCCT material properties. +class OpenGl_MaterialState : public OpenGl_StateInterface +{ +public: + + //! Creates new material state. + OpenGl_MaterialState (const OpenGl_Element* theAspect = NULL); + + //! Sets new material aspect. + void Set (const OpenGl_Element* theAspect); + + //! Returns material aspect. + const OpenGl_Element* Aspect() const; + +private: + + const OpenGl_Element* myAspect; //!< OCCT material aspect + +}; + +//! Defines generic state of OCCT clipping state. +class OpenGl_ClippingState : public OpenGl_StateInterface +{ +public: + + //! Creates new clipping state. + OpenGl_ClippingState(); + +}; + +#endif // _OpenGl_State_HeaderFile diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 6bcd5bb52f..5f9c9d7e0b 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -17,16 +17,17 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#include -#include - -#include -#include -#include #include #include +#include +#include +#include +#include #include +#include +#include +#include #include @@ -398,6 +399,8 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const // Is rendering in ADD or IMMEDIATE mode? const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0; + const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext(); + // Apply local transformation GLint matrix_mode = 0; const OpenGl_Matrix *local_trsf = NULL; @@ -405,20 +408,34 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const { if (isImmediate) { - float mat16[16]; - call_util_transpose_mat (mat16, myTransformation->mat); + Tmatrix3 aModelWorld; + call_util_transpose_mat (*aModelWorld, myTransformation->mat); glGetIntegerv (GL_MATRIX_MODE, &matrix_mode); + + if (!aCtx->ShaderManager()->IsEmpty()) + { + Tmatrix3 aWorldView; + glGetFloatv (GL_MODELVIEW_MATRIX, *aWorldView); + + Tmatrix3 aProjection; + glGetFloatv (GL_PROJECTION_MATRIX, *aProjection); + + aCtx->ShaderManager()->UpdateModelWorldStateTo (aModelWorld); + aCtx->ShaderManager()->UpdateWorldViewStateTo (aWorldView); + aCtx->ShaderManager()->UpdateProjectionStateTo (aProjection); + } + glMatrixMode (GL_MODELVIEW); glPushMatrix (); glScalef (1.F, 1.F, 1.F); - glMultMatrixf (mat16); + glMultMatrixf (*aModelWorld); } else { glMatrixMode (GL_MODELVIEW); glPushMatrix(); - local_trsf = AWorkspace->SetStructureMatrix(myTransformation); + local_trsf = AWorkspace->SetStructureMatrix (myTransformation); } } @@ -426,7 +443,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL; if ( myTransPers && myTransPers->mode != 0 ) { - trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers ); + trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers); } // Apply aspects @@ -491,6 +508,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const { // add planes at loaded view matrix state aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace); + + // Set OCCT state uniform variables + if (!aContext->ShaderManager()->IsEmpty()) + { + aContext->ShaderManager()->UpdateClippingState(); + } } // Render groups @@ -511,6 +534,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty()) { aContext->ChangeClipping().Remove (*aUserPlanes); + + // Set OCCT state uniform variables + if (!aContext->ShaderManager()->IsEmpty()) + { + aContext->ShaderManager()->RevertClippingState(); + } } // Restore highlight color @@ -525,7 +554,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const // Restore transform persistence if ( myTransPers && myTransPers->mode != 0 ) { - AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers ); + AWorkspace->ActiveView()->BeginTransformPersistence (aContext, trans_pers); } // Restore local transformation @@ -535,10 +564,17 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const { glPopMatrix (); glMatrixMode (matrix_mode); + + Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f, 0.f }, + { 0.f, 0.f, 1.f, 0.f }, + { 0.f, 0.f, 0.f, 1.f } }; + + aContext->ShaderManager()->RevertModelWorldStateTo (aModelWorldState); } else { - AWorkspace->SetStructureMatrix(local_trsf); + AWorkspace->SetStructureMatrix (local_trsf, true); glMatrixMode (GL_MODELVIEW); glPopMatrix(); diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index 47862bb233..8d49896ee1 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -54,7 +54,7 @@ public: void SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect); void SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx, - const CALL_DEF_BOUNDBOX& theBoundBox); + const CALL_DEF_BOUNDBOX& theBoundBox); void ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx); diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 352047902a..5d78def968 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -17,11 +17,13 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#include -#include - #include +#include #include +#include +#include +#include +#include #include #include @@ -385,11 +387,34 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True); const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + + if (aCtx->IsGlGreaterEqual (2, 0)) + { + Handle(OpenGl_ShaderProgram) aProgram = aTextAspect->ShaderProgramRes (theWorkspace); + + if (!aProgram.IsNull()) + { + aProgram->BindWithVariables (aCtx); + + const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram); + + if (aMaterialState == NULL || aMaterialState->Aspect() != aTextAspect) + aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, aTextAspect); + + aCtx->ShaderManager()->PushState (aProgram); + } + else + { + OpenGl_ShaderProgram::Unbind (aCtx); + } + } + // use highlight color or colors from aspect if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) { render (theWorkspace->PrinterContext(), - theWorkspace->GetGlContext(), + aCtx, *aTextAspect, *theWorkspace->HighlightColor, *theWorkspace->HighlightColor); @@ -397,7 +422,7 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const else { render (theWorkspace->PrinterContext(), - theWorkspace->GetGlContext(), + aCtx, *aTextAspect, aTextAspect->Color(), aTextAspect->SubtitleColor()); diff --git a/src/OpenGl/OpenGl_TextFormatter.cxx b/src/OpenGl/OpenGl_TextFormatter.cxx index 36ca3bb440..82a295bae5 100644 --- a/src/OpenGl/OpenGl_TextFormatter.cxx +++ b/src/OpenGl/OpenGl_TextFormatter.cxx @@ -50,7 +50,7 @@ namespace } //! Auxiliary function to translate rectangles in horizontal direction. - inline void moveX (NCollection_Vector& theRects, + /*inline void moveX (NCollection_Vector& theRects, const Standard_ShortReal theMoveVec, Standard_Integer theCharLower, const Standard_Integer theCharUpper) @@ -61,7 +61,7 @@ namespace aRect.Left += theMoveVec; aRect.Right += theMoveVec; } - } + }*/ //! Auxiliary function to translate rectangles in vertical direction. inline void moveY (NCollection_Vector& theRects, diff --git a/src/OpenGl/OpenGl_Trihedron.cxx b/src/OpenGl/OpenGl_Trihedron.cxx index e3498f95fd..de86dea78f 100644 --- a/src/OpenGl/OpenGl_Trihedron.cxx +++ b/src/OpenGl/OpenGl_Trihedron.cxx @@ -617,6 +617,8 @@ void OpenGl_Trihedron::Release (const Handle(OpenGl_Context)& theCtx) myLabelX.Release (theCtx); myLabelY.Release (theCtx); myLabelZ.Release (theCtx); + myAspectLine.Release (theCtx); + myAspectText.Release (theCtx); } /*----------------------------------------------------------------------*/ @@ -648,7 +650,7 @@ void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) con const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); /* affichage du Triedre Non Zoomable */ - theWorkspace->ActiveView()->EndTransformPersistence(); + theWorkspace->ActiveView()->EndTransformPersistence (theWorkspace->GetGlContext()); if (myIsWireframe) { diff --git a/src/OpenGl/OpenGl_Vec.hxx b/src/OpenGl/OpenGl_Vec.hxx index d659fe34f7..9eeb62dfb0 100644 --- a/src/OpenGl/OpenGl_Vec.hxx +++ b/src/OpenGl/OpenGl_Vec.hxx @@ -22,8 +22,28 @@ #include +typedef NCollection_Vec2 OpenGl_Vec2i; +typedef NCollection_Vec3 OpenGl_Vec3i; +typedef NCollection_Vec4 OpenGl_Vec4i; + +typedef NCollection_Vec2 OpenGl_Vec2b; +typedef NCollection_Vec3 OpenGl_Vec3b; +typedef NCollection_Vec4 OpenGl_Vec4b; + +typedef NCollection_Vec2 OpenGl_Vec2u; +typedef NCollection_Vec3 OpenGl_Vec3u; +typedef NCollection_Vec4 OpenGl_Vec4u; + +typedef NCollection_Vec2 OpenGl_Vec2ub; +typedef NCollection_Vec3 OpenGl_Vec3ub; +typedef NCollection_Vec4 OpenGl_Vec4ub; + typedef NCollection_Vec2 OpenGl_Vec2; typedef NCollection_Vec3 OpenGl_Vec3; typedef NCollection_Vec4 OpenGl_Vec4; +typedef NCollection_Vec2 OpenGl_Vec2d; +typedef NCollection_Vec3 OpenGl_Vec3d; +typedef NCollection_Vec4 OpenGl_Vec4d; + #endif // _OpenGl_Vec_H__ diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index cb53c9046a..32e4b2d58f 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -17,18 +17,18 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. -#include +#include -#include #include -#include #include - +#include +#include +#include #include #include -#include - #include +#include +#include #include @@ -103,7 +103,10 @@ OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext) myIntShadingMethod(TEL_SM_GOURAUD), myAntiAliasing(Standard_False), myTransPers(&myDefaultTransPers), - myIsTransPers(Standard_False) + myIsTransPers(Standard_False), + myOrientationChanged (Standard_True), + myViewMappingChanged (Standard_True), + myLightSourcesChanged (Standard_True) { // Initialize matrices memcpy(myOrientationMatrix,myDefaultMatrix,sizeof(Tmatrix3)); @@ -133,7 +136,7 @@ void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) { OpenGl_Element::Destroy (theCtx, myTrihedron); OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron); - + if (!myTextureEnv.IsNull()) { theCtx->DelayedRelease (myTextureEnv); @@ -242,6 +245,8 @@ void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT &AContext) myLights.Append(rep); } + + myLightSourcesChanged = Standard_True; } /*----------------------------------------------------------------------*/ @@ -353,6 +358,8 @@ void OpenGl_View::SetMapping (const Handle(OpenGl_Display)& theGlDisplay, if (!err_ind) myExtra.map = Map; + + myViewMappingChanged = Standard_True; } /*----------------------------------------------------------------------*/ @@ -414,6 +421,8 @@ void OpenGl_View::SetOrientation (const Graphic3d_CView& theCView) myExtra.scaleFactors[1] = ScaleFactors[1], myExtra.scaleFactors[2] = ScaleFactors[2]; } + + myOrientationChanged = Standard_True; } /*----------------------------------------------------------------------*/ @@ -498,7 +507,7 @@ void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx) /*----------------------------------------------------------------------*/ //transform_persistence_end -void OpenGl_View::EndTransformPersistence() +void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx) { if (myIsTransPers) { @@ -508,19 +517,33 @@ void OpenGl_View::EndTransformPersistence() glMatrixMode (GL_MODELVIEW); glPopMatrix(); myIsTransPers = Standard_False; + + // Note: the approach of accessing OpenGl matrices is used now since the matrix + // manipulation are made with help of OpenGl methods. This might be replaced by + // direct computation of matrices by OCC subroutines. + Tmatrix3 aResultWorldView; + glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView); + + Tmatrix3 aResultProjection; + glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection); + + // Set OCCT state uniform variables + theCtx->ShaderManager()->RevertWorldViewStateTo (aResultWorldView); + theCtx->ShaderManager()->RevertProjectionStateTo (aResultProjection); } } /*----------------------------------------------------------------------*/ //transform_persistence_begin -const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const TEL_TRANSFORM_PERSISTENCE* theTransPers) +const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx, + const TEL_TRANSFORM_PERSISTENCE* theTransPers) { const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers; myTransPers = theTransPers; if (theTransPers->mode == 0) { - EndTransformPersistence(); + EndTransformPersistence (theCtx); return aTransPersPrev; } @@ -659,5 +682,18 @@ const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const T glTranslated (aMoveX, aMoveY, aMoveZ); } + // Note: the approach of accessing OpenGl matrices is used now since the matrix + // manipulation are made with help of OpenGl methods. This might be replaced by + // direct computation of matrices by OCC subroutines. + Tmatrix3 aResultWorldView; + glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView); + + Tmatrix3 aResultProjection; + glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection); + + // Set OCCT state uniform variables + theCtx->ShaderManager()->UpdateWorldViewStateTo (aResultWorldView); + theCtx->ShaderManager()->UpdateProjectionStateTo (aResultProjection); + return aTransPersPrev; } diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 43d3a6bc6f..fb1636dbb4 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -152,8 +152,9 @@ class OpenGl_View : public MMgt_TShared Standard_Integer Backfacing () const { return myBackfacing; } - const TEL_TRANSFORM_PERSISTENCE * BeginTransformPersistence ( const TEL_TRANSFORM_PERSISTENCE *ATransPers ); - void EndTransformPersistence (); + const TEL_TRANSFORM_PERSISTENCE * BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx, + const TEL_TRANSFORM_PERSISTENCE *theTransPers); + void EndTransformPersistence (const Handle(OpenGl_Context)& theCtx); //! Add structure to display list with specified priority. //! The structure will be added to associated with it z layer. @@ -196,7 +197,6 @@ public: void RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace); void RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext, - const Handle(OpenGl_Workspace)& theWorkspace, const Graphic3d_CView& theCView, const Aspect_CLayer2d& theCLayer); @@ -245,6 +245,11 @@ public: const TEL_TRANSFORM_PERSISTENCE *myTransPers; Standard_Boolean myIsTransPers; + //! Modification flags. + Standard_Boolean myOrientationChanged; + Standard_Boolean myViewMappingChanged; + Standard_Boolean myLightSourcesChanged; + public: DEFINE_STANDARD_ALLOC }; diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 363b225951..7200c3a040 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -26,13 +26,19 @@ #include #include +#include + #include +#include #include +#include #include #include #include #include #include +#include +#include #include #define EPSI 0.0001 @@ -42,7 +48,7 @@ static const GLfloat default_sptdir[3] = { 0.F, 0.F, -1.F }; static const GLfloat default_sptexpo = 0.F; static const GLfloat default_sptcutoff = 180.F; -extern void InitLayerProp (const int AListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx +extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx /*----------------------------------------------------------------------*/ @@ -658,6 +664,39 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, } } + // Set OCCT state uniform variables + + if (!aContext->ShaderManager()->IsEmpty()) + { + if (myLightSourcesChanged) + { + aContext->ShaderManager()->UpdateLightSourceStateTo (&myLights); + myLightSourcesChanged = Standard_False; + } + + if (myViewMappingChanged) + { + aContext->ShaderManager()->UpdateProjectionStateTo (myMappingMatrix); + myViewMappingChanged = Standard_False; + } + + if (myOrientationChanged) + { + aContext->ShaderManager()->UpdateWorldViewStateTo (myOrientationMatrix); + myOrientationChanged = Standard_False; + } + + if (aContext->ShaderManager()->ModelWorldState().Index() == 0) + { + Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f, 0.f }, + { 0.f, 0.f, 1.f, 0.f }, + { 0.f, 0.f, 0.f, 1.f } }; + + aContext->ShaderManager()->UpdateModelWorldStateTo (aModelWorldState); + } + } + ///////////////////////////////////////////////////////////////////////////// // Step 1: Prepare for redraw @@ -858,7 +897,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, ///////////////////////////////////////////////////////////////////////////// // Step 2: Draw underlayer - RedrawLayer2d (thePrintContext, AWorkspace, ACView, ACUnderLayer); + RedrawLayer2d (thePrintContext, ACView, ACUnderLayer); ///////////////////////////////////////////////////////////////////////////// // Step 3: Redraw main plane @@ -1051,6 +1090,11 @@ D = -[Px,Py,Pz] dot |Nx| aContext->ChangeClipping().AddWorld (aUserPlanes); } } + + if (!aContext->ShaderManager()->IsEmpty()) + { + aContext->ShaderManager()->UpdateClippingState(); + } } // Apply AntiAliasing @@ -1138,6 +1182,12 @@ D = -[Px,Py,Pz] dot |Nx| aContext->ChangeClipping().RemoveAll(); + if (!aContext->ShaderManager()->IsEmpty()) + { + aContext->ShaderManager()->ResetMaterialStates(); + aContext->ShaderManager()->RevertClippingState(); + } + // display global trihedron if (myTrihedron != NULL) { @@ -1165,7 +1215,7 @@ D = -[Px,Py,Pz] dot |Nx| const int aMode = 0; AWorkspace->DisplayCallback (ACView, (aMode | OCC_PRE_OVERLAY)); - RedrawLayer2d (thePrintContext, AWorkspace, ACView, ACOverLayer); + RedrawLayer2d (thePrintContext, ACView, ACOverLayer); AWorkspace->DisplayCallback (ACView, aMode); @@ -1225,7 +1275,6 @@ void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace) //call_togl_redraw_layer2d void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext, - const Handle(OpenGl_Workspace)& /*AWorkspace*/, const Graphic3d_CView& ACView, const Aspect_CLayer2d& ACLayer) { @@ -1336,9 +1385,9 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo //calling dynamic render of LayerItems if ( ACLayer.ptrLayer->layerData ) { - InitLayerProp(ACLayer.ptrLayer->listIndex); + InitLayerProp (ACLayer.ptrLayer->listIndex); ((Visual3d_Layer*)ACLayer.ptrLayer->layerData)->RenderLayerItems(); - InitLayerProp(0); + InitLayerProp (0); } glPopAttrib (); diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 5caff56f19..c17a0064f6 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -143,7 +143,7 @@ public: const TEL_COLOUR* HighlightColor; const OpenGl_Matrix* SetViewMatrix (const OpenGl_Matrix* ); - const OpenGl_Matrix* SetStructureMatrix (const OpenGl_Matrix* ); + const OpenGl_Matrix* SetStructureMatrix (const OpenGl_Matrix*, bool aRevert = false); const OpenGl_AspectLine* SetAspectLine (const OpenGl_AspectLine* theAspect); const OpenGl_AspectFace* SetAspectFace (const OpenGl_AspectFace* theAspect); diff --git a/src/OpenGl/OpenGl_Workspace_5.cxx b/src/OpenGl/OpenGl_Workspace_5.cxx index c537078e5d..df0247499d 100644 --- a/src/OpenGl/OpenGl_Workspace_5.cxx +++ b/src/OpenGl/OpenGl_Workspace_5.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #ifdef HAVE_CONFIG_H # include @@ -441,7 +443,7 @@ const OpenGl_Matrix * OpenGl_Workspace::SetViewMatrix(const OpenGl_Matrix *AMatr /*----------------------------------------------------------------------*/ -const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix(const OpenGl_Matrix *AMatrix) +const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix (const OpenGl_Matrix *AMatrix, bool aRevert) { const OpenGl_Matrix *StructureMatrix_old = StructureMatrix_applied; StructureMatrix_applied = AMatrix; @@ -454,6 +456,14 @@ const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix(const OpenGl_Matrix * OpenGl_Multiplymat3 (&rmat, &lmat, ViewMatrix_applied); glLoadMatrixf ((const GLfloat* )rmat.mat); + if (!myGlContext->ShaderManager()->IsEmpty()) + { + if (aRevert) + myGlContext->ShaderManager()->UpdateModelWorldStateTo (lmat.mat); + else + myGlContext->ShaderManager()->RevertModelWorldStateTo (lmat.mat); + } + return StructureMatrix_old; } diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl new file mode 100644 index 0000000000..88046a8131 --- /dev/null +++ b/src/Shaders/Declarations.glsl @@ -0,0 +1,192 @@ +#define _OCC_MAX_LIGHTS_ 8 + +#define _OCC_MAX_CLIP_PLANES_ 8 + + +//! OCCT ambient light source. +const int occAmbientLight = 0; + +//! OCCT directional light source. +const int occDirectLight = 1; + +//! OCCT isotropic point light source. +const int occPointLight = 2; + +//! OCCT spot light source. +const int occSpotLight = 3; + + +//! Parameters of OCCT light source. +struct occLightSource +{ + //! Type of light source. + int Type; + + //! Is light a headlight? + int Head; + + //! Ambient intensity. + vec3 Ambient; + + //! Diffuse intensity. + vec3 Diffuse; + + //! Specular intensity. + vec3 Specular; + + //! Position of light source. + vec3 Position; + + //! Direction of the spot light. + vec3 SpotDirection; + + //! Maximum spread angle of the spot light (in radians). + float SpotCutoff; + + //! Attenuation of the spot light intensity (from 0 to 1). + float SpotExponent; + + //! Const attenuation factor of positional light source. + float ConstAttenuation; + + //! Linear attenuation factor of positional light source. + float LinearAttenuation; +}; + +//! Parameters of OCCT material. +struct occMaterialParams +{ + //! Emission color. + vec4 Emission; + + //! Ambient reflection. + vec4 Ambient; + + //! Diffuse reflection. + vec4 Diffuse; + + //! Specular reflection. + vec4 Specular; + + //! Specular exponent. + float Shininess; + + //! Transparency coefficient. + float Transparency; +}; + +//! OCCT view-space clipping plane. +const int occEquationCoordsView = 0; + +//! OCCT world-space clipping plane. +const int occEquationCoordsWorld = 1; + +//! Parameters of OCCT clipping plane. +struct occClipPlane +{ + //! Plane equation. + vec4 Equation; + + //! Equation space. + int Space; +}; + +#ifdef VERTEX_SHADER + +///////////////////////////////////////////////////////////////////// +// OCCT vertex attributes + +// Note: At the moment, we just 'rename' the default OpenGL +// vertex attributes from compatibility profile. In the next +// release old functionality will be removed from shader API. + +//! Vertex color. +#define occColor gl_Color + +//! Normal coordinates. +#define occNormal gl_Normal + +//! Vertex coordinates. +#define occVertex gl_Vertex + +//! Texture coordinates. +#define occTexCoord gl_MultiTexCoord0 + +#endif + +///////////////////////////////////////////////////////////////////// +// OCCT matrix state + +//! World-view matrix. +uniform mat4 occWorldViewMatrix; + +//! Projection matrix. +uniform mat4 occProjectionMatrix; + +//! Model-world matrix. +uniform mat4 occModelWorldMatrix; + +//------------------------------------------------------- + +//! Inverse of the world-view matrix. +uniform mat4 occWorldViewMatrixInverse; + +//! Inverse of the projection matrix. +uniform mat4 occProjectionMatrixInverse; + +//! Inverse of the model-world matrix. +uniform mat4 occModelWorldMatrixInverse; + +//------------------------------------------------------- + +//! Transpose of the world-view matrix. +uniform mat4 occWorldViewMatrixTranspose; + +//! Transpose of the projection matrix. +uniform mat4 occProjectionMatrixTranspose; + +//! Transpose of the model-world matrix. +uniform mat4 occModelWorldMatrixTranspose; + +//------------------------------------------------------- + +//! Transpose of the inverse of the world-view matrix. +uniform mat4 occWorldViewMatrixInverseTranspose; + +//! Transpose of the inverse of the projection matrix. +uniform mat4 occProjectionMatrixInverseTranspose; + +//! Transpose of the inverse of the model-world matrix. +uniform mat4 occModelWorldMatrixInverseTranspose; + +///////////////////////////////////////////////////////////////////// +// OCCT light source state + +//! Array of OCCT light sources. +uniform occLightSource occLightSources[_OCC_MAX_LIGHTS_]; + +//! Total number of OCCT light sources. +uniform int occLightSourcesCount; + +///////////////////////////////////////////////////////////////////// +// OCCT material state + +//! Parameters of OCCT back material. +uniform occMaterialParams occBackMaterial; + +//! Parameters of OCCT front material. +uniform occMaterialParams occFrontMaterial; + +//! Are front and back faces distinguished? +uniform int occDistinguishingMode; + +//! Is texture enabled? +uniform int occTextureEnable; + +//! Current active sampler. +uniform sampler2D occActiveSampler; + +///////////////////////////////////////////////////////////////////// +// OCCT clipping planes state + +uniform occClipPlane occClipPlanes[_OCC_MAX_CLIP_PLANES_]; diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index ac8fda7f09..065fd97a07 100755 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -56,6 +56,8 @@ #include #include #include +#include +#include #include #include #include @@ -1897,6 +1899,64 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha return 0; } +//============================================================================== +//function : VShaderProg +//purpose : Sets the pair of vertex and fragment shaders for the object +//============================================================================== +static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/, + Standard_Integer theArgNb, + const char** theArgVec) +{ + Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext(); + if (anAISContext.IsNull()) + { + std::cerr << "Use 'vinit' command before " << theArgVec[0] << "\n"; + return 1; + } + + if (theArgNb < 3) + { + std::cerr << theArgVec[0] <<" syntax error: lack of arguments - Type 'help vshaderprog\n"; + return 1; + } + + const TCollection_AsciiString aShapeName = theArgVec[1]; + if (!GetMapOfAIS().IsBound2 (aShapeName)) + { + std::cerr << theArgVec[0] << ": Use 'vdisplay' before\n"; + return 1; + } + + Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aShapeName)); + if (anIO.IsNull()) + { + std::cerr << "Shape " << aShapeName.ToCString() << " does not exist\n"; + return 1; + } + + Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram(); + const TCollection_AsciiString aVertexSource (theArgVec[2]); + if (!aVertexSource.IsEmpty() && !OSD_File(aVertexSource).Exists()) + { + std::cerr << "Non-existing vertex shader source\n"; + return 1; + } + + TCollection_AsciiString aFragmentSource (theArgVec[3]); + if (!aFragmentSource.IsEmpty() && !OSD_File(aFragmentSource).Exists()) + { + std::cerr << "Non-existing fragment shader source\n"; + return 1; + } + + aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aVertexSource)); + aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aFragmentSource)); + anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram); + + anAISContext->Redisplay (anIO); + return 0; +} + //============================================================================== //function : VDisplay2 //author : ege @@ -3281,6 +3341,10 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) or 'vtexture NameOfShape IdOfTexture' (0<=IdOfTexture<=20)' to use predefined textures\n ", __FILE__,VTexture,group); + theCommands.Add("vshaderprog", + "'vshaderprog NameOfShape VertexShaderFile FragmentShaderFile'", + __FILE__,VShaderProg,group); + theCommands.Add("vtexscale", "'vtexscale NameOfShape ScaleU ScaleV' \n \ or 'vtexscale NameOfShape ScaleUV' \n \