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:
parent
bb637e73f3
commit
b90503fdf5
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
namespace osg {
|
||||
|
||||
|
||||
class OSG_EXPORT Geometry : public Drawable
|
||||
{
|
||||
public:
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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<GLExtensions>();
|
||||
|
||||
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 <iostream>
|
||||
void Program::apply( osg::State& state ) const
|
||||
{
|
||||
const unsigned int contextID = state.getContextID();
|
||||
const GLExtensions* extensions = state.get<GLExtensions>();
|
||||
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="<<defMap.changed<<std::endl;
|
||||
for(State::DefineMap::DefineStackMap::const_iterator itr = defMap.map.begin();
|
||||
itr != defMap.map.end();
|
||||
++itr)
|
||||
{
|
||||
const State::DefineStack& ds = itr->second;
|
||||
OSG_NOTICE<<" define ["<<itr->first<<"] ds.changed="<<ds.changed<<" ";
|
||||
if (ds.defineVec.empty())
|
||||
{
|
||||
OSG_NOTICE<<" DefineStack empty "<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
const StateSet::DefinePair& dp = ds.defineVec.back();
|
||||
OSG_NOTICE<<" value = ["<<dp.first<<"], overridevalue = ["<<dp.second<<"]"<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (defMap.changed) defMap.updateCurrentDefines();
|
||||
|
||||
std::string shaderDefineStr = state.getDefineString(getShaderDefines());
|
||||
OSG_NOTICE<<"TailoredShaderDefineStr={"<<std::endl;
|
||||
OSG_NOTICE<<shaderDefineStr;
|
||||
OSG_NOTICE<<"}"<<std::endl;
|
||||
|
||||
|
||||
shaderDefineStr.clear();
|
||||
const StateSet::DefineList& currentDefines = defMap.currentDefines;
|
||||
for(StateSet::DefineList::const_iterator itr = currentDefines.begin();
|
||||
itr != currentDefines.end();
|
||||
++itr)
|
||||
{
|
||||
const StateSet::DefinePair& dp = itr->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 = ["<<itr->first<<"], value="<<itr->second.first<<", overridevalue = ["<<itr->second.second<<"]"<< std::endl;
|
||||
}
|
||||
|
||||
OSG_NOTICE<<"FullShaderDefineStr={"<<std::endl;
|
||||
OSG_NOTICE<<shaderDefineStr;
|
||||
OSG_NOTICE<<"}"<<std::endl;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
PerContextProgram* pcp = getPCP( state );
|
||||
if( pcp->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 "<<itr->get()<<" DefineString = "<<(*itr)->getDefineString()<<std::endl;
|
||||
return itr->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 "<<pcp<<" PCP DefineString = ["<<pcp->getDefineString()<<"]"<<std::endl;
|
||||
return pcp;
|
||||
}
|
||||
|
||||
void Program::ProgramObjects::requestLink()
|
||||
{
|
||||
for(PerContextPrograms::iterator itr = _perContextPrograms.begin();
|
||||
itr != _perContextPrograms.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->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()
|
||||
|
@ -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 "<<itr->get()<<" DefineString = "<<(*itr)->getDefineString()<<std::endl;
|
||||
return itr->get();
|
||||
}
|
||||
}
|
||||
// OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' returning NULL"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Shader::PerContextShader* Shader::ShaderObjects::createPerContextShader(const std::string& defineStr)
|
||||
{
|
||||
Shader::PerContextShader* pcs = new PerContextShader( _shader, _contextID );
|
||||
_perContextShaders.push_back( pcs );
|
||||
pcs->setDefineString(defineStr);
|
||||
// OSG_NOTICE<<"ShaderPtr = "<<_shader<<" FileName = '"<<_shader->getFileName()<<"' Creating PCS "<<pcs<<" DefineString = ["<<pcs->getDefineString()<<"]"<<std::endl;
|
||||
return pcs;
|
||||
}
|
||||
|
||||
void Shader::ShaderObjects::requestCompile()
|
||||
{
|
||||
for(PerContextShaders::const_iterator itr = _perContextShaders.begin();
|
||||
itr != _perContextShaders.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->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()<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int contextID = state.getContextID();
|
||||
if( ! _pcsList[contextID].valid() )
|
||||
{
|
||||
_pcsList[contextID] = new PerContextShader( this, contextID );
|
||||
_pcsList[contextID] = new ShaderObjects( this, contextID );
|
||||
}
|
||||
return _pcsList[contextID].get();
|
||||
}
|
||||
|
||||
const std::string defineStr = state.getDefineString(getShaderDefines());
|
||||
PerContextShader* pcs = _pcsList[contextID]->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<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
|
||||
|
||||
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" ShaderDefine="<<getDefineString()<<std::endl;
|
||||
|
||||
if (_defineStr.empty())
|
||||
{
|
||||
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLchar* sourceText[2];
|
||||
sourceText[0] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
||||
sourceText[1] = reinterpret_cast<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL );
|
||||
}
|
||||
_extensions->glCompileShader( _glShaderHandle );
|
||||
_extensions->glGetShaderiv( _glShaderHandle, GL_COMPILE_STATUS, &compiled );
|
||||
|
||||
@ -621,3 +681,96 @@ void Shader::PerContextShader::detachShader(GLuint program) const
|
||||
{
|
||||
_extensions->glDetachShader( program, _glShaderHandle );
|
||||
}
|
||||
|
||||
void Shader::_parseShaderDefines(const std::string& str, ShaderDefines& defines)
|
||||
{
|
||||
std::string::size_type start_of_parameter = 0;
|
||||
do
|
||||
{
|
||||
// skip spaces, tabs, commans
|
||||
start_of_parameter = str.find_first_not_of(" \t,", start_of_parameter);
|
||||
if (start_of_parameter==std::string::npos) break;
|
||||
|
||||
// find end of the parameter
|
||||
std::string::size_type end_of_parameter = str.find_first_of(" \t,)", start_of_parameter);
|
||||
|
||||
if (end_of_parameter==std::string::npos) end_of_parameter = str.size();
|
||||
|
||||
std::string parameter = str.substr(start_of_parameter, end_of_parameter-start_of_parameter);
|
||||
|
||||
defines.insert(parameter);
|
||||
|
||||
start_of_parameter = end_of_parameter;
|
||||
|
||||
} while (start_of_parameter<str.size());
|
||||
}
|
||||
|
||||
void Shader::_computeShaderDefines()
|
||||
{
|
||||
if (_shaderDefinesMode==USE_MANUAL_SETTINGS) return;
|
||||
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
_shaderDefines.clear();
|
||||
_shaderRequirements.clear();
|
||||
|
||||
while ((pos = _shaderSource.find("#pragma", pos))!=std::string::npos)
|
||||
{
|
||||
// skip over #pragma characters
|
||||
pos += 7;
|
||||
std::string::size_type first_chararcter = _shaderSource.find_first_not_of(" \t", pos);
|
||||
std::string::size_type eol = _shaderSource.find_first_of("\n\r", pos);
|
||||
if (eol==std::string::npos) eol = _shaderSource.size();
|
||||
|
||||
// OSG_NOTICE<<"\nFound pragma line ["<<_shaderSource.substr(first_chararcter, eol-first_chararcter)<<"]"<<std::endl;
|
||||
|
||||
if (first_chararcter<eol)
|
||||
{
|
||||
std::string::size_type end_of_keyword = _shaderSource.find_first_of(" \t(", first_chararcter);
|
||||
|
||||
std::string keyword = _shaderSource.substr(first_chararcter, end_of_keyword-first_chararcter);
|
||||
|
||||
std::string::size_type open_brackets = _shaderSource.find_first_of("(", end_of_keyword);
|
||||
std::string::size_type close_brackets = _shaderSource.find_first_of(")", open_brackets);
|
||||
|
||||
if ((open_brackets!=std::string::npos) && (close_brackets!=std::string::npos) && (close_brackets<eol))
|
||||
{
|
||||
std::string str(_shaderSource, open_brackets+1, close_brackets-open_brackets-1);
|
||||
|
||||
// OSG_NOTICE<<" parameter str = ["<<str<<"]"<<std::endl;
|
||||
if (keyword == "import_defines") _parseShaderDefines(str, _shaderDefines);
|
||||
else if (keyword == "requires") _parseShaderDefines(str, _shaderRequirements);
|
||||
else {
|
||||
//OSG_NOTICE<<" keyword not matched ["<<keyword<<"]"<<std::endl;
|
||||
_parseShaderDefines(str, _shaderDefines);
|
||||
}
|
||||
#if 0
|
||||
for(ShaderDefines::iterator itr = _shaderDefines.begin();
|
||||
itr != _shaderDefines.end();
|
||||
++itr)
|
||||
{
|
||||
OSG_NOTICE<<" define ["<<*itr<<"]"<<std::endl;
|
||||
}
|
||||
|
||||
for(ShaderDefines::iterator itr = _shaderRequirements.begin();
|
||||
itr != _shaderRequirements.end();
|
||||
++itr)
|
||||
{
|
||||
OSG_NOTICE<<" requirements ["<<*itr<<"]"<<std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
OSG_NOTICE<<" Found keyword ["<<keyword<<"] but not matched ()\n"<<std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
pos = eol;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -338,6 +338,8 @@ void State::pushStateSet(const StateSet* dstate)
|
||||
}
|
||||
|
||||
pushUniformList(_uniformMap,dstate->getUniformList());
|
||||
|
||||
pushDefineList(_defineMap,dstate->getDefineList());
|
||||
}
|
||||
|
||||
// OSG_NOTICE<<"State::pushStateSet()"<<_stateStateStack.size()<<std::endl;
|
||||
@ -388,6 +390,8 @@ void State::popStateSet()
|
||||
|
||||
popUniformList(_uniformMap,dstate->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 "<<str<< std::endl;
|
||||
OSG_NOTIFY(notifyLevel)<<" at "<<str<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_NOTIFY(WARN)<<" in osg::State."<< std::endl;
|
||||
OSG_NOTIFY(notifyLevel)<<" in osg::State."<< std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1769,3 +1775,91 @@ void State::frameCompleted()
|
||||
//OSG_NOTICE<<"State::frameCompleted() setting time stamp. timestamp="<<timestamp<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool State::DefineMap::updateCurrentDefines()
|
||||
{
|
||||
if (changed)
|
||||
{
|
||||
currentDefines.clear();
|
||||
for(DefineStackMap::const_iterator itr = map.begin();
|
||||
itr != map.end();
|
||||
++itr)
|
||||
{
|
||||
const DefineStack::DefineVec& dv = itr->second.defineVec;
|
||||
if (!dv.empty())
|
||||
{
|
||||
const StateSet::DefinePair& dp = dv.back();
|
||||
if (dp.second & osg::StateAttribute::ON)
|
||||
{
|
||||
currentDefines[itr->first] = dp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string State::getDefineString(const osg::ShaderDefines& shaderDefines)
|
||||
{
|
||||
if (_defineMap.changed) _defineMap.updateCurrentDefines();
|
||||
|
||||
const StateSet::DefineList& currentDefines = _defineMap.currentDefines;
|
||||
|
||||
ShaderDefines::const_iterator sd_itr = shaderDefines.begin();
|
||||
StateSet::DefineList::const_iterator cd_itr = currentDefines.begin();
|
||||
|
||||
std::string shaderDefineStr;
|
||||
|
||||
while(sd_itr != shaderDefines.end() && cd_itr != currentDefines.end())
|
||||
{
|
||||
if ((*sd_itr) < cd_itr->first) ++sd_itr;
|
||||
else if (cd_itr->first < (*sd_itr)) ++cd_itr;
|
||||
else
|
||||
{
|
||||
const StateSet::DefinePair& dp = cd_itr->second;
|
||||
shaderDefineStr += "#define ";
|
||||
shaderDefineStr += cd_itr->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());
|
||||
}
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user