From Mike Weiblen, adding prelimimnary GL Shader Language support into core OSG lib.

with renaming and reordering by Robert Osfield,
This commit is contained in:
Robert Osfield
2005-02-24 13:33:35 +00:00
parent 164cb8216c
commit 5fbb1f11cd
9 changed files with 3861 additions and 4 deletions

View File

@@ -380,6 +380,10 @@ SOURCE=..\..\src\osg\PrimitiveSet.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Program.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Projection.cpp
# End Source File
# Begin Source File
@@ -400,6 +404,10 @@ SOURCE=..\..\src\osg\ShadeModel.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Shader.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\ShadowVolumeOccluder.cpp
# End Source File
# Begin Source File
@@ -484,6 +492,10 @@ SOURCE=..\..\src\osg\Transform.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Uniform.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\UnitTestFramework.cpp
# End Source File
# Begin Source File
@@ -837,6 +849,10 @@ SOURCE=..\..\Include\Osg\Projection
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Program
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Quat
# End Source File
# Begin Source File
@@ -857,6 +873,10 @@ SOURCE=..\..\Include\Osg\ShadeModel
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Shader
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\ShadowVolumeOccluder
# End Source File
# Begin Source File
@@ -949,6 +969,10 @@ SOURCE=..\..\Include\Osg\TriangleFunctor
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Uniform
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\UnitTestFramework
# End Source File
# Begin Source File

447
include/osg/Program Normal file
View File

