Introduced new shader composition approach that utilizes #pragma requires(), #pragma import_defines() and #ifdef in GLSL to enable multiple different versions of shaders based

on defines passed in from osg::StateSet::setDefine(..).



git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14681 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield
2015-02-10 17:04:02 +00:00
parent bb637e73f3
commit b90503fdf5
14 changed files with 910 additions and 175 deletions

View File

@@ -26,8 +26,6 @@
#include <map>
#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

View File

@@ -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;
};
}

View File

@@ -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

View File

@@ -26,6 +26,7 @@
namespace osg {
class OSG_EXPORT Geometry : public Drawable
{
public:

View File

@@ -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<const osg::ElementBufferObject*>(_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; }

View File

@@ -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<std::string, UniformBlockInfo> 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<GLExtensions> _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<PerContextProgram> > 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<PerContextProgram> > _pcpList;
mutable osg::buffered_value< osg::ref_ptr<ProgramObjects> > _pcpList;
AttribBindingList _attribBindingList;
FragDataBindingList _fragDataBindingList;
UniformBlockBindingList _uniformBlockBindingList;
@@ -424,6 +458,9 @@ class OSG_EXPORT Program : public osg::StateAttribute
GLenum _feedbackmode;
std::vector<std::string> _feedbackout;
ShaderDefines _shaderDefines;
private:
Program& operator=(const Program&); // disallowed

View File

@@ -33,6 +33,9 @@ namespace osg {
class Program;
// set of shader define strings that the shader is dependent upon.
typedef std::set<std::string> 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<osg::GLExtensions> _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<PerContextShader> > 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<PerContextShader> > _pcsList;
mutable osg::buffered_value< osg::ref_ptr<ShaderObjects> > _pcsList;
private:
Shader& operator=(const Shader&); // disallowed

View File

@@ -1588,21 +1588,54 @@ class OSG_EXPORT State : public Referenced
UniformVec uniformVec;
};
struct DefineStack
{
typedef std::vector<StateSet::DefinePair> DefineVec;
DefineStack() {}
void print(std::ostream& fout) const;
bool changed;
DefineVec defineVec;
};
struct DefineMap
{
DefineMap():
changed(false) {}
typedef std::map<std::string, DefineStack> DefineStackMap;
DefineStackMap map;
bool changed;
StateSet::DefineList currentDefines;
bool updateCurrentDefines();
};
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
typedef std::vector<ModeMap> TextureModeMapList;
typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
typedef std::vector<AttributeMap> TextureAttributeMapList;
typedef std::map<std::string,UniformStack> UniformMap;
typedef std::map<std::string, UniformStack> UniformMap;
typedef std::vector<ref_ptr<const Matrix> > 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<const Matrix> > 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->first<dl_itr->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();
++dm_itr;
}
else if (dl_itr->first<dm_itr->first)
{
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();

View File

@@ -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<std::string, StateAttribute::OverrideValue> DefinePair;
typedef std::map<std::string, DefinePair> 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)
{