Added shader pipeline support to osg::TexGen.

This commit is contained in:
Robert Osfield 2016-11-22 15:09:48 +00:00
parent 2fc28a7f64
commit 59a28859ec
2 changed files with 176 additions and 81 deletions

View File

@ -14,8 +14,9 @@
#ifndef OSG_TEXGEN #ifndef OSG_TEXGEN
#define OSG_TEXGEN 1 #define OSG_TEXGEN 1
#include <osg/Plane> #include <osg/TextureAttribute>
#include <osg/StateAttribute> #include <osg/Uniform>
#include <osg/State>
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE) || defined(OSG_GL3_AVAILABLE) #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE) || defined(OSG_GL3_AVAILABLE)
#define GL_OBJECT_LINEAR 0x2401 #define GL_OBJECT_LINEAR 0x2401
@ -39,25 +40,17 @@ namespace osg {
/** TexGen encapsulates the OpenGL glTexGen (texture coordinate generation) /** TexGen encapsulates the OpenGL glTexGen (texture coordinate generation)
* state.*/ * state.*/
class OSG_EXPORT TexGen : public StateAttribute class OSG_EXPORT TexGen : public TextureAttribute
{ {
public : public :
TexGen(); TexGen();
/** Copy constructor using CopyOp to manage deep vs shallow copy. */ /** Copy constructor using CopyOp to manage deep vs shallow copy. */
TexGen(const TexGen& texgen,const CopyOp& copyop=CopyOp::SHALLOW_COPY): TexGen(const TexGen& texgen,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
StateAttribute(texgen,copyop),
_mode(texgen._mode),
_plane_s(texgen._plane_s),
_plane_t(texgen._plane_t),
_plane_r(texgen._plane_r),
_plane_q(texgen._plane_q) {}
META_StateAttribute(osg, TexGen, TEXGEN); META_StateAttribute(osg, TexGen, TEXGEN);
virtual bool isTextureAttribute() const { return true; }
/** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */ /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
virtual int compare(const StateAttribute& sa) const virtual int compare(const StateAttribute& sa) const
{ {
@ -105,7 +98,7 @@ class OSG_EXPORT TexGen : public StateAttribute
REFLECTION_MAP = GL_REFLECTION_MAP REFLECTION_MAP = GL_REFLECTION_MAP
}; };
inline void setMode( Mode mode ) { _mode = mode; } void setMode( Mode mode );
Mode getMode() const { return _mode; } Mode getMode() const { return _mode; }
@ -129,12 +122,18 @@ class OSG_EXPORT TexGen : public StateAttribute
virtual ~TexGen( void ); virtual ~TexGen( void );
std::string getUniformName(const char* baseName, unsigned int unit);
void configureUniformNames();
Mode _mode; Mode _mode;
/** Additional texgen coefficients for GL_OBJECT_PLANE or ref_ptr<PlaneUniform> _plane_s;
* GL_EYE_PLANE, */ ref_ptr<PlaneUniform> _plane_t;
Plane _plane_s, _plane_t, _plane_r, _plane_q; ref_ptr<PlaneUniform> _plane_r;
ref_ptr<PlaneUniform> _plane_q;
StateSet::DefineList _defineList;
}; };
} }

View File