@@ -0,0 +1,447 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: include/osg/Program
* author: Mike Weiblen 2005-02-20
*/
// NOTICE: This code is CLOSED during construction and/or renovation!
// It is in active development, so DO NOT yet use in application code.
// This notice will be removed when the code is open for business.
// For development plan and status see:
// http://www.openscenegraph.org/index.php?page=Community.DevelopmentWork
#ifndef OSG_PROGRAM
#define OSG_PROGRAM 1
#include <osg/State>
#include <osg/StateAttribute>
#include <osg/buffered_value>
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Referenced>
#include <osg/GL>
#include <osg/Uniform>
#include <string>
#include <vector>
namespace osg {
class SG_EXPORT GL2Extensions : public osg::Referenced
{
public:
GL2Extensions();
GL2Extensions(const GL2Extensions& rhs);
void lowestCommonDenominator(const GL2Extensions& rhs);
void setupGL2Extensions();
/** Does the GL driver support OpenGL Shading Language? */
bool isGlslSupported() const;
float getGlVersion() const { return _glVersion; }
float getLanguageVersion() const { return _glslLanguageVersion; }
void setShaderObjectsSupported(bool flag) { _isShaderObjectsSupported = flag; }
bool isShaderObjectsSupported() const { return _isShaderObjectsSupported; }
void setVertexShaderSupported(bool flag) { _isVertexShaderSupported = flag; }
bool isVertexShaderSupported() const { return _isVertexShaderSupported; }
void setFragmentShaderSupported(bool flag) { _isFragmentShaderSupported = flag; }
bool isFragmentShaderSupported() const { return _isFragmentShaderSupported; }
void setLanguage100Supported(bool flag) { _isLanguage100Supported = flag; }
bool isLanguage100Supported() const { return _isLanguage100Supported; }
/** Function to call to get the extension of a specified context.
* If the Exentsion object for that context has not yet been created then
* and the 'createIfNotInitalized' flag been set to false then returns NULL.
* If 'createIfNotInitalized' is true then the Extensions object is
* automatically created. However, in this case the extension object
* only be created with the graphics context associated with ContextID..*/
static GL2Extensions* Get(unsigned int contextID,bool createIfNotInitalized);
/** allows users to override the extensions across graphics contexts.
* typically used when you have different extensions supported across graphics pipes
* but need to ensure that they all use the same low common denominator extensions.*/
static void Set(unsigned int contextID, GL2Extensions* extensions);
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) const;
void glDrawBuffers(GLsizei n, const GLenum *bufs) const;
void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) const;
void glStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) const;
void glStencilMaskSeparate(GLenum face, GLuint mask) const;
void glAttachShader(GLuint program, GLuint shader) const;
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name) const;
void glCompileShader(GLuint shader) const;
GLuint glCreateProgram(void) const;
GLuint glCreateShader(GLenum type) const;
void glDeleteProgram(GLuint program) const;
void glDeleteShader(GLuint shader) const;
void glDetachShader(GLuint program, GLuint shader) const;
void glDisableVertexAttribArray(GLuint index) const;
void glEnableVertexAttribArray(GLuint index) const;
void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
void glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj) const;
GLint glGetAttribLocation(GLuint program, const GLchar *name) const;
void glGetProgramiv(GLuint program, GLenum pname, GLint *params) const;
void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) const;
void glGetShaderiv(GLuint shader, GLenum pname, GLint *params) const;
void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) const;
void glGetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) const;
GLint glGetUniformLocation(GLuint program, const GLchar *name) const;
void glGetUniformfv(GLuint program, GLint location, GLfloat *params) const;
void glGetUniformiv(GLuint program, GLint location, GLint *params) const;
void glGetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) const;
void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) const;
void glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) const;
void glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid* *pointer) const;
GLboolean glIsProgram(GLuint program) const;
GLboolean glIsShader(GLuint shader) const;
void glLinkProgram(GLuint program) const;
void glShaderSource(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length) const;
void glUseProgram(GLuint program) const;
void glUniform1f(GLint location, GLfloat v0) const;
void glUniform2f(GLint location, GLfloat v0, GLfloat v1) const;
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) const;
void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) const;
void glUniform1i(GLint location, GLint v0) const;
void glUniform2i(GLint location, GLint v0, GLint v1) const;
void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) const;
void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) const;
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform1iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform2iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform3iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform4iv(GLint location, GLsizei count, const GLint *value) const;
void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glValidateProgram(GLuint program) const;
void glVertexAttrib1d(GLuint index, GLdouble x) const;
void glVertexAttrib1dv(GLuint index, const GLdouble *v) const;
void glVertexAttrib1f(GLuint index, GLfloat x) const;
void glVertexAttrib1fv(GLuint index, const GLfloat *v) const;
void glVertexAttrib1s(GLuint index, GLshort x) const;
void glVertexAttrib1sv(GLuint index, const GLshort *v) const;
void glVertexAttrib2d(GLuint index, GLdouble x, GLdouble y) const;
void glVertexAttrib2dv(GLuint index, const GLdouble *v) const;
void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) const;
void glVertexAttrib2fv(GLuint index, const GLfloat *v) const;
void glVertexAttrib2s(GLuint index, GLshort x, GLshort y) const;
void glVertexAttrib2sv(GLuint index, const GLshort *v) const;
void glVertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z) const;
void glVertexAttrib3dv(GLuint index, const GLdouble *v) const;
void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) const;
void glVertexAttrib3fv(GLuint index, const GLfloat *v) const;
void glVertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z) const;
void glVertexAttrib3sv(GLuint index, const GLshort *v) const;
void glVertexAttrib4Nbv(GLuint index, const GLbyte *v) const;
void glVertexAttrib4Niv(GLuint index, const GLint *v) const;
void glVertexAttrib4Nsv(GLuint index, const GLshort *v) const;
void glVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) const;
void glVertexAttrib4Nubv(GLuint index, const GLubyte *v) const;
void glVertexAttrib4Nuiv(GLuint index, const GLuint *v) const;
void glVertexAttrib4Nusv(GLuint index, const GLushort *v) const;
void glVertexAttrib4bv(GLuint index, const GLbyte *v) const;
void glVertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) const;
void glVertexAttrib4dv(GLuint index, const GLdouble *v) const;
void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) const;
void glVertexAttrib4fv(GLuint index, const GLfloat *v) const;
void glVertexAttrib4iv(GLuint index, const GLint *v) const;
void glVertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) const;
void glVertexAttrib4sv(GLuint index, const GLshort *v) const;
void glVertexAttrib4ubv(GLuint index, const GLubyte *v) const;
void glVertexAttrib4uiv(GLuint index, const GLuint *v) const;
void glVertexAttrib4usv(GLuint index, const GLushort *v) const;
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) const;
// C++-friendly convenience wrapper methods
GLuint getCurrentProgram() const;
bool getProgramInfoLog( GLuint program, std::string& result ) const;
bool getShaderInfoLog( GLuint shader, std::string& result ) const;
protected:
~GL2Extensions() {}
float _glVersion;
float _glslLanguageVersion;
bool _isShaderObjectsSupported;
bool _isVertexShaderSupported;
bool _isFragmentShaderSupported;
bool _isLanguage100Supported;
void* _glBlendEquationSeparate;
void* _glDrawBuffers;
void* _glStencilOpSeparate;
void* _glStencilFuncSeparate;
void* _glStencilMaskSeparate;
void* _glAttachShader;
void* _glBindAttribLocation;
void* _glCompileShader;
void* _glCreateProgram;
void* _glCreateShader;
void* _glDeleteProgram;
void* _glDeleteShader;
void* _glDetachShader;
void* _glDisableVertexAttribArray;
void* _glEnableVertexAttribArray;
void* _glGetActiveAttrib;
void* _glGetActiveUniform;
void* _glGetAttachedShaders;
void* _glGetAttribLocation;
void* _glGetProgramiv;
void* _glGetProgramInfoLog;
void* _glGetShaderiv;
void* _glGetShaderInfoLog;
void* _glGetShaderSource;
void* _glGetUniformLocation;
void* _glGetUniformfv;
void* _glGetUniformiv;
void* _glGetVertexAttribdv;
void* _glGetVertexAttribfv;
void* _glGetVertexAttribiv;
void* _glGetVertexAttribPointerv;
void* _glIsProgram;
void* _glIsShader;
void* _glLinkProgram;
void* _glShaderSource;
void* _glUseProgram;
void* _glUniform1f;
void* _glUniform2f;
void* _glUniform3f;
void* _glUniform4f;
void* _glUniform1i;
void* _glUniform2i;
void* _glUniform3i;
void* _glUniform4i;
void* _glUniform1fv;
void* _glUniform2fv;
void* _glUniform3fv;
void* _glUniform4fv;
void* _glUniform1iv;
void* _glUniform2iv;
void* _glUniform3iv;
void* _glUniform4iv;
void* _glUniformMatrix2fv;
void* _glUniformMatrix3fv;
void* _glUniformMatrix4fv;
void* _glValidateProgram;
void* _glVertexAttrib1d;
void* _glVertexAttrib1dv;
void* _glVertexAttrib1f;
void* _glVertexAttrib1fv;
void* _glVertexAttrib1s;
void* _glVertexAttrib1sv;
void* _glVertexAttrib2d;
void* _glVertexAttrib2dv;
void* _glVertexAttrib2f;
void* _glVertexAttrib2fv;
void* _glVertexAttrib2s;
void* _glVertexAttrib2sv;
void* _glVertexAttrib3d;
void* _glVertexAttrib3dv;
void* _glVertexAttrib3f;
void* _glVertexAttrib3fv;
void* _glVertexAttrib3s;
void* _glVertexAttrib3sv;
void* _glVertexAttrib4Nbv;
void* _glVertexAttrib4Niv;
void* _glVertexAttrib4Nsv;
void* _glVertexAttrib4Nub;
void* _glVertexAttrib4Nubv;
void* _glVertexAttrib4Nuiv;
void* _glVertexAttrib4Nusv;
void* _glVertexAttrib4bv;
void* _glVertexAttrib4d;
void* _glVertexAttrib4dv;
void* _glVertexAttrib4f;
void* _glVertexAttrib4fv;
void* _glVertexAttrib4iv;
void* _glVertexAttrib4s;
void* _glVertexAttrib4sv;
void* _glVertexAttrib4ubv;
void* _glVertexAttrib4uiv;
void* _glVertexAttrib4usv;
void* _glVertexAttribPointer;
void* _glGetInfoLogARB;
void* _glGetObjectParameterivARB;
void* _glDeleteObjectARB;
void* _glGetHandleARB;
};
class Program;
typedef osg::ref_ptr<Program> ProgramPtr;
class Shader;
typedef osg::ref_ptr<Shader> ShaderPtr;
typedef std::vector< ShaderPtr > ShaderList;
///////////////////////////////////////////////////////////////////////////
/** osg::Program is an application-level abstraction of an OpenGL glProgram.
* It is an osg::StateAttribute that, when applied, will activate a
* glProgram for subsequent rendering.
* osg::Shaders containing the actual shader source code are
* attached to a Program, which will then manage the compilation,
* linking, and activation of the GLSL program.
* Program will automatically manage per-context instancing of the
* OpenGL objects, if that is necessary for a particular display
* configuration.
*/
class SG_EXPORT Program : public osg::StateAttribute
{
public:
Program();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
Program(const Program& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_StateAttribute(osg, Program, PROGRAM);
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
virtual int compare(const osg::StateAttribute& sa) const;
/** If enabled, activate our program in the GL pipeline,
* performing any rebuild operations that might be pending. */
virtual void apply(osg::State& state) const;
virtual void compileGLObjects(osg::State& state) const;
/** release OpenGL objects in specified graphics context if State
object is passed, otherwise release OpenGL objects for all graphics context if
State object pointer NULL.*/
virtual void releaseGLObjects(osg::State* state=0) const;
// data access methods.
/** Mark us as "dirty" and in need of relinking. */
void dirtyProgram();
/** Mark our attached Shaders as "dirty" and in need of recompilation. */
void dirtyShaders();
/** Attach a Shader to this Program */
void addShader( Shader* shader );
/** Mark internal GL glProgram for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteProgram(unsigned int contextID, GLuint program);
/** flush all the cached glPrograms which need to be deleted
* in the OpenGL context related to contextID.*/
static void flushDeletedGlslObjects(unsigned int contextID,double currentTime, double& availableTime);
/** An annotation/comment for use by the application */
void setComment( const std::string& comment ) { _comment = comment; }
void setComment( const char* comment ) { _comment = comment; }
const std::string& getComment() const { return _comment; }
/** should Uniform values be tested to avoid redundant setting? */
void setAvoidRedundantUniformSetting( bool flag ) { _avoidRedundantUniformSetting = flag; }
bool getAvoidRedundantUniformSetting() const { return _avoidRedundantUniformSetting; }
// TODO glBindAttribLocation
protected:
/** An OSG-internal encapsulation of glProgram's active uniforms */
class ActiveUniform : public osg::Referenced
{
public:
ActiveUniform( const GLchar* name, GLenum type );
protected:
virtual ~ActiveUniform() {}
Uniform::Value _value;
GLint _location;
private:
ActiveUniform(); // disallowed
};
typedef osg::ref_ptr< ActiveUniform > ActiveUniformPtr;
typedef std::vector< ActiveUniformPtr > ActiveUniformList;
protected:
/** PCPO is an OSG-internal encapsulation of glPrograms per-GL context. */
class PerContextProgObj : public osg::Referenced
{
public:
PerContextProgObj(const Program* program, unsigned int contextID);
PerContextProgObj(const PerContextProgObj& rhs);
const GLuint getHandle() {return _glProgramHandle;}
bool isDirty() const {return _dirty;}
void markAsDirty();
void linkProgram();
void useProgram() const;
void applyUniforms( osg::State& state ) const;
protected: /*methods*/
PerContextProgObj();
~PerContextProgObj();
protected: /*data*/
/** Pointer to our parent Program */
const Program* _program;
/** Pointer to this context's extension functions */
osg::ref_ptr<GL2Extensions> _extensions;
/** Handle to the actual OpenGL glProgram */
GLuint _glProgramHandle;
/** Do we need to be linked? */
bool _dirty;
/** Queue of UniformValues awaiting assignment */
const unsigned int _contextID;
/** List of PCPO's active uniforms */
ActiveUniformList _activeUniformList;
};
protected: /*methods*/
virtual ~Program();
/** Get the PCPO for a particular GL context */
PerContextProgObj* getPCPO(unsigned int contextID) const;
protected: /*data*/
bool _avoidRedundantUniformSetting;
std::string _comment;
ShaderList _shaderList;
mutable osg::buffered_value< osg::ref_ptr<PerContextProgObj> > _pcpoList;
private:
const Program& operator=(const Program&);
};
}
#endif
/*EOF*/

