/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * Copyright (C) 2003 3Dlabs Inc. Ltd. * * This application is open source and may be redistributed and/or modified * freely and without restriction, both in commericial and non commericial * applications, as long as this copyright notice is maintained. * * This application is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* file: include/osgGL2/ProgramObject * author: Mike Weiblen 2003-12-28 * * See http://www.3dlabs.com/opengl2/ for more information regarding * the OpenGL Shading Language. */ #ifndef OSGGL2_PROGRAMOBJECT #define OSGGL2_PROGRAMOBJECT 1 #include #include #include #include #include #include #include #include #include #include #include #include namespace osgGL2 { class ProgramObject; typedef osg::ref_ptr ProgramObjectPtr; class ShaderObject; typedef osg::ref_ptr ShaderObjectPtr; /////////////////////////////////////////////////////////////////////////// /** osgGL2::ProgramObject is an application-level abstraction of the OpenGL Shading Language glProgramObject. * It is an osg::StateAttribute that, when applied, will install an OGLSL * shader program for subsequent rendering. * osgGL2::ShaderObjects containing the actual shader source code are * attached to the ProgramObject, which will then manage the compilation, * linking, and installation of the GL shader program. * ProgramObject will automatically manage per-context instancing of the * internal objects, if that is necessary for a particular display * configuration. */ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute { public: ProgramObject(); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ ProgramObject(const ProgramObject& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); META_StateAttribute(osgGL2, ProgramObject, PROGRAMOBJECT); /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ virtual int compare(const osg::StateAttribute& sa) const; /** If enabled, install our shader program in the GL pipeline, * performing any shader program rebuild operations that might * be pending. */ virtual void apply(osg::State& state) const; virtual void compileGLObjects(osg::State& state) const { apply(state); } /** release an OpenGL objects in specified graphics context if State object is passed, otherwise release OpenGL objexts for all graphics context if State object pointer NULL.*/ virtual void releaseGLObjects(osg::State* state=0) const; // data access methods. /** Mark us as "dirty" and in need of relinking. */ void dirtyProgramObject(); /** Mark our attached ShaderObjects as "dirty" and in need of * recompilation. */ void dirtyShaderObjects(); /** An override to control whether the shader program will * actually be installed when OSG attempts to apply() */ void enable( bool enabled ) { _enabled = enabled; } /** Attach a ShaderObject to this ProgramObject */ void addShader( ShaderObject* shadObj ); /** Assign a value to a ProgramObject's uniform variable */ void setUniform( const char* uniformName, int value ); void setUniform( const char* uniformName, float value ); void setUniform( const char* uniformName, osg::Vec2 value ); void setUniform( const char* uniformName, osg::Vec3 value ); void setUniform( const char* uniformName, osg::Vec4 value ); inline void setSampler( const char* uniformName, int value ) { // emphatic alias for setUniform(int) setUniform( uniformName, static_cast(value) ); } /** Mark internal GL objects for deletion. * Deletion requests are queued until they can be executed * in the proper GL context. */ static void deleteObject(unsigned int contextID, GLhandleARB handle); /** flush all the cached glProgramObjects which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedGL2Objects(unsigned int contextID,double currentTime, double& availableTime); protected: /** PCPO is an OSG-internal encapsulation of glProgramObjects per-GL context. */ class PerContextProgObj : public osg::Referenced { public: PerContextProgObj(const ProgramObject* progObj, unsigned int contextID); PerContextProgObj(const PerContextProgObj& rhs); GLhandleARB& getHandle() {return _glProgObjHandle;} bool isDirty() const {return _dirty;} void markAsDirty() {_dirty = true; } void build(); void use() const; /** Add a list of UniformValues to our per-context queue */ void updateUniforms( const UniformValueList& univalList ); /** Apply our queue of pending UniformValue updates to the glProgramObjects */ void applyUniformValues(); protected: /*methods*/ PerContextProgObj(); ~PerContextProgObj(); protected: /*data*/ /** Pointer to our parent ProgramObject */ const ProgramObject* _progObj; /** Pointer to this context's extension functions */ osg::ref_ptr _extensions; /** Handle to the actual glProgramObject */ GLhandleARB _glProgObjHandle; /** Do we need to be linked? */ bool _dirty; /** Queue of UniformValues awaiting assignment */ UniformValueList _univalList; const unsigned int _contextID; }; protected: /*methods*/ virtual ~ProgramObject(); /** Get the PCPO for a particular GL context */ PerContextProgObj* getPCPO(unsigned int contextID) const; /** Per frame, copy the list of pending UniformValue updates to * each of the PCPOs. */ void updateUniforms( int frameNumber ) const; protected: /*data*/ bool _enabled; typedef std::vector< ShaderObjectPtr > ShaderObjectList; ShaderObjectList _shaderObjectList; mutable osg::buffered_value< osg::ref_ptr > _pcpoList; mutable int _frameNumberOfLastPCPOUpdate; mutable UniformValueList _univalList; private: const ProgramObject& operator=(const ProgramObject&); }; /////////////////////////////////////////////////////////////////////////// /** osgGL2::ShaderObject is an application-level abstraction of the OpenGL Shading Language glShaderObject. * It is a container to load the shader source code text and manage its * compilation. * A ShaderObject may be attached to more than one osgGL2::ProgramObject. * ShaderObject will automatically manage per-context instancing of the * internal objects, if that is necessary for a particular display * configuration. */ class OSGGL2_EXPORT ShaderObject : public osg::Object { public: enum Type { VERTEX = GL_VERTEX_SHADER_ARB, FRAGMENT = GL_FRAGMENT_SHADER_ARB, UNKNOWN = -1 }; ShaderObject(); ShaderObject(Type type); ShaderObject(Type type, const char* sourceText); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ ShaderObject(const ShaderObject& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); META_Object(osgGL2, ShaderObject); int compare(const ShaderObject& sa) const; // data access methods. /** Load the ShaderObject's source code text from a string. */ void setShaderSource( const char* sourceText ); /** Retreive the source code text */ inline const std::string& getShaderSource() const {return _shaderSource; } /** Load the ShaderObject's source code text from a file. */ bool loadShaderSourceFromFile( const char* fileName ); /** Get the ShaderObject type as an enum. */ inline Type getType() const { return _type; } /** Get the ShaderObject type as a descriptive string. */ const char* getTypename() const; /** Mark us as "dirty" and in need of recompilation */ void dirtyShaderObject(); /** Perform a recompilation of all our PCSOs */ void build(unsigned int contextID) const; /** For a given GL context, attach a glShaderObject to a glProgramObject */ void attach(unsigned int contextID, GLhandleARB progObj) const; protected: /** PCSO is an OSG-internal encapsulation of glShaderObjects per-GL context. */ class PerContextShaderObj : public osg::Referenced { public: PerContextShaderObj(const ShaderObject* shadObj, unsigned int contextID); PerContextShaderObj(const PerContextShaderObj& rhs); GLhandleARB& getHandle() {return _glShaderObjHandle;} bool isDirty() const {return _dirty;} void markAsDirty() {_dirty = true; } void build(); /** Attach our glShaderObject to a glProgramObject */ void attach(GLhandleARB progObj) const; protected: /*methods*/ PerContextShaderObj(); ~PerContextShaderObj(); protected: /*data*/ /** Pointer to our parent ShaderObject */ const ShaderObject* _shadObj; /** Pointer to this context's extension functions. */ osg::ref_ptr _extensions; /** Handle to the actual glShaderObject. */ GLhandleARB _glShaderObjHandle; /** Do we need to be recompiled? */ bool _dirty; const unsigned int _contextID; }; protected: /*methods*/ virtual ~ShaderObject(); PerContextShaderObj* getPCSO(unsigned int contextID) const; friend void ProgramObject::addShader( ShaderObject* shadObj ); // to access addProgObjRef() void addProgObjRef( ProgramObject* progObj ); protected: /*data*/ Type _type; std::string _shaderSource; std::vector< ProgramObjectPtr > _programObjectList; mutable osg::buffered_value< osg::ref_ptr > _pcsoList; private: const ShaderObject& operator=(const ShaderObject&); }; } #endif /*EOF*/