@ -11,6 +11,7 @@
* OpenSceneGraph Public License for more details. * OpenSceneGraph Public License for more details.
*/ */
#include <osg/TexGen> #include <osg/TexGen>
#include <osg/State>
#include <osg/Notify> #include <osg/Notify>
#include <osg/io_utils> #include <osg/io_utils>
@ -19,10 +20,25 @@ using namespace osg;
TexGen::TexGen() TexGen::TexGen()
{ {
_mode = OBJECT_LINEAR; _mode = OBJECT_LINEAR;
_plane_s.set(1.0f, 0.0f, 0.0f, 0.0f); _plane_s = new osg::PlaneUniform(osg::Plane(1.0f, 0.0f, 0.0f, 0.0f));
_plane_t.set(0.0f, 1.0f, 0.0f, 0.0f); _plane_t = new osg::PlaneUniform(osg::Plane(0.0f, 1.0f, 0.0f, 0.0f));
_plane_r.set(0.0f, 0.0f, 1.0f, 0.0f); _plane_r = new osg::PlaneUniform(osg::Plane(0.0f, 0.0f, 1.0f, 0.0f));
_plane_q.set(0.0f, 0.0f, 0.0f, 1.0f); _plane_q = new osg::PlaneUniform(osg::Plane(0.0f, 0.0f, 0.0f, 1.0f));
configureUniformNames();
}
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
TexGen::TexGen(const TexGen& texgen,const CopyOp& copyop):
TextureAttribute(texgen,copyop),
_mode(texgen._mode)
{
_plane_s = new osg::PlaneUniform(texgen._plane_s->getValue());
_plane_t = new osg::PlaneUniform(texgen._plane_t->getValue());
_plane_r = new osg::PlaneUniform(texgen._plane_r->getValue());
_plane_q = new osg::PlaneUniform(texgen._plane_q->getValue());
configureUniformNames();
} }
@ -30,15 +46,69 @@ TexGen::~TexGen()
{ {
} }
void TexGen::setMode( Mode mode )
{
if (_mode!=mode)
{
_mode = mode;
configureUniformNames();
}
}
void TexGen::configureUniformNames()
{
OSG_NOTICE<<__PRETTY_FUNCTION__<<" _textureUnit="<<_textureUnit<<std::endl;
MakeString str;
std::string TEXTURE_GEN_FUNCTION = str<<"TEXTURE_GEN_FUNCTION"<<_textureUnit;
_defineList.clear();
switch(_mode)
{
case(OBJECT_LINEAR):
_plane_s->setName("osg_ObjectPlaneS", _textureUnit);
_plane_t->setName("osg_ObjectPlaneT", _textureUnit);
_plane_r->setName("osg_ObjectPlaneR", _textureUnit);
_plane_q->setName("osg_ObjectPlaneQ", _textureUnit);
_defineList[TEXTURE_GEN_FUNCTION] = StateSet::DefinePair(str.clear()<<"(texcoord, unit, s, t, r, q) texgen_OBJECT_LINEAR(texcoord, unit, s, t, r, q)", osg::StateAttribute::ON);
break;
case(EYE_LINEAR):
_plane_s->setName("osg_EyePlaneS", _textureUnit);
_plane_t->setName("osg_EyePlaneT", _textureUnit);
_plane_r->setName("osg_EyePlaneR", _textureUnit);
_plane_q->setName("osg_EyePlaneQ", _textureUnit);
_defineList[TEXTURE_GEN_FUNCTION] = StateSet::DefinePair(str.clear()<<"(texcoord, unit, s, t, r, q) texgen_EYE_LINEAR(texcoord, unit, s, t, r, q)", osg::StateAttribute::ON);
break;
case(NORMAL_MAP):
_defineList[TEXTURE_GEN_FUNCTION] = StateSet::DefinePair(str.clear()<<"(texcoord, unit, s, t, r, q) texgen_NORMAL_MAP(texcoord, unit, s, t, r, q)", osg::StateAttribute::ON);
break;
case(REFLECTION_MAP):
_defineList[TEXTURE_GEN_FUNCTION] = StateSet::DefinePair(str.clear()<<"(texcoord, unit, s, t, r, q) texgen_REFLECTION_MAP(texcoord, unit, s, t, r, q)", osg::StateAttribute::ON);
break;
case(SPHERE_MAP):
_defineList[TEXTURE_GEN_FUNCTION] = StateSet::DefinePair(str.clear()<<"(texcoord, unit, s, t, r, q) texgen_SPHERE_MAP(texcoord, unit, s, t, r, q)", osg::StateAttribute::ON);
break;
default:
break;
}
}
void TexGen::setPlane(Coord which, const Plane& plane) void TexGen::setPlane(Coord which, const Plane& plane)
{ {
switch( which ) switch( which )
{ {
case S : _plane_s = plane; break; case S : _plane_s->setValue(plane); break;
case T : _plane_t = plane; break; case T : _plane_t->setValue(plane); break;
case R : _plane_r = plane; break; case R : _plane_r->setValue(plane); break;
case Q : _plane_q = plane; break; case Q : _plane_q->setValue(plane); break;
default : OSG_WARN<<"Error: invalid 'which' passed TexGen::setPlane("<<(unsigned int)which<<","<<plane<<")"<<std::endl; break; default : OSG_WARN<<"Error: invalid 'which' passed TexGen::setPlane("<<(unsigned int)which<<","<<plane<<")"<<std::endl; break;
} }
} }
@ -47,11 +117,11 @@ const Plane& TexGen::getPlane(Coord which) const
{ {
switch( which ) switch( which )
{ {
case S : return _plane_s; case S : return _plane_s->getValue();
case T : return _plane_t; case T : return _plane_t->getValue();
case R : return _plane_r; case R : return _plane_r->getValue();
case Q : return _plane_q; case Q : return _plane_q->getValue();
default : OSG_WARN<<"Error: invalid 'which' passed TexGen::getPlane(which)"<<std::endl; return _plane_r; default : OSG_WARN<<"Error: invalid 'which' passed TexGen::getPlane(which)"<<std::endl; return _plane_r->getValue();
} }
} }
@ -59,73 +129,99 @@ Plane& TexGen::getPlane(Coord which)
{ {
switch( which ) switch( which )
{ {
case S : return _plane_s; case S : return _plane_s->getValue();
case T : return _plane_t; case T : return _plane_t->getValue();
case R : return _plane_r; case R : return _plane_r->getValue();
case Q : return _plane_q; case Q : return _plane_q->getValue();
default : OSG_WARN<<"Error: invalid 'which' passed TexGen::getPlane(which)"<<std::endl; return _plane_r; default : OSG_WARN<<"Error: invalid 'which' passed TexGen::getPlane(which)"<<std::endl; return _plane_r->getValue();
} }
} }
void TexGen::setPlanesFromMatrix(const Matrixd& matrix) void TexGen::setPlanesFromMatrix(const Matrixd& matrix)
{ {
_plane_s.set(matrix(0,0),matrix(1,0),matrix(2,0),matrix(3,0)); _plane_s->setValue(Plane(matrix(0,0),matrix(1,0),matrix(2,0),matrix(3,0)));
_plane_t.set(matrix(0,1),matrix(1,1),matrix(2,1),matrix(3,1)); _plane_t->setValue(Plane(matrix(0,1),matrix(1,1),matrix(2,1),matrix(3,1)));
_plane_r.set(matrix(0,2),matrix(1,2),matrix(2,2),matrix(3,2)); _plane_r->setValue(Plane(matrix(0,2),matrix(1,2),matrix(2,2),matrix(3,2)));
_plane_q.set(matrix(0,3),matrix(1,3),matrix(2,3),matrix(3,3)); _plane_q->setValue(Plane(matrix(0,3),matrix(1,3),matrix(2,3),matrix(3,3)));
} }
void TexGen::apply(State&) const
void TexGen::apply(State& state) const
{ {
#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE) #if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
if (_mode == OBJECT_LINEAR || _mode == EYE_LINEAR) if (state.getUseStateAttributeFixedFunction())
{ {
GLenum glmode = _mode == OBJECT_LINEAR ? GL_OBJECT_PLANE : GL_EYE_PLANE; if (_mode == OBJECT_LINEAR || _mode == EYE_LINEAR)
if (sizeof(_plane_s[0])==sizeof(GLfloat))
{ {
glTexGenfv(GL_S, glmode, (const GLfloat*)_plane_s.ptr()); GLenum glmode = _mode == OBJECT_LINEAR ? GL_OBJECT_PLANE : GL_EYE_PLANE;
glTexGenfv(GL_T, glmode, (const GLfloat*)_plane_t.ptr());
glTexGenfv(GL_R, glmode, (const GLfloat*)_plane_r.ptr()); if (sizeof(_plane_s[0])==sizeof(GLfloat))
glTexGenfv(GL_Q, glmode, (const GLfloat*)_plane_q.ptr()); {
glTexGenfv(GL_S, glmode, (const GLfloat*)_plane_s->getValue().ptr());
glTexGenfv(GL_T, glmode, (const GLfloat*)_plane_t->getValue().ptr());
glTexGenfv(GL_R, glmode, (const GLfloat*)_plane_r->getValue().ptr());
glTexGenfv(GL_Q, glmode, (const GLfloat*)_plane_q->getValue().ptr());
}
else
{
glTexGendv(GL_S, glmode, (const GLdouble*)_plane_s->getValue().ptr());
glTexGendv(GL_T, glmode, (const GLdouble*)_plane_t->getValue().ptr());
glTexGendv(GL_R, glmode, (const GLdouble*)_plane_r->getValue().ptr());
glTexGendv(GL_Q, glmode, (const GLdouble*)_plane_q->getValue().ptr());
}
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
} }
else else if (_mode == NORMAL_MAP)
{ {
glTexGendv(GL_S, glmode, (const GLdouble*)_plane_s.ptr()); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGendv(GL_T, glmode, (const GLdouble*)_plane_t.ptr()); glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGendv(GL_R, glmode, (const GLdouble*)_plane_r.ptr()); glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
glTexGendv(GL_Q, glmode, (const GLdouble*)_plane_q.ptr()); // glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
} }
else if (_mode == REFLECTION_MAP)
{
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
// glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
}
else // SPHERE_MAP
{
// Also don't set the mode of GL_R & GL_Q as these will generate
// GL_INVALID_ENUM (See OpenGL Reference Guide, glTexGEn.)
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode ); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode ); glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode ); }
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode ); }
} if (state.getUseStateAttributeShaders())
else if (_mode == NORMAL_MAP)
{
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
// glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
}
else if (_mode == REFLECTION_MAP)
{
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
// glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
}
else // SPHERE_MAP
{
// Also don't set the mode of GL_R & GL_Q as these will generate
// GL_INVALID_ENUM (See OpenGL Reference Guide, glTexGEn.)
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
}
#else
OSG_NOTICE<<"Warning: TexGen::apply(State&) - not supported."<<std::endl;
#endif #endif
{
state.applyShaderCompositionDefines(_defineList);
switch(_mode)
{
case(OBJECT_LINEAR):
state.applyShaderCompositionUniform(_plane_s.get());
state.applyShaderCompositionUniform(_plane_t.get());
state.applyShaderCompositionUniform(_plane_r.get());
state.applyShaderCompositionUniform(_plane_q.get());
break;
case(EYE_LINEAR):
state.applyShaderCompositionUniform(_plane_s.get());
state.applyShaderCompositionUniform(_plane_t.get());
state.applyShaderCompositionUniform(_plane_r.get());
state.applyShaderCompositionUniform(_plane_q.get());
break;
default:
break;
}
}
} }