152
include/osg/Shader Normal file
View File

@@ -0,0 +1,152 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: include/osg/Program
* author: Mike Weiblen 2005-02-20
*/
// NOTICE: This code is CLOSED during construction and/or renovation!
// It is in active development, so DO NOT yet use in application code.
// This notice will be removed when the code is open for business.
// For development plan and status see:
// http://www.openscenegraph.org/index.php?page=Community.DevelopmentWork
#ifndef OSG_SHADER
#define OSG_SHADER 1
#include <osg/Program>
namespace osg {
///////////////////////////////////////////////////////////////////////////
/** osg::Shader is an application-level abstraction of an OpenGL glShader.
* It is a container to load the shader source code text and manage its
* compilation.
* A Shader may be attached to more than one osg::Program.
* Shader will automatically manage per-context instancing of the
* internal objects, if that is necessary for a particular display
* configuration.
*/
class SG_EXPORT Shader : public osg::Referenced
{
public:
enum Type {
VERTEX = GL_VERTEX_SHADER,
FRAGMENT = GL_FRAGMENT_SHADER,
};
Shader( Type type, const char* sourceText = 0 );
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
Shader(const Shader& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
int compare(const Shader& rhs) const;
// data access methods.
/** Load the Shader's source code text from a string. */
void setShaderSource( const char* sourceText );
/** Load the Shader's source code text from a file. */
bool loadShaderSourceFromFile( const char* fileName );
/** Query the shader's source code text */
inline const std::string& getShaderSource() const { return _shaderSource; }
/** Get the Shader type as an enum. */
inline Type getType() const { return _type; }
/** Get the Shader type as a descriptive string. */
const char* getTypename() const;
/** Mark us as "dirty" and in need of recompilation */
void dirtyShader();
/** Mark internal GL glShader for deletion.
* Deletion requests are queued until they can be executed
* in the proper GL context. */
static void deleteShader(unsigned int contextID, GLuint shader);
/** Perform a recompilation of all our PCSOs */
void compileShader(unsigned int contextID) const;
/** For a given GL context, attach a glShader to a glProgram */
void attachShader(unsigned int contextID, GLuint program) const;
/** An annotation/comment for use by the application */
void setComment( const std::string& comment ) { _comment = comment; }
void setComment( const char* comment ) { _comment = comment; }
const std::string& getComment() const { return _comment; };
protected:
/** PCSO is an OSG-internal encapsulation of glShader per-GL context. */
class PerContextShaderObj : public osg::Referenced
{
public:
PerContextShaderObj(const Shader* shader, unsigned int contextID);
PerContextShaderObj(const PerContextShaderObj& rhs);
const GLuint getHandle() {return _glShaderHandle;}
bool isDirty() const {return _dirty;}
void markAsDirty() {_dirty = true; }
void compileShader();
/** Attach our glShader to a glProgram */
void attachShader(GLuint program) const;
protected: /*methods*/
PerContextShaderObj();
~PerContextShaderObj();
protected: /*data*/
/** Pointer to our parent Shader */
const Shader* _shader;
/** Pointer to this context's extension functions. */
osg::ref_ptr<GL2Extensions> _extensions;
/** Handle to the actual glShader. */
GLuint _glShaderHandle;
/** Do we need to be recompiled? */
bool _dirty;
const unsigned int _contextID;
};
protected: /*methods*/
virtual ~Shader();
PerContextShaderObj* getPCSO(unsigned int contextID) const;
friend void Program::addShader( Shader* shader ); // to access addProgObjRef()
void addProgObjRef( Program* program );
protected: /*data*/
const Type _type;
std::string _comment;
std::string _shaderSource;
/** list of Programs that this Shader is attached to */
std::vector< ProgramPtr > _programList;
mutable osg::buffered_value< osg::ref_ptr<PerContextShaderObj> > _pcsoList;
private:
Shader(); // disallowed
Shader& operator=(const Shader&); // disallowed
};
}
#endif
/*EOF*/

View File

@@ -1,4 +1,4 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
@@ -175,8 +175,11 @@ class SG_EXPORT StateAttribute : public Object
VERTEX_PROGRAM,
REGISTER_COMBINERS,
// osgNVParse
PROGRAM,
PROGRAM_PARSER
PROGRAM_PARSER,
/// core GLSL
PROGRAM,
UNIFORM,
};
/** Simple pairing between an attribute type and the member within that attribute type group.*/

