diff --git a/include/osg/BufferObject b/include/osg/BufferObject index bc1cfb36b..1fd48563b 100644 --- a/include/osg/BufferObject +++ b/include/osg/BufferObject @@ -26,8 +26,6 @@ #include #ifndef GL_ARB_vertex_buffer_object - #define GL_ARB_vertex_buffer_object - #define GL_ARRAY_BUFFER_ARB 0x8892 #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 #define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 diff --git a/include/osg/Drawable b/include/osg/Drawable index 7304cb2c8..c88492bc3 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -582,6 +582,92 @@ inline void Drawable::draw(RenderInfo& renderInfo) const drawImplementation(renderInfo); } +class AttributeFunctorArrayVisitor : public ArrayVisitor +{ + public: + + AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af): + _af(af), + _type(0) {} + + virtual ~AttributeFunctorArrayVisitor() {} + + virtual void apply(ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + + + inline void applyArray(Drawable::AttributeType type,Array* array) + { + if (array) + { + _type = type; + array->accept(*this); + } + } + + protected: + + AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; } + Drawable::AttributeFunctor& _af; + Drawable::AttributeType _type; +}; + +class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor +{ + public: + + ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af): + _af(af), + _type(0) {} + + virtual ~ConstAttributeFunctorArrayVisitor() {} + + virtual void apply(const ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + virtual void apply(const Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } + + + inline void applyArray(Drawable::AttributeType type,const Array* array) + { + if (array) + { + _type = type; + array->accept(*this); + } + } + +protected: + + ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; } + + Drawable::ConstAttributeFunctor& _af; + Drawable::AttributeType _type; +}; } diff --git a/include/osg/GLDefines b/include/osg/GLDefines index 1fb8be64a..5f903375c 100644 --- a/include/osg/GLDefines +++ b/include/osg/GLDefines @@ -177,12 +177,19 @@ typedef char GLchar; #define GL_FRAMEBUFFER_SRGB 0x8DB9 #endif -// EXT_geometry_shader4 +#ifndef EXT_geometry_shader4 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#endif + #ifndef GL_VERSION_3_2 #define GL_GEOMETRY_SHADER 0x8DD9 -#define GL_GEOMETRY_VERTICES_OUT 0x8DDA -#define GL_GEOMETRY_INPUT_TYPE 0x8DDB -#define GL_GEOMETRY_OUTPUT_TYPE 0x8DDC +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 #define GL_MAX_GEOMETRY_VARYING_COMPONENTS 0x8DDD #define GL_MAX_VERTEX_VARYING_COMPONENTS 0x8DDE @@ -493,7 +500,7 @@ typedef char GLchar; #endif #ifndef GL_VERSION_4_3 -#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000 +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 #define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 #define GL_SHADER_STORAGE_BUFFER 0x90D2 #define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 diff --git a/include/osg/Geometry b/include/osg/Geometry index f1ab73537..1dfa83054 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -26,6 +26,7 @@ namespace osg { + class OSG_EXPORT Geometry : public Drawable { public: diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index 81794f1bd..b9168add9 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -389,6 +389,7 @@ class DrawElements : public PrimitiveSet /** Get the const ElementBufferObject. If no EBO is assigned returns NULL*/ inline const osg::ElementBufferObject* getElementBufferObject() const { return dynamic_cast(_bufferObject.get()); } + virtual GLenum getDataType() = 0; virtual void resizeElements(unsigned int numIndices) = 0; virtual void reserveElements(unsigned int numIndices) = 0; virtual void setElement(unsigned int, unsigned int) = 0; @@ -446,6 +447,7 @@ class OSG_EXPORT DrawElementsUByte : public DrawElements, public VectorGLubyte virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); + virtual GLenum getDataType() { return GL_UNSIGNED_BYTE; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } @@ -509,6 +511,7 @@ class OSG_EXPORT DrawElementsUShort : public DrawElements, public VectorGLushort virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); + virtual GLenum getDataType() { return GL_UNSIGNED_SHORT; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } @@ -572,6 +575,7 @@ class OSG_EXPORT DrawElementsUInt : public DrawElements, public VectorGLuint virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); + virtual GLenum getDataType() { return GL_UNSIGNED_INT; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } diff --git a/include/osg/Program b/include/osg/Program index e1c669974..2f1a1fc68 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -151,6 +151,13 @@ class OSG_EXPORT Program : public osg::StateAttribute /** Get TransformFeedBack Mode. */ GLenum getTransformFeedBackMode() const {return _feedbackmode;} + /** Experimental. */ + void setShaderDefines(const ShaderDefines& shaderDefs) { _shaderDefines = shaderDefs; } + ShaderDefines& getShaderDefines() { return _shaderDefines; } + const ShaderDefines& getShaderDefines() const { return _shaderDefines; } + + + /** Simple class for wrapping up the data used in glProgramBinary and glGetProgramBinary. * On the first run of your application Programs should be assigned an empty ProgramBinary. * Before your application exits it should retrieve the program binary via @@ -245,8 +252,8 @@ class OSG_EXPORT Program : public osg::StateAttribute }; typedef std::map< unsigned int, ActiveVarInfo > ActiveUniformMap; typedef std::map< std::string, ActiveVarInfo > ActiveVarInfoMap; - const ActiveUniformMap& getActiveUniforms(unsigned int contextID) const; - const ActiveVarInfoMap& getActiveAttribs(unsigned int contextID) const; + //const ActiveUniformMap& getActiveUniforms(unsigned int contextID) const; + //const ActiveVarInfoMap& getActiveAttribs(unsigned int contextID) const; struct UniformBlockInfo { UniformBlockInfo() : _index(GL_INVALID_INDEX), _size(0) {} @@ -258,7 +265,8 @@ class OSG_EXPORT Program : public osg::StateAttribute GLsizei _size; }; typedef std::map UniformBlockMap; - const UniformBlockMap& getUniformBlocks(unsigned contextID) const; + + //const UniformBlockMap& getUniformBlocks(unsigned contextID) const; public: // make PerContextProgram a friend to allow it access Program's protected @@ -275,6 +283,9 @@ class OSG_EXPORT Program : public osg::StateAttribute GLuint getHandle() const {return _glProgramHandle;} + void setDefineString(const std::string& defStr) { _defineStr = defStr; } + const std::string& getDefineString() const { return _defineStr; } + void requestLink(); virtual void linkProgram(osg::State& state); virtual bool validateProgram(); @@ -359,8 +370,13 @@ class OSG_EXPORT Program : public osg::StateAttribute const Program* _program; /** Pointer to this context's extension functions */ osg::ref_ptr _extensions; + /** Handle to the actual OpenGL glProgram */ GLuint _glProgramHandle; + + /** Define string passed on to Shaders to help configure them.*/ + std::string _defineStr; + /** Does our glProgram need to be linked? */ bool _needsLink; /** Is our glProgram successfully linked? */ @@ -391,15 +407,33 @@ class OSG_EXPORT Program : public osg::StateAttribute PerContextProgram& operator=(const PerContextProgram&); // disallowed }; + struct OSG_EXPORT ProgramObjects : public osg::Referenced + { + typedef std::vector< osg::ref_ptr > PerContextPrograms; + + ProgramObjects(const Program* program, unsigned int contextID); + + unsigned int _contextID; + const Program* _program; + mutable PerContextPrograms _perContextPrograms; + + PerContextProgram* getPCP(const std::string& defineStr) const; + PerContextProgram* createPerContextProgram(const std::string& defineStr); + void requestLink(); + void addShaderToAttach(Shader* shader); + void addShaderToDetach(Shader* shader); + bool getGlProgramInfoLog(std::string& log) const; + }; + /** Get the PCP for a particular GL context */ - PerContextProgram* getPCP(unsigned int contextID) const; + PerContextProgram* getPCP(State& state) const; protected: /*methods*/ virtual ~Program(); protected: /*data*/ - mutable osg::buffered_value< osg::ref_ptr > _pcpList; + mutable osg::buffered_value< osg::ref_ptr > _pcpList; AttribBindingList _attribBindingList; FragDataBindingList _fragDataBindingList; UniformBlockBindingList _uniformBlockBindingList; @@ -424,6 +458,9 @@ class OSG_EXPORT Program : public osg::StateAttribute GLenum _feedbackmode; std::vector _feedbackout; + ShaderDefines _shaderDefines; + + private: Program& operator=(const Program&); // disallowed diff --git a/include/osg/Shader b/include/osg/Shader index 5da7159a0..9a23394dc 100644 --- a/include/osg/Shader +++ b/include/osg/Shader @@ -33,6 +33,9 @@ namespace osg { class Program; +// set of shader define strings that the shader is dependent upon. +typedef std::set ShaderDefines; + /** Simple class for wrapping up the data used in OpenGL ES 2's glShaderBinary calls. * ShaderBinary is set up with the binary data then assigned to one or more osg::Shader. */ class OSG_EXPORT ShaderBinary : public osg::Object @@ -131,6 +134,25 @@ class OSG_EXPORT Shader : public osg::Object inline const std::string& getShaderSource() const { return _shaderSource; } + enum ShaderDefinesMode + { + USE_SHADER_PRAGAMA, + USE_MANUAL_SETTINGS + }; + + void setShaderDefinesMode(ShaderDefinesMode sdm) { _shaderDefinesMode = sdm; } + ShaderDefinesMode getShaderDefinesMode() const { return _shaderDefinesMode; } + + + void setShaderDefines(const ShaderDefines& shaderDefs) { _shaderDefines = shaderDefs; } + ShaderDefines& getShaderDefines() { return _shaderDefines; } + const ShaderDefines& getShaderDefines() const { return _shaderDefines; } + + void setShaderRequirements(const ShaderDefines& shaderDefs) { _shaderRequirements = shaderDefs; } + ShaderDefines& getShaderRequirements() { return _shaderRequirements; } + const ShaderDefines& getShaderRequirements() const { return _shaderRequirements; } + + /** Set the Shader using a ShaderBinary. */ void setShaderBinary(ShaderBinary* shaderBinary) { _shaderBinary = shaderBinary; } @@ -183,14 +205,6 @@ class OSG_EXPORT Shader : public osg::Object /** If needed, compile the PCS's glShader */ void compileShader(osg::State& state) const; - /** For a given GL context, attach a glShader to a glProgram */ - void attachShader(unsigned int contextID, GLuint program) const; - - /** For a given GL context, detach a glShader to a glProgram */ - void detachShader(unsigned int contextID, GLuint program) const; - - /** Query InfoLog from a glShader */ - bool getGlShaderInfoLog(unsigned int contextID, std::string& log) const; /** Mark internal glShader for deletion. * Deletion requests are queued until they can be executed @@ -215,6 +229,9 @@ class OSG_EXPORT Shader : public osg::Object public: PerContextShader(const Shader* shader, unsigned int contextID); + void setDefineString(const std::string& defStr) { _defineStr = defStr; } + const std::string& getDefineString() const { return _defineStr; } + GLuint getHandle() const {return _glShaderHandle;} void requestCompile(); @@ -235,14 +252,22 @@ class OSG_EXPORT Shader : public osg::Object protected: /*data*/ /** Pointer to our parent osg::Shader */ const Shader* _shader; + /** Pointer to this context's extension functions. */ osg::ref_ptr _extensions; + /** Handle to the actual glShader. */ GLuint _glShaderHandle; + + /** Define string passed on to Shaders to help configure them.*/ + std::string _defineStr; + /** Does our glShader need to be recompiled? */ bool _needsCompile; + /** Is our glShader successfully compiled? */ bool _isCompiled; + const unsigned int _contextID; private: @@ -251,7 +276,23 @@ class OSG_EXPORT Shader : public osg::Object PerContextShader& operator=(const PerContextShader&); // disallowed }; - PerContextShader* getPCS(unsigned int contextID) const; + + struct OSG_EXPORT ShaderObjects : public osg::Referenced + { + typedef std::vector< osg::ref_ptr > PerContextShaders; + + ShaderObjects(const Shader* shader, unsigned int contextID); + + unsigned int _contextID; + const Shader* _shader; + mutable PerContextShaders _perContextShaders; + + PerContextShader* getPCS(const std::string& defineStr) const; + PerContextShader* createPerContextShader(const std::string& defineStr); + void requestCompile(); + }; + + PerContextShader* getPCS(osg::State& state) const; protected: /*methods*/ virtual ~Shader(); @@ -261,7 +302,11 @@ class OSG_EXPORT Shader : public osg::Object bool addProgramRef( osg::Program* program ); bool removeProgramRef( osg::Program* program ); - protected: /*data*/ + void _computeShaderDefines(); + void _parseShaderDefines(const std::string& str, ShaderDefines& defines); + + + protected: /*data*/ Type _type; std::string _shaderFileName; std::string _shaderSource; @@ -269,10 +314,15 @@ class OSG_EXPORT Shader : public osg::Object CodeInjectionMap _codeInjectionMap; + // ShaderDefines variables + ShaderDefinesMode _shaderDefinesMode; + ShaderDefines _shaderDefines; + ShaderDefines _shaderRequirements; + /** osg::Programs that this osg::Shader is attached to */ typedef std::set< osg::Program* > ProgramSet; ProgramSet _programSet; - mutable osg::buffered_value< osg::ref_ptr > _pcsList; + mutable osg::buffered_value< osg::ref_ptr > _pcsList; private: Shader& operator=(const Shader&); // disallowed diff --git a/include/osg/State b/include/osg/State index 7a15a106a..ae6181399 100644 --- a/include/osg/State +++ b/include/osg/State @@ -1588,21 +1588,54 @@ class OSG_EXPORT State : public Referenced UniformVec uniformVec; }; + struct DefineStack + { + typedef std::vector DefineVec; + + DefineStack() {} + + void print(std::ostream& fout) const; + + bool changed; + DefineVec defineVec; + }; + + struct DefineMap + { + DefineMap(): + changed(false) {} + + typedef std::map DefineStackMap; + DefineStackMap map; + bool changed; + StateSet::DefineList currentDefines; + + bool updateCurrentDefines(); + + }; + typedef std::map ModeMap; typedef std::vector TextureModeMapList; typedef std::map AttributeMap; typedef std::vector TextureAttributeMapList; - typedef std::map UniformMap; + typedef std::map UniformMap; - typedef std::vector > MatrixStack; - inline const ModeMap& getModeMap() const {return _modeMap;}; - inline const AttributeMap& getAttributeMap() const {return _attributeMap;}; - inline const UniformMap& getUniformMap() const {return _uniformMap;}; - inline const TextureModeMapList& getTextureModeMapList() const {return _textureModeMapList;}; - inline const TextureAttributeMapList& getTextureAttributeMapList() const {return _textureAttributeMapList;}; + typedef std::vector< ref_ptr > MatrixStack; + + inline const ModeMap& getModeMap() const {return _modeMap;} + inline const AttributeMap& getAttributeMap() const {return _attributeMap;} + inline const UniformMap& getUniformMap() const {return _uniformMap;} + inline DefineMap& getDefineMap() {return _defineMap;} + inline const DefineMap& getDefineMap() const {return _defineMap;} + inline const TextureModeMapList& getTextureModeMapList() const {return _textureModeMapList;} + inline const TextureAttributeMapList& getTextureAttributeMapList() const {return _textureAttributeMapList;} + + std::string getDefineString(const osg::ShaderDefines& shaderDefines); + bool supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements); + bool supportsShaderRequirement(const std::string& shaderRequirement); protected: @@ -1806,6 +1839,7 @@ class OSG_EXPORT State : public Referenced ModeMap _modeMap; AttributeMap _attributeMap; UniformMap _uniformMap; + DefineMap _defineMap; TextureModeMapList _textureModeMapList; TextureAttributeMapList _textureAttributeMapList; @@ -1865,18 +1899,22 @@ class OSG_EXPORT State : public Referenced inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList); inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList); inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList); + inline void pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList); inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList); inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList); inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList); + inline void popDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList); inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList); inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList); inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList); + inline void applyDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList); inline void applyModeMap(ModeMap& modeMap); inline void applyAttributeMap(AttributeMap& attributeMap); inline void applyUniformMap(UniformMap& uniformMap); + inline void applyUniformMap(DefineMap& defineMap); inline void applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList); inline void applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList); @@ -2042,6 +2080,44 @@ inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::Unifor } } +inline void State::pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList) +{ + for(StateSet::DefineList::const_iterator aitr=defineList.begin(); + aitr!=defineList.end(); + ++aitr) + { + // get the attribute stack for incoming type {aitr->first}. + DefineStack& ds = defineMap.map[aitr->first]; + DefineStack::DefineVec& dv = ds.defineVec; + if (dv.empty()) + { + // first pair so simply push incoming pair to back. + dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second)); + + ds.changed = true; + defineMap.changed = true; + } + else if ((ds.defineVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag + { + // push existing back since override keeps the previous value. + ds.defineVec.push_back(ds.defineVec.back()); + } + else + { + // no override on so simply push incoming pair to back. + dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second)); + + // if the back of the stack has changed since the last then mark it as changed. + bool changed = (dv[dv.size()-2].first==dv[dv.size()-1].first); + if (changed) + { + ds.changed = true; + defineMap.changed = true; + } + } + } +} + inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList) { for(StateSet::ModeList::const_iterator mitr=modeList.begin(); @@ -2089,6 +2165,28 @@ inline void State::popUniformList(UniformMap& uniformMap,const StateSet::Uniform } } +inline void State::popDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList) +{ + for(StateSet::DefineList::const_iterator aitr=defineList.begin(); + aitr!=defineList.end(); + ++aitr) + { + // get the attribute stack for incoming type {aitr->first}. + DefineStack& ds = defineMap.map[aitr->first]; + DefineStack::DefineVec& dv = ds.defineVec; + if (!dv.empty()) + { + // if the stack has less than 2 entries or new back vs old back are different then mark the DefineStack as changed + if ((dv.size()<2) || (dv[dv.size()-2].first!=dv.back().first)) + { + ds.changed = true; + defineMap.changed = true; + } + dv.pop_back(); + } + } +} + inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList) { StateSet::ModeList::const_iterator ds_mitr = modeList.begin(); @@ -2643,6 +2741,74 @@ inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::Unifo } +inline void State::applyDefineList(DefineMap& defineMap, const StateSet::DefineList& defineList) +{ + StateSet::DefineList::const_iterator dl_itr = defineList.begin(); + DefineMap::DefineStackMap::iterator dm_itr = defineMap.map.begin(); + + defineMap.changed = false; + defineMap.currentDefines.clear(); + + while (dm_itr!=defineMap.map.end() && dl_itr!=defineList.end()) + { + if (dm_itr->firstfirst) + { + DefineStack& ds = dm_itr->second; + DefineStack::DefineVec& dv = ds.defineVec; + if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back(); + + ++dm_itr; + } + else if (dl_itr->firstfirst) + { + if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second; + + ++dl_itr; + } + else + { + // this_mitr & ds_mitr refer to the same mode, check the override + // if any otherwise just apply the incoming mode. + + DefineStack& ds = dm_itr->second; + DefineStack::DefineVec& dv = ds.defineVec; + + if (!dv.empty() && (dv.back().second & StateAttribute::OVERRIDE)!=0 && !(dl_itr->second.second & StateAttribute::PROTECTED)) + { + // override is on, just treat as a normal apply on modes. + if ((dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back(); + } + else + { + // no override on or no previous entry, therefore consider incoming mode. + if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second; + } + + ++dm_itr; + ++dl_itr; + } + } + + // iterator over the remaining state modes to apply any previous changes. + for(; + dm_itr!=defineMap.map.end(); + ++dm_itr) + { + // note GLMode = this_mitr->first + DefineStack& ds = dm_itr->second; + DefineStack::DefineVec& dv = ds.defineVec; + if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back(); + } + + // iterator over the remaining incoming modes to apply any new mode. + for(; + dl_itr!=defineList.end(); + ++dl_itr) + { + if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second; + } +} + inline void State::applyModeMap(ModeMap& modeMap) { for(ModeMap::iterator mitr=modeMap.begin(); diff --git a/include/osg/StateSet b/include/osg/StateSet index 6dca8a69b..d68700e13 100644 --- a/include/osg/StateSet +++ b/include/osg/StateSet @@ -308,6 +308,35 @@ class OSG_EXPORT StateSet : public Object /** return the const list of all Uniforms contained in this const StateSet.*/ inline const UniformList& getUniformList() const { return _uniformList; } + + typedef std::pair DefinePair; + typedef std::map DefineList; + + /** Added define pass on to shaders that use utilize that define, as secified by the GLSL #pragma import_defines(..) and #pragam requires(..). */ + void setDefine(const std::string& defineName, StateAttribute::OverrideValue value=StateAttribute::ON); + + /** Added define with value to pass on to shaders that use utilize that define, as secified by the GLSL #pragma import_defines(..) and #pragam requires(..). */ + void setDefine(const std::string& defineName, const std::string& defineValue, StateAttribute::OverrideValue value=StateAttribute::ON); + + DefinePair* getDefinePair(const std::string& defineName) { DefineList::iterator itr = _defineList.find(defineName); return (itr!=_defineList.end()) ? &(itr->second) : 0; } + const DefinePair* getDefinePair(const std::string& defineName) const { DefineList::const_iterator itr = _defineList.find(defineName); return (itr!=_defineList.end()) ? &(itr->second) : 0; } + + + /** Remove define*/ + void removeDefine(const std::string& defineName); + + + /** Set the list of defines to pass on to shaders.*/ + void setDefineList(DefineList& dl) { _defineList = dl; } + + /** Get the list of defines to pass on to shaders.*/ + DefineList& getDefineList() { return _defineList; } + + /** Get the const list of defines to pass on to shaders.*/ + const DefineList& getDefineList() const { return _defineList; } + + + enum RenderingHint { DEFAULT_BIN = 0, @@ -474,6 +503,7 @@ class OSG_EXPORT StateSet : public Object TextureAttributeList _textureAttributeList; UniformList _uniformList; + DefineList _defineList; inline ModeList& getOrCreateTextureModeList(unsigned int unit) { diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index ef6f84bc5..36e167200 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -850,49 +850,6 @@ void Geometry::drawPrimitivesImplementation(RenderInfo& renderInfo) const } } -class AttributeFunctorArrayVisitor : public ArrayVisitor -{ - public: - - AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af): - _af(af), - _type(0) {} - - virtual ~AttributeFunctorArrayVisitor() {} - - virtual void apply(ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - - - inline void applyArray(Drawable::AttributeType type,Array* array) - { - if (array) - { - _type = type; - array->accept(*this); - } - } - - protected: - - AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; } - Drawable::AttributeFunctor& _af; - Drawable::AttributeType _type; -}; - void Geometry::accept(AttributeFunctor& af) { AttributeFunctorArrayVisitor afav(af); @@ -923,49 +880,6 @@ void Geometry::accept(AttributeFunctor& af) } } -class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor -{ - public: - - ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af): - _af(af), - _type(0) {} - - virtual ~ConstAttributeFunctorArrayVisitor() {} - - virtual void apply(const ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - virtual void apply(const Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } - - - inline void applyArray(Drawable::AttributeType type,const Array* array) - { - if (array) - { - _type = type; - array->accept(*this); - } - } - -protected: - - ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; } - - Drawable::ConstAttributeFunctor& _af; - Drawable::AttributeType _type; -}; void Geometry::accept(ConstAttributeFunctor& af) const { diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 1e4d038a1..6014f9e00 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -247,8 +247,6 @@ void Program::compileGLObjects( osg::State& state ) const { if( isFixedFunction() ) return; - const unsigned int contextID = state.getContextID(); - for( unsigned int i=0; i < _shaderList.size(); ++i ) { _shaderList[i]->compileShader( state ); @@ -256,7 +254,7 @@ void Program::compileGLObjects( osg::State& state ) const if(!_feedbackout.empty()) { - const PerContextProgram* pcp = getPCP(contextID); + const PerContextProgram* pcp = getPCP(state); const GLExtensions* extensions = state.get(); unsigned int numfeedback = _feedbackout.size(); @@ -272,7 +270,7 @@ void Program::compileGLObjects( osg::State& state ) const extensions->glTransformFeedbackVaryings( pcp->getHandle(), numfeedback, varyings, _feedbackmode); delete [] varyings; } - getPCP( contextID )->linkProgram(state); + getPCP( state )->linkProgram(state); } void Program::setThreadSafeRefUnref(bool threadSafe) @@ -292,6 +290,20 @@ void Program::dirtyProgram() { if( _pcpList[cxt].valid() ) _pcpList[cxt]->requestLink(); } + + // update list of defines required. + _shaderDefines.clear(); + for(ShaderList::iterator itr = _shaderList.begin(); + itr != _shaderList.end(); + ++itr) + { + Shader* shader = itr->get(); + ShaderDefines& sd = shader->getShaderDefines(); + _shaderDefines.insert(sd.begin(), sd.end()); + + ShaderDefines& sr = shader->getShaderRequirements(); + _shaderDefines.insert(sr.begin(), sr.end()); + } } @@ -376,14 +388,17 @@ void Program::setParameter( GLenum pname, GLint value ) { switch( pname ) { + case GL_GEOMETRY_VERTICES_OUT: case GL_GEOMETRY_VERTICES_OUT_EXT: _geometryVerticesOut = value; dirtyProgram(); break; + case GL_GEOMETRY_INPUT_TYPE: case GL_GEOMETRY_INPUT_TYPE_EXT: _geometryInputType = value; dirtyProgram(); // needed? break; + case GL_GEOMETRY_OUTPUT_TYPE: case GL_GEOMETRY_OUTPUT_TYPE_EXT: _geometryOutputType = value; //dirtyProgram(); // needed? @@ -401,9 +416,15 @@ GLint Program::getParameter( GLenum pname ) const { switch( pname ) { - case GL_GEOMETRY_VERTICES_OUT_EXT: return _geometryVerticesOut; - case GL_GEOMETRY_INPUT_TYPE_EXT: return _geometryInputType; - case GL_GEOMETRY_OUTPUT_TYPE_EXT: return _geometryOutputType; + case GL_GEOMETRY_VERTICES_OUT: + case GL_GEOMETRY_VERTICES_OUT_EXT: + return _geometryVerticesOut; + case GL_GEOMETRY_INPUT_TYPE: + case GL_GEOMETRY_INPUT_TYPE_EXT: + return _geometryInputType; + case GL_GEOMETRY_OUTPUT_TYPE: + case GL_GEOMETRY_OUTPUT_TYPE_EXT: + return _geometryOutputType; } OSG_WARN << "getParameter invalid param " << pname << std::endl; return 0; @@ -464,7 +485,6 @@ void Program::removeBindUniformBlock(const std::string& name) #include void Program::apply( osg::State& state ) const { - const unsigned int contextID = state.getContextID(); const GLExtensions* extensions = state.get(); if( ! extensions->isGlslSupported ) return; @@ -475,7 +495,66 @@ void Program::apply( osg::State& state ) const return; } - PerContextProgram* pcp = getPCP( contextID ); +#if 0 + State::DefineMap& defMap = state.getDefineMap(); + + OSG_NOTICE<<"Program::apply() defMap.changed="<second; + OSG_NOTICE<<" define ["<first<<"] ds.changed="<second; + shaderDefineStr += "#define "; + shaderDefineStr += itr->first; + if (itr->second.first.empty()) + { + shaderDefineStr += "\n"; + } + else + { + shaderDefineStr += " "; + shaderDefineStr += itr->second.first; + shaderDefineStr += "\n"; + } + OSG_NOTICE<<" active-define = ["<first<<"], value="<second.first<<", overridevalue = ["<second.second<<"]"<< std::endl; + } + + OSG_NOTICE<<"FullShaderDefineStr={"<needsLink() ) compileGLObjects( state ); if( pcp->isLinked() ) { @@ -497,20 +576,102 @@ void Program::apply( osg::State& state ) const } -Program::PerContextProgram* Program::getPCP(unsigned int contextID) const +Program::ProgramObjects::ProgramObjects(const osg::Program* program, unsigned int contextID): + _contextID(contextID), + _program(program) { - if( ! _pcpList[contextID].valid() ) - { - _pcpList[contextID] = new PerContextProgram( this, contextID ); +} - // attach all PCSs to this new PCP - for( unsigned int i=0; i < _shaderList.size(); ++i ) + +Program::PerContextProgram* Program::ProgramObjects::getPCP(const std::string& defineStr) const +{ + for(PerContextPrograms::const_iterator itr = _perContextPrograms.begin(); + itr != _perContextPrograms.end(); + ++itr) + { + if ((*itr)->getDefineString()==defineStr) { - _pcpList[contextID]->addShaderToAttach( _shaderList[i].get() ); + // OSG_NOTICE<<"Returning PCP "<get()<<" DefineString = "<<(*itr)->getDefineString()<get(); } } + return 0; +} - return _pcpList[contextID].get(); +Program::PerContextProgram* Program::ProgramObjects::createPerContextProgram(const std::string& defineStr) +{ + Program::PerContextProgram* pcp = new PerContextProgram( _program, _contextID ); + _perContextPrograms.push_back( pcp ); + pcp->setDefineString(defineStr); + // OSG_NOTICE<<"Creating PCP "<getDefineString()<<"]"<requestLink(); + } +} + +void Program::ProgramObjects::addShaderToAttach(Shader* shader) +{ + for(PerContextPrograms::iterator itr = _perContextPrograms.begin(); + itr != _perContextPrograms.end(); + ++itr) + { + (*itr)->addShaderToAttach(shader); + } +} + +void Program::ProgramObjects::addShaderToDetach(Shader* shader) +{ + for(PerContextPrograms::iterator itr = _perContextPrograms.begin(); + itr != _perContextPrograms.end(); + ++itr) + { + (*itr)->addShaderToDetach(shader); + } +} + + +bool Program::ProgramObjects::getGlProgramInfoLog(std::string& log) const +{ + bool result = false; + for(PerContextPrograms::const_iterator itr = _perContextPrograms.begin(); + itr != _perContextPrograms.end(); + ++itr) + { + result = (*itr)->getInfoLog( log ) | result; + } + return result; +} + +Program::PerContextProgram* Program::getPCP(State& state) const +{ + unsigned int contextID = state.getContextID(); + const std::string defineStr = state.getDefineString(getShaderDefines()); + + if( ! _pcpList[contextID].valid() ) + { + _pcpList[contextID] = new ProgramObjects( this, contextID ); + } + + Program::PerContextProgram* pcp = _pcpList[contextID]->getPCP(defineStr); + if (pcp) return pcp; + + pcp = _pcpList[contextID]->createPerContextProgram(defineStr); + + // attach all PCSs to this new PCP + for( unsigned int i=0; i < _shaderList.size(); ++i ) + { + pcp->addShaderToAttach( _shaderList[i].get() ); + } + + return pcp; } @@ -525,9 +686,11 @@ bool Program::isFixedFunction() const bool Program::getGlProgramInfoLog(unsigned int contextID, std::string& log) const { - return getPCP( contextID )->getInfoLog( log ); + if (contextID<_pcpList.size()) return (_pcpList[ contextID ])->getGlProgramInfoLog( log ); + else return false; } +#if 0 const Program::ActiveUniformMap& Program::getActiveUniforms(unsigned int contextID) const { return getPCP( contextID )->getActiveUniforms(); @@ -542,6 +705,7 @@ const Program::UniformBlockMap& Program::getUniformBlocks(unsigned contextID) co { return getPCP( contextID )->getUniformBlocks(); } +#endif /////////////////////////////////////////////////////////////////////////// // osg::Program::PerContextProgram @@ -603,19 +767,20 @@ void Program::PerContextProgram::linkProgram(osg::State& state) _loadedBinary = _isLinked = (linked == GL_TRUE); } + if (!_loadedBinary && _extensions->isGeometryShader4Supported) + { + _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_VERTICES_OUT_EXT, _program->_geometryVerticesOut ); + _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType ); + _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType ); + } + if (!_loadedBinary) { - if (_extensions->isGeometryShader4Supported) - { - _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_VERTICES_OUT_EXT, _program->_geometryVerticesOut ); - _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType ); - _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType ); - } - // Detach removed shaders for( unsigned int i=0; i < _shadersToDetach.size(); ++i ) { - _shadersToDetach[i]->detachShader( _contextID, _glProgramHandle ); + Shader::PerContextShader* pcs = _shadersToDetach[i]->getPCS(state); + if (pcs) _extensions->glDetachShader( _glProgramHandle, pcs->getHandle() ); } } _shadersToDetach.clear(); @@ -625,9 +790,12 @@ void Program::PerContextProgram::linkProgram(osg::State& state) // Attach new shaders for( unsigned int i=0; i < _shadersToAttach.size(); ++i ) { - _shadersToAttach[i]->attachShader( _contextID, _glProgramHandle ); + Shader::PerContextShader* pcs = _shadersToAttach[i]->getPCS(state); + if (pcs) _extensions->glAttachShader( _glProgramHandle, pcs->getHandle() ); } } + //state.checkGLErrors("After attaching shaders."); + _shadersToAttach.clear(); _uniformInfoMap.clear(); @@ -909,6 +1077,10 @@ void Program::PerContextProgram::linkProgram(osg::State& state) delete [] name; } OSG_INFO << std::endl; + + + //state.checkGLErrors("After Program::PerContextProgram::linkProgram."); + } bool Program::PerContextProgram::validateProgram() diff --git a/src/osg/Shader.cpp b/src/osg/Shader.cpp index a07a5af72..b9896ab28 100644 --- a/src/osg/Shader.cpp +++ b/src/osg/Shader.cpp @@ -214,19 +214,22 @@ void Shader::discardDeletedGlShaders(unsigned int contextID) /////////////////////////////////////////////////////////////////////////// Shader::Shader(Type type) : - _type(type) + _type(type), + _shaderDefinesMode(USE_SHADER_PRAGAMA) { } Shader::Shader(Type type, const std::string& source) : - _type(type) + _type(type), + _shaderDefinesMode(USE_SHADER_PRAGAMA) { setShaderSource( source); } Shader::Shader(Type type, ShaderBinary* shaderBinary) : _type(type), - _shaderBinary(shaderBinary) + _shaderBinary(shaderBinary), + _shaderDefinesMode(USE_SHADER_PRAGAMA) { } @@ -237,7 +240,8 @@ Shader::Shader(const Shader& rhs, const osg::CopyOp& copyop): _shaderFileName(rhs._shaderFileName), _shaderSource(rhs._shaderSource), _shaderBinary(rhs._shaderBinary), - _codeInjectionMap(rhs._codeInjectionMap) + _codeInjectionMap(rhs._codeInjectionMap), + _shaderDefinesMode(rhs._shaderDefinesMode) { } @@ -283,6 +287,9 @@ int Shader::compare(const Shader& rhs) const void Shader::setShaderSource( const std::string& sourceText ) { _shaderSource = sourceText; + + _computeShaderDefines(); + dirtyShader(); } @@ -365,12 +372,55 @@ void Shader::releaseGLObjects(osg::State* state) const void Shader::compileShader( osg::State& state ) const { - PerContextShader* pcs = getPCS( state.getContextID() ); + PerContextShader* pcs = getPCS( state ); if( pcs ) pcs->compileShader( state ); } -Shader::PerContextShader* Shader::getPCS(unsigned int contextID) const +Shader::ShaderObjects::ShaderObjects(const osg::Shader* shader, unsigned int contextID): + _contextID(contextID), + _shader(shader) +{ +} + + +Shader::PerContextShader* Shader::ShaderObjects::getPCS(const std::string& defineStr) const +{ + for(PerContextShaders::const_iterator itr = _perContextShaders.begin(); + itr != _perContextShaders.end(); + ++itr) + { + if ((*itr)->getDefineString()==defineStr) + { + // OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' returning PCS "<get()<<" DefineString = "<<(*itr)->getDefineString()<get(); + } + } + // OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' returning NULL"<setDefineString(defineStr); + // OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' Creating PCS "<getDefineString()<<"]"<requestCompile(); + } +} + + +Shader::PerContextShader* Shader::getPCS(osg::State& state) const { if( getType() == UNDEFINED ) { @@ -378,31 +428,28 @@ Shader::PerContextShader* Shader::getPCS(unsigned int contextID) const return 0; } + if (!state.supportsShaderRequirements(_shaderRequirements)) + { + // OSG_NOTICE<<"Shader not supported "<<_shaderRequirements.size()<getPCS(defineStr); + if (pcs) return pcs; -void Shader::attachShader(unsigned int contextID, GLuint program) const -{ - PerContextShader* pcs = getPCS( contextID ); - if( pcs ) pcs->attachShader( program ); -} + if (state.supportsShaderRequirements(_shaderRequirements)) + { + pcs = _pcsList[contextID]->createPerContextShader(defineStr); + } -void Shader::detachShader(unsigned int contextID, GLuint program) const -{ - PerContextShader* pcs = getPCS( contextID ); - if( pcs ) pcs->detachShader( program ); -} - - -bool Shader::getGlShaderInfoLog(unsigned int contextID, std::string& log) const -{ - PerContextShader* pcs = getPCS( contextID ); - return (pcs) ? pcs->getInfoLog( log ) : false; + return pcs; } @@ -577,8 +624,21 @@ void Shader::PerContextShader::compileShader(osg::State& state) } GLint compiled = GL_FALSE; - const GLchar* sourceText = reinterpret_cast(source.c_str()); - _extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL ); + + // OSG_NOTICE<<"Compiling PerContextShader "<getUniformList()); + + pushDefineList(_defineMap,dstate->getDefineList()); } // OSG_NOTICE<<"State::pushStateSet()"<<_stateStateStack.size()<getUniformList()); + popDefineList(_defineMap,dstate->getDefineList()); + } // remove the top draw state from the stack. @@ -513,6 +517,7 @@ void State::apply(const StateSet* dstate) const Program::PerContextProgram* previousLastAppliedProgramObject = _lastAppliedProgramObject; applyModeList(_modeMap,dstate->getModeList()); + applyDefineList(_defineMap, dstate->getDefineList()); applyAttributeList(_attributeMap,dstate->getAttributeList()); if (_shaderCompositionEnabled) @@ -617,7 +622,7 @@ void State::applyShaderComposition() if (_currentShaderCompositionProgram) { - Program::PerContextProgram* pcp = _currentShaderCompositionProgram->getPCP(_contextID); + Program::PerContextProgram* pcp = _currentShaderCompositionProgram->getPCP(*this); if (_lastAppliedProgramObject != pcp) applyAttribute(_currentShaderCompositionProgram); } } @@ -1284,23 +1289,24 @@ bool State::checkGLErrors(const char* str) const GLenum errorNo = glGetError(); if (errorNo!=GL_NO_ERROR) { + osg::NotifySeverity notifyLevel = NOTICE; // WARN; const char* error = (char*)gluErrorString(errorNo); if (error) { - OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error '" << error<<"'"; + OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error '" << error<<"'"; } else { - OSG_NOTIFY(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec; + OSG_NOTIFY(notifyLevel)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec; } if (str) { - OSG_NOTIFY(WARN)<<" at "<first; + if (cd_itr->second.first.empty()) + { + shaderDefineStr += "\n"; + } + else + { + shaderDefineStr += " "; + shaderDefineStr += cd_itr->second.first; + shaderDefineStr += "\n"; + } + + ++sd_itr; + ++cd_itr; + } + } + return shaderDefineStr; +} + +bool State::supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements) +{ + if (shaderRequirements.empty()) return true; + + if (_defineMap.changed) _defineMap.updateCurrentDefines(); + + const StateSet::DefineList& currentDefines = _defineMap.currentDefines; + for(ShaderDefines::const_iterator sr_itr = shaderRequirements.begin(); + sr_itr != shaderRequirements.end(); + ++sr_itr) + { + if (currentDefines.find(*sr_itr)==currentDefines.end()) return false; + } + return true; +} + +bool State::supportsShaderRequirement(const std::string& shaderRequirement) +{ + if (_defineMap.changed) _defineMap.updateCurrentDefines(); + const StateSet::DefineList& currentDefines = _defineMap.currentDefines; + return (currentDefines.find(shaderRequirement)!=currentDefines.end()); +} diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 16defaa33..ae8bf31bd 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -178,6 +178,8 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop), } } + _defineList = rhs._defineList; + _renderingHint = rhs._renderingHint; _binMode = rhs._binMode; @@ -1129,6 +1131,27 @@ const StateSet::RefUniformPair* StateSet::getUniformPair(const std::string& name else return 0; } +void StateSet::setDefine(const std::string& defineName, StateAttribute::OverrideValue value) +{ + DefinePair& dp = _defineList[defineName]; + dp.first = ""; + dp.second = value; +} + +void StateSet::setDefine(const std::string& defineName, const std::string& defineValue, StateAttribute::OverrideValue value) +{ + DefinePair& dp = _defineList[defineName]; + dp.first = defineValue; + dp.second = value; +} + +void StateSet::removeDefine(const std::string& defineName) +{ + DefineList::iterator itr = _defineList.find(defineName); + if (itr != _defineList.end()) _defineList.erase(itr); +} + + void StateSet::setTextureMode(unsigned int unit,StateAttribute::GLMode mode, StateAttribute::GLModeValue value) { if (getTextureGLModeSet().isTextureMode(mode))