Files
OpenSceneGraph/include/osgGL2/ProgramObject
Robert Osfield aa833acfd3 Added support for releasing GLObjects, and renamed DisplayListVisitor the
GLObjectVisitor to better fit its function, and added support for releasing
objects as well as compiling them.
2004-07-20 05:37:59 +00:00

304 lines
10 KiB
C++

/* -*-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 <osg/State>
#include <osg/StateAttribute>
#include <osg/buffered_value>
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osgGL2/Export>
#include <osgGL2/Extensions>
#include <osgGL2/UniformValue>
#include <string>
#include <vector>
namespace osgGL2 {
class ProgramObject;
typedef osg::ref_ptr<ProgramObject> ProgramObjectPtr;
class ShaderObject;
typedef osg::ref_ptr<ShaderObject> 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
{
// check the types are equal and then create the rhs variable
// used by the COMPARE_StateAttribute_Paramter macro's below.
COMPARE_StateAttribute_Types(ProgramObject,sa)
// compare each parameter in turn against the rhs.
COMPARE_StateAttribute_Parameter(_shaderObjectList);
// COMPARE_StateAttribute_Parameter(_pcpoList);
return 0; // passed all the above comparison macro's, must be equal.
}
/** 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<int>(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> _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;
std::vector< ShaderObjectPtr > _shaderObjectList;
mutable osg::buffered_value< osg::ref_ptr<PerContextProgObj> > _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);
// 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> _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<PerContextShaderObj> > _pcsoList;
private:
const ShaderObject& operator=(const ShaderObject&);
};
}
#endif
/*EOF*/