299
include/osg/Uniform Normal file
View File

@@ -0,0 +1,299 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: include/osg/Uniform
* author: Mike Weiblen 2005-02-20
*/
// NOTICE: This code is CLOSED during construction and/or renovation!
// It is in active development, so DO NOT yet use in application code.
// This notice will be removed when the code is open for business.
// For development plan and status see:
// http://www.openscenegraph.org/index.php?page=Community.DevelopmentWork
#ifndef OSG_UNIFORM
#define OSG_UNIFORM 1
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Matrix>
#include <osg/StateAttribute>
#include <string>
#ifndef GL_VERSION_2_0
#define GL_VERSION_2_0 1
#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#define GL_STENCIL_BACK_FUNC 0x8800
#define GL_STENCIL_BACK_FAIL 0x8801
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
#define GL_MAX_DRAW_BUFFERS 0x8824
#define GL_DRAW_BUFFER0 0x8825
#define GL_DRAW_BUFFER1 0x8826
#define GL_DRAW_BUFFER2 0x8827
#define GL_DRAW_BUFFER3 0x8828
#define GL_DRAW_BUFFER4 0x8829
#define GL_DRAW_BUFFER5 0x882A
#define GL_DRAW_BUFFER6 0x882B
#define GL_DRAW_BUFFER7 0x882C
#define GL_DRAW_BUFFER8 0x882D
#define GL_DRAW_BUFFER9 0x882E
#define GL_DRAW_BUFFER10 0x882F
#define GL_DRAW_BUFFER11 0x8830
#define GL_DRAW_BUFFER12 0x8831
#define GL_DRAW_BUFFER13 0x8832
#define GL_DRAW_BUFFER14 0x8833
#define GL_DRAW_BUFFER15 0x8834
#define GL_BLEND_EQUATION_ALPHA 0x883D
#define GL_POINT_SPRITE 0x8861
#define GL_COORD_REPLACE 0x8862
#define GL_MAX_VERTEX_ATTRIBS 0x8869
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#define GL_MAX_TEXTURE_COORDS 0x8871
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
#define GL_MAX_VARYING_FLOATS 0x8B4B
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
#define GL_SHADER_TYPE 0x8B4F
#define GL_FLOAT_VEC2 0x8B50
#define GL_FLOAT_VEC3 0x8B51
#define GL_FLOAT_VEC4 0x8B52
#define GL_INT_VEC2 0x8B53
#define GL_INT_VEC3 0x8B54
#define GL_INT_VEC4 0x8B55
#define GL_BOOL 0x8B56
#define GL_BOOL_VEC2 0x8B57
#define GL_BOOL_VEC3 0x8B58
#define GL_BOOL_VEC4 0x8B59
#define GL_FLOAT_MAT2 0x8B5A
#define GL_FLOAT_MAT3 0x8B5B
#define GL_FLOAT_MAT4 0x8B5C
#define GL_SAMPLER_1D 0x8B5D
#define GL_SAMPLER_2D 0x8B5E
#define GL_SAMPLER_3D 0x8B5F
#define GL_SAMPLER_CUBE 0x8B60
#define GL_SAMPLER_1D_SHADOW 0x8B61
#define GL_SAMPLER_2D_SHADOW 0x8B62
#define GL_DELETE_STATUS 0x8B80
#define GL_COMPILE_STATUS 0x8B81
#define GL_LINK_STATUS 0x8B82
#define GL_VALIDATE_STATUS 0x8B83
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_ATTACHED_SHADERS 0x8B85
#define GL_ACTIVE_UNIFORMS 0x8B86
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
#define GL_SHADER_SOURCE_LENGTH 0x8B88
#define GL_ACTIVE_ATTRIBUTES 0x8B89
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_CURRENT_PROGRAM 0x8B8D
#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
#define GL_LOWER_LEFT 0x8CA1
#define GL_UPPER_LEFT 0x8CA2
#define GL_STENCIL_BACK_REF 0x8CA3
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
typedef char GLchar;
#endif
namespace osg {
///////////////////////////////////////////////////////////////////////////
/** Uniform is an osg::StateAttribute to encapsulate glUniform values */
class SG_EXPORT Uniform : public StateAttribute
{
public:
class Value
{
public:
enum Type {
FLOAT = GL_FLOAT,
FLOAT_VEC2 = GL_FLOAT_VEC2,
FLOAT_VEC3 = GL_FLOAT_VEC3,
FLOAT_VEC4 = GL_FLOAT_VEC4,
INT = GL_INT,
INT_VEC2 = GL_INT_VEC2,
INT_VEC3 = GL_INT_VEC3,
INT_VEC4 = GL_INT_VEC4,
BOOL = GL_BOOL,
BOOL_VEC2 = GL_BOOL_VEC2,
BOOL_VEC3 = GL_BOOL_VEC3,
BOOL_VEC4 = GL_BOOL_VEC4,
FLOAT_MAT2 = GL_FLOAT_MAT2,
FLOAT_MAT3 = GL_FLOAT_MAT3,
FLOAT_MAT4 = GL_FLOAT_MAT4,
SAMPLER_1D = GL_SAMPLER_1D,
SAMPLER_2D = GL_SAMPLER_2D,
SAMPLER_3D = GL_SAMPLER_3D,
SAMPLER_CUBE = GL_SAMPLER_CUBE,
SAMPLER_1D_SHADOW = GL_SAMPLER_1D_SHADOW,
SAMPLER_2D_SHADOW = GL_SAMPLER_2D_SHADOW,
UNDEFINED = -1,
};
Value( const char* name, Type type );
Value( const Value& rhs );
/** Get the name of glUniform. */
const std::string& getName() const { return _name; }
/** Get the type of glUniform as enum. */
const Type getType() const { return _type; }
/** Return the name of a type as string. */
static const char* getTypename(Type t);
/** Does this Value contain real data? */
bool isValid() const { return _isValid; }
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
int compare(const Value& rhs) const;
bool isCompatibleType( Type t ) const;
/** assignment */
void set( float f );
void set( const osg::Vec2& v2 );
void set( const osg::Vec3& v3 );
void set( const osg::Vec4& v4 );
//TODO void set( const osg::Matrix2& m2 );
//TODO void set( const osg::Matrix3& m3 );
void set( const osg::Matrix& m4 );
void set( int i );
//TODO void set( int i0, int i1 );
//TODO void set( int i0, int i1, int i2 );
//TODO void set( int i0, int i1, int i2, int i3 );
//TODO void set( bool b );
//TODO void set( bool b0, bool b1 );
//TODO void set( bool b0, bool b1, bool b2 );
//TODO void set( bool b0, bool b1, bool b2, bool b3 );
protected:
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
int compareData(const Value& rhs) const;
void copyData(const Value& rhs);
protected:
const std::string _name;
const Type _type;
bool _isValid; // is _data valid?
union {
GLfloat f1; // float
GLfloat f2[2]; // vec2
GLfloat f3[3]; // vec3
GLfloat f4[4]; // vec4, mat2
GLfloat f9[9]; // mat3
GLfloat f16[16]; // mat4
GLint i1; // int, bool, sampler*
GLint i2[2]; // ivec2, bvec2
GLint i3[3]; // ivec3, bvec3
GLint i4[4]; // ivec4, bvec4
} _data;
private:
Value(); // disallowed
};
public:
Uniform();
Uniform( const char* name, Value::Type type );
/** convenient construction w/ assignment */
Uniform( const char* name, float f );
Uniform( const char* name, const osg::Vec2& v2 );
Uniform( const char* name, const osg::Vec3& v3 );
Uniform( const char* name, const osg::Vec4& v4 );
//TODO Uniform( const char* name, const osg::Matrix2& m2 );
//TODO Uniform( const char* name, const osg::Matrix3& m3 );
Uniform( const char* name, const osg::Matrix& m4 );
Uniform( const char* name, int i );
//TODO Uniform( const char* name, int i0, int i1 );
//TODO Uniform( const char* name, int i0, int i1, int i2 );
//TODO Uniform( const char* name, int i0, int i1, int i2, int i3 );
//TODO Uniform( const char* name, bool b );
//TODO Uniform( const char* name, bool b0, bool b1 );
//TODO Uniform( const char* name, bool b0, bool b1, bool b2 );
//TODO Uniform( const char* name, bool b0, bool b1, bool b2, bool b3 );
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
Uniform(const Uniform& gu,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
META_StateAttribute(osg, Uniform, UNIFORM);
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
virtual int compare(const StateAttribute& sa) const
{
// check if the types are equal and then create the rhs variable
// used by the COMPARE_StateAttribute_Parameter macros below.
COMPARE_StateAttribute_Types(Uniform,sa)
return _value.compare( rhs._value );
}
virtual void apply( State& state ) const;
/** assignment */
bool set( float f );
bool set( const osg::Vec2& v2 );
bool set( const osg::Vec3& v3 );
bool set( const osg::Vec4& v4 );
//TODO bool set( const osg::Matrix2& m2 );
//TODO bool set( const osg::Matrix3& m3 );
bool set( const osg::Matrix& m4 );
bool set( int i );
//TODO bool set( int i0, int i1 );
//TODO bool set( int i0, int i1, int i2 );
//TODO bool set( int i0, int i1, int i2, int i3 );
//TODO bool set( bool b );
//TODO bool set( bool b0, bool b1 );
//TODO bool set( bool b0, bool b1, bool b2 );
//TODO bool set( bool b0, bool b1, bool b2, bool b3 );
protected:
virtual ~Uniform() {}
bool isCompatibleType( Value::Type t ) const;
protected:
Value _value;
private:
Uniform& operator=(const Uniform&); // disallowed
};
}
#endif
/*EOF*/

View File

@@ -39,8 +39,10 @@ CXXFILES =\
FrameStamp.cpp\
FrontFace.cpp\
GLExtensions.cpp\
Geometry.cpp\
Geode.cpp\
Geometry.cpp\
Program.cpp\
Uniform.cpp\
Group.cpp\
dxtctool.cpp\
Image.cpp\
@@ -78,6 +80,7 @@ CXXFILES =\
Quat.cpp\
Referenced.cpp\
Sequence.cpp\
Shader.cpp\
ShadeModel.cpp\
ShadowVolumeOccluder.cpp\
Shape.cpp\

2163
src/osg/Program.cpp Normal file

File diff suppressed because it is too large Load Diff

239
src/osg/Shader.cpp Normal file
View File

@@ -0,0 +1,239 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/* file: src/osg/Program.cpp
* author: Mike Weiblen 2005-02-20
*/
// NOTICE: This code is CLOSED during construction and/or renovation!
// It is in active development, so DO NOT yet use in application code.
// This notice will be removed when the code is open for business.
// For development plan and status see:
// http://www.openscenegraph.org/index.php?page=Community.DevelopmentWork
#include <fstream>
#include <list>
#include <osg/Notify>
#include <osg/State>
#include <osg/Timer>
#include <osg/FrameStamp>
#include <osg/buffered_value>
#include <osg/ref_ptr>
#include <osg/Shader>
#include <osg/GLExtensions>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
using namespace osg;
typedef std::list<GLuint> GlShaderHandleList;
typedef std::map<unsigned int, GlShaderHandleList> DeletedGlShaderCache;
static OpenThreads::Mutex s_mutex_deletedGL2ShaderCache;
static DeletedGlShaderCache s_deletedGlShaderCache;
///////////////////////////////////////////////////////////////////////////
// osg::Shader
///////////////////////////////////////////////////////////////////////////
Shader::Shader(Type type, const char* sourceText) :
_type(type)
{
setShaderSource( sourceText );
}
Shader::Shader(const Shader& rhs, const osg::CopyOp& /*copyop*/):
Referenced( rhs ),
_type(rhs._type)
{
/*TODO*/
}
Shader::~Shader()
{
/*TODO*/
}
int Shader::compare(const Shader& rhs) const
{
if( this == &rhs ) return 0;
if( getComment() < rhs.getComment() ) return -1;
if( rhs.getComment() < getComment() ) return 1;
if( getShaderSource() < rhs.getShaderSource() ) return -1;
if( rhs.getShaderSource() < getShaderSource() ) return 1;
return 0;
}
void Shader::dirtyShader()
{
// mark each PCSO as needing a recompile
for( unsigned int cxt=0; cxt < _pcsoList.size(); ++cxt )
{
if( ! _pcsoList[cxt] ) continue;
PerContextShaderObj* pcso = _pcsoList[cxt].get();
pcso->markAsDirty();
}
// also mark-as-dirty the Programs we're attach to
for( unsigned int i=0; i < _programList.size(); ++i )
{
_programList[i]->dirtyProgram();
}
}
void Shader::setShaderSource( const char* sourceText )
{
_shaderSource = ( sourceText ? sourceText : "" );
dirtyShader();
}
bool Shader::loadShaderSourceFromFile( const char* fileName )
{
std::ifstream sourceFile;
sourceFile.open(fileName, std::ios::binary);
if(!sourceFile)
{
osg::notify(osg::WARN)<<"Error: can't open file \""<<fileName<<"\""<<std::endl;
return false;
}
osg::notify(osg::INFO)<<"Loading shader source file \""<<fileName<<"\""<<std::endl;
sourceFile.seekg(0, std::ios::end);
int length = sourceFile.tellg();
char *text = new char[length + 1];
sourceFile.seekg(0, std::ios::beg);
sourceFile.read(text, length);
sourceFile.close();
text[length] = '\0';
setShaderSource( text );
delete [] text;
return true;
}
const char* Shader::getTypename() const
{
switch( getType() )
{
case VERTEX: return "Vertex";
case FRAGMENT: return "Fragment";
default: return "UNDEFINED";
}
}
void Shader::compileShader( unsigned int contextID ) const
{
PerContextShaderObj* pcso = getPCSO( contextID );
if( pcso->isDirty() ) pcso->compileShader();
}
Shader::PerContextShaderObj* Shader::getPCSO(unsigned int contextID) const
{
if( ! _pcsoList[contextID].valid() )
{
_pcsoList[contextID] = new PerContextShaderObj( this, contextID );
}
return _pcsoList[contextID].get();
}
void Shader::attachShader(unsigned int contextID, GLuint program) const
{
getPCSO( contextID )->attachShader( program );
}
void Shader::addProgObjRef( Program* program )
{
_programList.push_back( program );
}
void Shader::deleteShader(unsigned int contextID, GLuint shader)
{
if( shader )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGL2ShaderCache);
// add shader to the cache for the appropriate context.
s_deletedGlShaderCache[contextID].push_back(shader);
}
}
///////////////////////////////////////////////////////////////////////////
// osg::Shader::PerContextShaderObj
// PCSO is the OSG abstraction of the per-context glShader
///////////////////////////////////////////////////////////////////////////
Shader::PerContextShaderObj::PerContextShaderObj(const Shader* shader, unsigned int contextID) :
osg::Referenced(),
_contextID( contextID )
{
_shader = shader;
_extensions = GL2Extensions::Get( _contextID, true );
_glShaderHandle = _extensions->glCreateShader( shader->getType() );
markAsDirty();
}
Shader::PerContextShaderObj::PerContextShaderObj(const PerContextShaderObj& rhs) :
osg::Referenced(),
_contextID( rhs._contextID )
{
_shader = rhs._shader;
_extensions = rhs._extensions;
_glShaderHandle = rhs._glShaderHandle;
_dirty = rhs._dirty;
}
Shader::PerContextShaderObj::~PerContextShaderObj()
{
}
void Shader::PerContextShaderObj::compileShader()
{
GLint compiled;
const char* sourceText = _shader->getShaderSource().c_str();
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
_extensions->glCompileShader( _glShaderHandle );
_extensions->glGetShaderiv( _glShaderHandle, GL_COMPILE_STATUS, &compiled );
_dirty = (compiled == 0);
if( _dirty )
{
// _still_ dirty, something went wrong
std::string infoLog;
_extensions->getShaderInfoLog( _glShaderHandle, infoLog );
osg::notify(osg::WARN) << _shader->getTypename() <<
" glCompileShader FAILED:\n" << infoLog << std::endl;
}
}
void Shader::PerContextShaderObj::attachShader(GLuint program) const
{
_extensions->glAttachShader( program, _glShaderHandle );
}
/*EOF*/

