diff --git a/examples/osgshaders/GL2Scene.cpp b/examples/osgshaders/GL2Scene.cpp index 807fa1d72..f90e6f470 100644 --- a/examples/osgshaders/GL2Scene.cpp +++ b/examples/osgshaders/GL2Scene.cpp @@ -11,7 +11,7 @@ */ /* file: examples/osgshaders/GL2Scene.cpp - * author: Mike Weiblen 2003-10-03 + * author: Mike Weiblen 2003-12-28 * * Compose a scene of several instances of a model, with a different * OpenGL Shading Language shader applied to each. @@ -138,19 +138,21 @@ make1DSineTexture( int texSize ) /////////////////////////////////////////////////////////////////////////// -// static osg::Node* createGlobe() -// { -// osg::Geode* geode = new osg::Geode(); -// osg::StateSet* stateset = geode->getOrCreateStateSet(); -// -// osg::Texture2D* texture = new osg::Texture2D; -// texture->setImage( osgDB::readImageFile("Images/land_shallow_topo_2048.jpg") ); -// stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); -// -// geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 2.0f))); -// -// return geode; -// } +#if 0 //[ +static osg::Node* createGlobe() +{ + osg::Geode* geode = new osg::Geode(); + osg::StateSet* stateset = geode->getOrCreateStateSet(); + + osg::Texture2D* texture = new osg::Texture2D; + texture->setImage( osgDB::readImageFile("Images/land_shallow_topo_2048.jpg") ); + stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); + + geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 2.0f))); + + return geode; +} +#endif //] /////////////////////////////////////////////////////////////////////////// // OpenGL Shading Language source code for the "microshader" example, @@ -169,7 +171,7 @@ static const char *microshaderFragSource = { "varying vec4 color;" "void main(void)" "{" - "gl_FragColor = color;" + "gl_FragColor = clamp( color, 0.0, 1.0 );" "}" }; @@ -347,18 +349,20 @@ GL2Scene::buildScene() ss->setAttributeAndModes(MarbleProgObj, osg::StateAttribute::ON); } +#ifdef INTERNAL_3DLABS //[ // regular GL 1.x texturing for comparison. - if( 0 ) { - osg::StateSet* ss = ModelInstance(); - osg::Texture2D* tex0 = new osg::Texture2D; - tex0->setImage( osgDB::readImageFile( "images/3dl-ge100.png" ) ); - ss->setTextureAttributeAndModes(0, tex0, osg::StateAttribute::ON); - } + osg::StateSet* ss = ModelInstance(); + osg::Texture2D* tex0 = new osg::Texture2D; + tex0->setImage( osgDB::readImageFile( "images/3dl-ge100.png" ) ); + ss->setTextureAttributeAndModes(0, tex0, osg::StateAttribute::ON); +#endif //] reloadShaderSource(); +#ifdef INTERNAL_3DLABS //[ // add logo overlays - // rootNode->addChild( osgDB::readNodeFile( "3dl_ogl.logo" ) ); + rootNode->addChild( osgDB::readNodeFile( "3dl_ogl.logo" ) ); +#endif //] return rootNode; } diff --git a/examples/osgshaders/Noise.cpp b/examples/osgshaders/Noise.cpp index 4ac82e826..10fec0cd5 100644 --- a/examples/osgshaders/Noise.cpp +++ b/examples/osgshaders/Noise.cpp @@ -2,7 +2,7 @@ * * * Copyright (C) 2002 3Dlabs Inc. Ltd. * * * -/************************************************************************/ + ************************************************************************/ #include #include diff --git a/include/osgGL2/ProgramObject b/include/osgGL2/ProgramObject index 447d753cd..8c6539f98 100644 --- a/include/osgGL2/ProgramObject +++ b/include/osgGL2/ProgramObject @@ -11,7 +11,7 @@ */ /* file: include/osgGL2/ProgramObject - * author: Mike Weiblen 2003-10-03 + * author: Mike Weiblen 2003-12-28 * * See http://www.3dlabs.com/opengl2/ for more information regarding * the OpenGL Shading Language. @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -47,8 +46,17 @@ 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. + */ -/** Encapsulates the OpenGL Shading Language ProgramObject */ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute { public: @@ -75,24 +83,30 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute virtual void getAssociatedModes(std::vector& ) 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 compile(osg::State& state) const { apply(state); } // data access methods. - /** Force a relink on next apply() of associated glProgramObject. */ + /** Mark us as "dirty" and in need of relinking. */ void dirtyProgramObject(); - /** Force a recompile of all ShaderObjects on next apply(). */ + /** Mark our attached ShaderObjects as "dirty" and in need of + * recompilation. */ void dirtyShaderObjects(); - /** Set whether rendering of ProgramObject is enabled or disabled */ + /** 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 ); @@ -105,10 +119,9 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute setUniform( uniformName, static_cast(value) ); } - /** use deleteObject instead of glDeleteObject to allow - * GL2 Objects to cached until they can be deleted - * by the OpenGL context in which they were created, specified - * by contextID.*/ + /** 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 @@ -117,6 +130,7 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute protected: + /** PCPO is an OSG-internal encapsulation of glProgramObjects per-GL context. */ class PerContextProgObj : public osg::Referenced { public: @@ -130,27 +144,37 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute void build(); void use() const; + /** Add a list of UniformValues to our per-context queue */ void updateUniforms( const UniformValueList& univalList ); - void applyUniformValues(); - void printInfoLog(osg::NotifySeverity severity) const; + /** 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*/ @@ -159,11 +183,21 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute 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. + */ -/** Encapsulates the OpenGL Shading Language ShaderObject */ class OSGGL2_EXPORT ShaderObject : public osg::Object { public: @@ -184,20 +218,33 @@ class OSGGL2_EXPORT ShaderObject : public osg::Object // 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; - /** Force a recompile on next apply() of associated glShaderObject. */ + /** 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: @@ -210,18 +257,21 @@ class OSGGL2_EXPORT ShaderObject : public osg::Object void markAsDirty() {_dirty = true; } void build(); + /** Attach our glShaderObject to a glProgramObject */ void attach(GLhandleARB progObj) const; - void printInfoLog(osg::NotifySeverity severity) 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; }; @@ -238,9 +288,13 @@ class OSGGL2_EXPORT ShaderObject : public osg::Object std::string _shaderSource; std::vector< ProgramObjectPtr > _programObjectList; mutable osg::buffered_value< osg::ref_ptr > _pcsoList; + + private: + const ShaderObject& operator=(const ShaderObject&); }; } #endif +/*EOF*/ diff --git a/include/osgGL2/UniformValue b/include/osgGL2/UniformValue index 70202f06e..11632eee4 100644 --- a/include/osgGL2/UniformValue +++ b/include/osgGL2/UniformValue @@ -11,7 +11,7 @@ */ /* file: include/osgGL2/UniformValue - * author: Mike Weiblen 2003-09-18 + * author: Mike Weiblen 2003-12-28 * * See http://www.3dlabs.com/opengl2/ for more information regarding * the OpenGL Shading Language. @@ -34,13 +34,13 @@ namespace osgGL2 { /////////////////////////////////////////////////////////////////////////// - -/** An abstract class to encapsulate a new value for a glUniform. +/** osgGL2::UniformValue is for internal use by osgGL2::ProgramObject. + * UniformValue is an abstract class to encapsulate a new value for a glUniform. * osgGL2::ProgramObject.setUniform() constructs and sends a UniformValue - * to all its PCPOs (per-context glProgramObjects) to set the value of a - * glUniform; that value is propogated to the glProgramObjects during the - * next osgGL2::ProgramObject.apply(). - * This class is for internal use by osgGL2::ProgramObject. + * to all its PerContextProgramObjects (PCPOs) to set the value of a + * glUniform. + * The value contained in each UniformValue value is propagated to the + * glProgramObjects during the next osgGL2::ProgramObject.apply(). */ class UniformValue : public osg::Referenced @@ -51,6 +51,9 @@ class UniformValue : public osg::Referenced protected: UniformValue( const char* uniformName ) : _name( uniformName ) {}; virtual ~UniformValue() {}; + UniformValue(); + UniformValue(const UniformValue&); + UniformValue& operator=(const UniformValue&); int getLocation( Extensions *ext, const GLhandleARB progObj ) const; @@ -61,28 +64,30 @@ typedef std::vector< osg::ref_ptr > UniformValueList; /////////////////////////////////////////////////////////////////////////// +/** UniformValueTemplate creates the concrete classes for each of the + * uniform value types */ -#define META_UniformValue( typeName ) \ -class UniformValue_##typeName : public UniformValue \ -{ \ - public: \ - UniformValue_##typeName( const char* uniformName, typeName value ); \ - virtual void apply( Extensions *ext, const GLhandleARB progObj ) const; \ - protected: \ - typeName _value; \ -} +template +class UniformValueTemplate: public UniformValue +{ + public: + UniformValueTemplate( const char* uniformName, T value ) : + UniformValue( uniformName ), _value( value ) {} + virtual void apply( Extensions *ext, const GLhandleARB progObj ) const; -META_UniformValue( int ); -META_UniformValue( float ); + protected: + UniformValueTemplate(); + const T _value; +}; -using namespace osg; -META_UniformValue( Vec2 ); -META_UniformValue( Vec3 ); -META_UniformValue( Vec4 ); +typedef UniformValueTemplate UniformValue_int; +typedef UniformValueTemplate UniformValue_float; +typedef UniformValueTemplate UniformValue_Vec2; +typedef UniformValueTemplate UniformValue_Vec3; +typedef UniformValueTemplate UniformValue_Vec4; } #endif /*EOF*/ - diff --git a/src/osgGL2/ProgramObject.cpp b/src/osgGL2/ProgramObject.cpp index 40d94bc53..8bb49b11b 100644 --- a/src/osgGL2/ProgramObject.cpp +++ b/src/osgGL2/ProgramObject.cpp @@ -12,7 +12,7 @@ */ /* file: src/osgGL2/ProgramObject.cpp - * author: Mike Weiblen 2003-09-18 + * author: Mike Weiblen 2003-12-27 * * See http://www.3dlabs.com/opengl2/ for more information regarding * the OpenGL Shading Language. @@ -34,6 +34,38 @@ using namespace osgGL2; +/////////////////////////////////////////////////////////////////////////// + +namespace { + +class InfoLog +{ +public: + InfoLog( Extensions* ext, const GLhandleARB handle ) + { + int blen = 0; // length of buffer to allocate + int slen = 0; // strlen GL actually wrote to buffer + + ext->glGetObjectParameteriv(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen); + if (blen > 1) + { + GLcharARB* infoLog = new GLcharARB[blen]; + ext->glGetInfoLog( handle, blen, &slen, infoLog ); + _text = infoLog; + delete [] infoLog; + } + } + + const std::string& operator()() { return _text; } + +private: + InfoLog(); + std::string _text; +}; + +} + + /////////////////////////////////////////////////////////////////////////// // static cache of deleted GL2 objects which may only // by actually deleted in the correct GL context. @@ -305,8 +337,8 @@ void ProgramObject::PerContextProgObj::build() _dirty = (linked == 0); if( _dirty ) { - osg::notify(osg::WARN) << "glLinkProgram FAILED:" << std::endl; - printInfoLog(osg::WARN); + InfoLog log( _extensions.get(), _glProgObjHandle ); + osg::notify(osg::WARN) << "glLinkProgram FAILED:\n" << log() << std::endl; } } @@ -333,22 +365,6 @@ void ProgramObject::PerContextProgObj::applyUniformValues() } -void ProgramObject::PerContextProgObj::printInfoLog(osg::NotifySeverity severity) const -{ - int blen = 0; // length of buffer to allocate - int slen = 0; // strlen GL actually wrote to buffer - - _extensions->glGetObjectParameteriv(_glProgObjHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen); - if (blen > 1) - { - GLcharARB* infoLog = new GLcharARB[blen]; - _extensions->glGetInfoLog(_glProgObjHandle, blen, &slen, infoLog); - osg::notify(severity) << infoLog << std::endl; - delete infoLog; - } -} - - /////////////////////////////////////////////////////////////////////////// // osgGL2::ShaderObject /////////////////////////////////////////////////////////////////////////// @@ -426,7 +442,7 @@ bool ShaderObject::loadShaderSourceFromFile( const char* fileName ) text[length] = '\0'; setShaderSource( text ); - delete text; + delete [] text; return true; } @@ -437,7 +453,7 @@ const char* ShaderObject::getTypename() const { case VERTEX: return "Vertex"; case FRAGMENT: return "Fragment"; - default: return "UNKNOWN"; + default: return "UNKNOWN"; } } @@ -515,8 +531,9 @@ void ShaderObject::PerContextShaderObj::build() _dirty = (compiled == 0); if( _dirty ) { - osg::notify(osg::WARN) << _shadObj->getTypename() << " glCompileShader FAILED:" << std::endl; - printInfoLog(osg::WARN); + InfoLog log( _extensions.get(), _glShaderObjHandle ); + osg::notify(osg::WARN) << _shadObj->getTypename() << + " glCompileShader FAILED:\n" << log() << std::endl; } } @@ -525,20 +542,4 @@ void ShaderObject::PerContextShaderObj::attach(GLhandleARB progObj) const _extensions->glAttachObject( progObj, _glShaderObjHandle ); } -void ShaderObject::PerContextShaderObj::printInfoLog(osg::NotifySeverity severity) const -{ - int blen = 0; // length of buffer to allocate - int slen = 0; // strlen GL actually wrote to buffer - - _extensions->glGetObjectParameteriv(_glShaderObjHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen); - if (blen > 1) - { - GLcharARB* infoLog = new GLcharARB[blen]; - _extensions->glGetInfoLog(_glShaderObjHandle, blen, &slen, infoLog); - osg::notify(severity) << infoLog << std::endl; - delete infoLog; - } -} - /*EOF*/ - diff --git a/src/osgGL2/UniformValue.cpp b/src/osgGL2/UniformValue.cpp index ef8217815..c1bde3f7d 100644 --- a/src/osgGL2/UniformValue.cpp +++ b/src/osgGL2/UniformValue.cpp @@ -11,7 +11,7 @@ */ /* file: src/osgGL2/UniformValue - * author: Mike Weiblen 2003-09-12 + * author: Mike Weiblen 2003-12-27 * * See http://www.3dlabs.com/opengl2/ for more information regarding * the OpenGL Shading Language. @@ -38,13 +38,6 @@ int UniformValue::getLocation( Extensions *ext, const GLhandleARB progObj ) cons /////////////////////////////////////////////////////////////////////////// -#define META_UniformValueCtor( typeName ) \ -UniformValue_##typeName::UniformValue_##typeName( const char* uniformName, typeName value ) : \ - UniformValue( uniformName ) \ -{ _value = value; } \ - - -META_UniformValueCtor( int ); void UniformValue_int::apply( Extensions *ext, const GLhandleARB progObj ) const { int loc = getLocation( ext, progObj ); @@ -54,7 +47,6 @@ void UniformValue_int::apply( Extensions *ext, const GLhandleARB progObj ) const } } -META_UniformValueCtor( float ); void UniformValue_float::apply( Extensions *ext, const GLhandleARB progObj ) const { int loc = getLocation( ext, progObj ); @@ -64,7 +56,6 @@ void UniformValue_float::apply( Extensions *ext, const GLhandleARB progObj ) con } } -META_UniformValueCtor( Vec2 ); void UniformValue_Vec2::apply( Extensions *ext, const GLhandleARB progObj ) const { int loc = getLocation( ext, progObj ); @@ -74,7 +65,6 @@ void UniformValue_Vec2::apply( Extensions *ext, const GLhandleARB progObj ) cons } } -META_UniformValueCtor( Vec3 ); void UniformValue_Vec3::apply( Extensions *ext, const GLhandleARB progObj ) const { int loc = getLocation( ext, progObj ); @@ -84,7 +74,6 @@ void UniformValue_Vec3::apply( Extensions *ext, const GLhandleARB progObj ) cons } } -META_UniformValueCtor( Vec4 ); void UniformValue_Vec4::apply( Extensions *ext, const GLhandleARB progObj ) const { int loc = getLocation( ext, progObj ); @@ -95,4 +84,3 @@ void UniformValue_Vec4::apply( Extensions *ext, const GLhandleARB progObj ) cons } /*EOF*/ - diff --git a/src/osgGL2/Version.cpp b/src/osgGL2/Version.cpp index 240d15178..cfa65f889 100644 --- a/src/osgGL2/Version.cpp +++ b/src/osgGL2/Version.cpp @@ -2,7 +2,7 @@ const char* osgGL2GetVersion() { - return "0.2.3"; + return "0.2.6"; }