527
src/osg/Uniform.cpp Normal file
View File

@@ -0,0 +1,527 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: src/osg/Uniform.cpp
* author: Mike Weiblen 2005-02-20
*/
// NOTICE: This code is CLOSED during construction and/or renovation!
// It is in active development, so DO NOT yet use in application code.
// This notice will be removed when the code is open for business.
// For development plan and status see:
// http://www.openscenegraph.org/index.php?page=Community.DevelopmentWork
#include <osg/Notify>
#include <osg/Uniform>
using namespace osg;
///////////////////////////////////////////////////////////////////////////
// osg::Uniform::Value
///////////////////////////////////////////////////////////////////////////
Uniform::Value::Value( const char* name, Type type ) :
_name(name), _type(type), _isValid(false)
{}
Uniform::Value::Value( const Value& rhs ) :
_name(rhs._name), _type(rhs._type), _isValid(false)
{
if( rhs._isValid ) copyData(rhs);
}
const char* Uniform::Value::getTypename( Type t )
{
switch( t )
{
case FLOAT: return "float";
case FLOAT_VEC2: return "vec2";
case FLOAT_VEC3: return "vec3";
case FLOAT_VEC4: return "vec4";
case INT: return "int";
case INT_VEC2: return "ivec2";
case INT_VEC3: return "ivec3";
case INT_VEC4: return "ivec4";
case BOOL: return "bool";
case BOOL_VEC2: return "bvec2";
case BOOL_VEC3: return "bvec3";
case BOOL_VEC4: return "bvec4";
case FLOAT_MAT2: return "mat2";
case FLOAT_MAT3: return "mat3";
case FLOAT_MAT4: return "mat4";
case SAMPLER_1D: return "sampler1D";
case SAMPLER_2D: return "sampler2D";
case SAMPLER_3D: return "sampler3D";
case SAMPLER_CUBE: return "samplerCube";
case SAMPLER_1D_SHADOW: return "sampler1DShadow";
case SAMPLER_2D_SHADOW: return "sampler2DShadow";
default: return "UNDEFINED";
}
}
int Uniform::Value::compare(const Value& rhs) const
{
if( this == &rhs ) return 0;
if( _type < rhs._type ) return -1;
if( rhs._type < _type ) return 1;
// consider invalid values "less than" valid values
if( !_isValid && rhs._isValid ) return -1;
if( _isValid && !rhs._isValid ) return 1;
if( _name < rhs._name ) return -1;
if( rhs._name < _name ) return 1;
if( isValid() ) return compareData( rhs );
return 0;
}
void Uniform::Value:: set( float f )
{
_data.f1 = f;
_isValid = true;
}
void Uniform::Value:: set( const osg::Vec2& v2 )
{
_data.f2[0] = v2.x();
_data.f2[1] = v2.y();
_isValid = true;
}
void Uniform::Value:: set( const osg::Vec3& v3 )
{
_data.f3[0] = v3.x();
_data.f3[1] = v3.y();
_data.f3[2] = v3.z();
_isValid = true;
}
void Uniform::Value:: set( const osg::Vec4& v4 )
{
_data.f4[0] = v4.x();
_data.f4[1] = v4.y();
_data.f4[2] = v4.z();
_data.f4[3] = v4.w();
_isValid = true;
}
//TODO void Uniform::Value:: set( const osg::Matrix2& m2 )
//TODO void Uniform::Value:: set( const osg::Matrix3& m3 )
void Uniform::Value:: set( const osg::Matrix& m4 )
{ // TODO verify if needs to be transposed
int n = 0;
for(int row=0; row<4; ++row)
{
for(int col=0; col<4; ++col)
{
_data.f16[n++] = m4(row,col);
}
}
_isValid = true;
}
void Uniform::Value:: set( int i )
{
_data.i1 = i;
_isValid = true;
}
//TODO void Uniform::Value:: set( int i0, int i1 )
//TODO void Uniform::Value:: set( int i0, int i1, int i2 )
//TODO void Uniform::Value:: set( int i0, int i1, int i2, int i3 )
//TODO void Uniform::Value:: set( bool b )
//TODO void Uniform::Value:: set( bool b0, bool b1 )
//TODO void Uniform::Value:: set( bool b0, bool b1, bool b2 )
//TODO void Uniform::Value:: set( bool b0, bool b1, bool b2, bool b3 )
int Uniform::Value::compareData(const Value& rhs) const
{
// caller is responsible for ensuring that
// _type==rhs._type && _isValid && rhs._isValid
switch( getType() )
{
case FLOAT:
{
if( _data.f1 < rhs._data.f1 ) return -1;
if( _data.f1 > rhs._data.f1 ) return 1;
return 0;
}
case FLOAT_VEC2:
{
if( _data.f2[0] < rhs._data.f2[0] ) return -1;
if( _data.f2[0] > rhs._data.f2[0] ) return 1;
if( _data.f2[1] < rhs._data.f2[1] ) return -1;
if( _data.f2[1] > rhs._data.f2[1] ) return 1;
return 0;
}
case FLOAT_VEC3:
{
if( _data.f3[0] < rhs._data.f3[0] ) return -1;
if( _data.f3[0] > rhs._data.f3[0] ) return 1;
if( _data.f3[1] < rhs._data.f3[1] ) return -1;
if( _data.f3[1] > rhs._data.f3[1] ) return 1;
if( _data.f3[2] < rhs._data.f3[2] ) return -1;
if( _data.f3[2] > rhs._data.f3[2] ) return 1;
return 0;
}
case FLOAT_VEC4:
case FLOAT_MAT2:
{
if( _data.f4[0] < rhs._data.f4[0] ) return -1;
if( _data.f4[0] > rhs._data.f4[0] ) return 1;
if( _data.f4[1] < rhs._data.f4[1] ) return -1;
if( _data.f4[1] > rhs._data.f4[1] ) return 1;
if( _data.f4[2] < rhs._data.f4[2] ) return -1;
if( _data.f4[2] > rhs._data.f4[2] ) return 1;
if( _data.f4[3] < rhs._data.f4[3] ) return -1;
if( _data.f4[3] > rhs._data.f4[3] ) return 1;
return 0;
}
case FLOAT_MAT3: return memcmp(_data.f9, rhs._data.f9, sizeof(_data.f9));
case FLOAT_MAT4: return memcmp(_data.f16, rhs._data.f16, sizeof(_data.f16));
case INT:
case BOOL:
case SAMPLER_1D:
case SAMPLER_2D:
case SAMPLER_3D:
case SAMPLER_CUBE:
case SAMPLER_1D_SHADOW:
case SAMPLER_2D_SHADOW:
{
if( _data.i1 < rhs._data.i1 ) return -1;
if( _data.i1 > rhs._data.i1 ) return 1;
return 0;
}
case INT_VEC2:
case BOOL_VEC2:
{
if( _data.i2[0] < rhs._data.i2[0] ) return -1;
if( _data.i2[0] > rhs._data.i2[0] ) return 1;
if( _data.i2[1] < rhs._data.i2[1] ) return -1;
if( _data.i2[1] > rhs._data.i2[1] ) return 1;
return 0;
}
case INT_VEC3:
case BOOL_VEC3:
{
if( _data.i3[0] < rhs._data.i3[0] ) return -1;
if( _data.i3[0] > rhs._data.i3[0] ) return 1;
if( _data.i3[1] < rhs._data.i3[1] ) return -1;
if( _data.i3[1] > rhs._data.i3[1] ) return 1;
if( _data.i3[2] < rhs._data.i3[2] ) return -1;
if( _data.i3[2] > rhs._data.i3[2] ) return 1;
return 0;
}
case INT_VEC4:
case BOOL_VEC4:
{
if( _data.i4[0] < rhs._data.i4[0] ) return -1;
if( _data.i4[0] > rhs._data.i4[0] ) return 1;
if( _data.i4[1] < rhs._data.i4[1] ) return -1;
if( _data.i4[1] > rhs._data.i4[1] ) return 1;
if( _data.i4[2] < rhs._data.i4[2] ) return -1;
if( _data.i4[2] > rhs._data.i4[2] ) return 1;
if( _data.i4[3] < rhs._data.i4[3] ) return -1;
if( _data.i4[3] > rhs._data.i4[3] ) return 1;
return 0;
}
default:
osg::notify(osg::INFO) << "how got here?" << std::endl;
return 0;
}
}
void Uniform::Value::copyData(const Value& rhs)
{
// caller is responsible for ensuring that
// _type==rhs._type && rhs._isValid
_isValid = true;
switch( getType() )
{
case FLOAT:
_data.f1 = rhs._data.f1;
break;
case FLOAT_VEC2:
_data.f2[0] = rhs._data.f2[0];
_data.f2[1] = rhs._data.f2[1];
break;
case FLOAT_VEC3:
_data.f3[0] = rhs._data.f3[0];
_data.f3[1] = rhs._data.f3[1];
_data.f3[2] = rhs._data.f3[2];
break;
case FLOAT_VEC4:
case FLOAT_MAT2:
_data.f4[0] = rhs._data.f4[0];
_data.f4[1] = rhs._data.f4[1];
_data.f4[2] = rhs._data.f4[2];
_data.f4[3] = rhs._data.f4[3];
break;
case FLOAT_MAT3:
for(int i=0;i<9;++i) _data.f9[i]=rhs._data.f9[i];
break;
case FLOAT_MAT4:
for(int i=0;i<16;++i) _data.f16[i]=rhs._data.f16[i];
break;
case INT:
case BOOL:
case SAMPLER_1D:
case SAMPLER_2D:
case SAMPLER_3D:
case SAMPLER_CUBE:
case SAMPLER_1D_SHADOW:
case SAMPLER_2D_SHADOW:
_data.i1 = rhs._data.i1;
break;
case INT_VEC2:
case BOOL_VEC2:
_data.i2[0] = rhs._data.i2[0];
_data.i2[1] = rhs._data.i2[1];
break;
case INT_VEC3:
case BOOL_VEC3:
_data.i3[0] = rhs._data.i3[0];
_data.i3[1] = rhs._data.i3[1];
_data.i3[2] = rhs._data.i3[2];
break;
case INT_VEC4:
case BOOL_VEC4:
_data.i4[0] = rhs._data.i4[0];
_data.i4[1] = rhs._data.i4[1];
_data.i4[2] = rhs._data.i4[2];
_data.i4[3] = rhs._data.i4[3];
break;
default:
osg::notify(osg::INFO) << "how got here?" << std::endl;
break;
}
}
///////////////////////////////////////////////////////////////////////////
// osg::Uniform
///////////////////////////////////////////////////////////////////////////
Uniform::Uniform() :
_value( "", Value::UNDEFINED )
{
// do not use this constructor in application code!
// it exists only because StateAttribute _requires_ a trivial default
// constructor, but that is concept is meaningless for Uniform.
}
Uniform::Uniform( const char* name, Value::Type type ) :
_value( name, type )
{}
Uniform::Uniform( const char* name, float f ) :
_value( name, Value::FLOAT )
{
_value.set( f );
}
Uniform::Uniform( const char* name, const osg::Vec2& v2 ) :
_value( name, Value::FLOAT_VEC2 )
{
_value.set( v2 );
}
Uniform::Uniform( const char* name, const osg::Vec3& v3 ) :
_value( name, Value::FLOAT_VEC3 )
{
_value.set( v3 );
}
Uniform::Uniform( const char* name, const osg::Vec4& v4 ) :
_value( name, Value::FLOAT_VEC4 )
{
_value.set( v4 );
}
//TODO Uniform::Uniform( const char* name, const osg::Matrix2& m2 )
//TODO Uniform::Uniform( const char* name, const osg::Matrix3& m3 )
Uniform::Uniform( const char* name, const osg::Matrix& m4 ) :
_value( name, Value::FLOAT_MAT4 )
{
_value.set( m4 );
}
Uniform::Uniform( const char* name, int i ) :
_value( name, Value::INT )
{
_value.set( i );
}
//TODO Uniform::Uniform( const char* name, int i0, int i1 )
//TODO Uniform::Uniform( const char* name, int i0, int i1, int i2 )
//TODO Uniform::Uniform( const char* name, int i0, int i1, int i2, int i3 )
//TODO Uniform::Uniform( const char* name, bool b )
//TODO Uniform::Uniform( const char* name, bool b0, bool b1 )
//TODO Uniform::Uniform( const char* name, bool b0, bool b1, bool b2 )
//TODO Uniform::Uniform( const char* name, bool b0, bool b1, bool b2, bool b3 )
Uniform::Uniform( const Uniform& gu, const CopyOp& copyop ) :
StateAttribute(gu,copyop),
_value( gu._value )
{
}
void Uniform::apply( State& /*state*/ ) const
{
// The definition of apply() for Uniforms is unique among
// osg::StateAttributes...
// If a Program is not active, then cannot apply the uniform value,
// but must wait for a Program to do that itself later when it
// does become active.
// If a Program is active, then the Uniform may be applied
// immediately.
// something like...
//
// Program* program = state->getActiveProgram();
// if( program )
// {
// program->applyUniform( this );
// }
}
bool Uniform::set( float f )
{
if( ! isCompatibleType( Value::FLOAT ) ) return false;
_value.set( f );
return true;
}
bool Uniform::set( const osg::Vec2& v2 )
{
if( ! isCompatibleType( Value::FLOAT_VEC2 ) ) return false;
_value.set( v2 );
return true;
}
bool Uniform::set( const osg::Vec3& v3 )
{
if( ! isCompatibleType( Value::FLOAT_VEC3 ) ) return false;
_value.set( v3 );
return true;
}
bool Uniform::set( const osg::Vec4& v4 )
{
if( ! isCompatibleType( Value::FLOAT_VEC4 ) ) return false;
_value.set( v4 );
return true;
}
//TODO bool Uniform::set( const osg::Matrix2& m2 )
//TODO bool Uniform::set( const osg::Matrix3& m3 )
bool Uniform::set( const osg::Matrix& m4 )
{
if( ! isCompatibleType( Value::FLOAT_MAT4 ) ) return false;
_value.set( m4 );
return true;
}
bool Uniform::set( int i )
{
if( ! isCompatibleType( Value::INT ) ) return false;
_value.set( i );
return true;
}
//TODO bool Uniform::set( int i0, int i1 )
//TODO bool Uniform::set( int i0, int i1, int i2 )
//TODO bool Uniform::set( int i0, int i1, int i2, int i3 )
//TODO bool Uniform::set( bool b )
//TODO bool Uniform::set( bool b0, bool b1 );
//TODO bool Uniform::set( bool b0, bool b1, bool b2 )
//TODO bool Uniform::set( bool b0, bool b1, bool b2, bool b3 )
bool Uniform::isCompatibleType( Value::Type t ) const
{
if( t == _value.getType() ) return true;
osg::notify(osg::WARN) <<
"Cannot assign " << _value.getTypename(t) <<
" to Uniform \"" << _value.getName() <<
"\" of type " << _value.getTypename( _value.getType() ) <<
std::endl;
return false;
}
/*EOF*/