Added osg::StencilTwoSided state attribute to wrap up the stencil_two_sided extension.
Added path in osgShadow work for using StencilTwoSided to accelerate shadow volume rendering.
This commit is contained in:
@@ -528,6 +528,10 @@ SOURCE=..\..\src\osg\Stencil.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\StencilTwoSided.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\Switch.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1040,6 +1044,10 @@ SOURCE=..\..\Include\Osg\Stencil
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\StencilTwoSided
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\Switch
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -5,16 +5,19 @@
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Camera>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/StencilTwoSided>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/AnimationPathManipulator>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <osgShadow/OccluderGeometry>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -47,6 +50,12 @@ public:
|
||||
polytope.add( osg::Plane(0.0, -1.0, 0.0, (_bb.yMax()+delta)) );
|
||||
}
|
||||
|
||||
void getBase(osg::Polytope& polytope, float margin=0.1) const
|
||||
{
|
||||
float delta = _bb.radius()*margin;
|
||||
polytope.add( osg::Plane(0.0, 0.0, 1.0, -(_bb.zMin()-delta)) );
|
||||
}
|
||||
|
||||
void apply(osg::Node& node)
|
||||
{
|
||||
traverse(node);
|
||||
@@ -152,6 +161,19 @@ int main(int argc, char** argv)
|
||||
|
||||
bool doShadow = true;
|
||||
while (arguments.read("--noShadow")) doShadow = false;
|
||||
|
||||
osgShadow::ShadowVolumeGeometry::DrawMode drawMode = osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS;
|
||||
while (arguments.read("--two-sided")) drawMode = osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED;
|
||||
|
||||
|
||||
std::string pathfile;
|
||||
while (arguments.read("-p",pathfile))
|
||||
{
|
||||
osg::ref_ptr<osgGA::AnimationPathManipulator> apm = new osgGA::AnimationPathManipulator(pathfile);
|
||||
if (apm->valid()) viewer.setCameraManipulator(apm.get());
|
||||
}
|
||||
|
||||
if (!viewer.getCameraManipulator()) viewer.setCameraManipulator( new osgGA::TrackballManipulator() );
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
@@ -204,7 +226,8 @@ int main(int argc, char** argv)
|
||||
// set up the occluder
|
||||
osg::ref_ptr<osgShadow::OccluderGeometry> occluder = new osgShadow::OccluderGeometry;
|
||||
occluder->computeOccluderGeometry(model.get());
|
||||
cbbv.getPolytope(occluder->getBoundingPolytope(),0.001);
|
||||
// cbbv.getPolytope(occluder->getBoundingPolytope(),0.001);
|
||||
cbbv.getBase(occluder->getBoundingPolytope(),0.001);
|
||||
|
||||
if (addOccluderToScene)
|
||||
{
|
||||
@@ -215,7 +238,8 @@ int main(int argc, char** argv)
|
||||
|
||||
osg::ref_ptr<osgShadow::ShadowVolumeGeometry> shadowVolume = new osgShadow::ShadowVolumeGeometry;
|
||||
|
||||
shadowVolume->setUseDisplayList(!updateLightPosition);
|
||||
// shadowVolume->setUseDisplayList(!updateLightPosition);
|
||||
shadowVolume->setUseDisplayList(false);
|
||||
|
||||
osg::Vec4 lightpos;
|
||||
|
||||
@@ -251,7 +275,7 @@ int main(int argc, char** argv)
|
||||
osg::Vec4 diffuse(0.8,0.8,0.8,1.0);
|
||||
osg::Vec4 zero_colour(0.0,0.0,0.0,1.0);
|
||||
|
||||
// first group
|
||||
// first group, render the depth buffer + ambient light contribution
|
||||
{
|
||||
|
||||
osg::Group* first_model_group = new osg::Group;
|
||||
@@ -291,50 +315,58 @@ int main(int argc, char** argv)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
occluder->computeShadowVolumeGeometry(lightpos, *shadowVolume);
|
||||
geode->addDrawable(shadowVolume.get());
|
||||
|
||||
// switch off the writing to the color bit planes.
|
||||
osg::ColorMask* colourMask = new osg::ColorMask;
|
||||
colourMask->setMask(false,false,false,false);
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::ALWAYS,0,~0u);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::INCR);
|
||||
|
||||
osg::StateSet* ss_sv1 = geode->getOrCreateStateSet();
|
||||
ss_sv1->setRenderBinDetails(0, "RenderBin");
|
||||
ss_sv1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
ss_sv1->setAttribute(colourMask);
|
||||
shadowVolume->setDrawMode(drawMode);
|
||||
|
||||
ss_sv1->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
|
||||
camera->addChild(geode.get());
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
occluder->computeShadowVolumeGeometry(lightpos, *shadowVolume);
|
||||
geode->addDrawable(shadowVolume.get());
|
||||
if (drawMode == osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"STENCIL_TWO_SIDED seleteced"<<std::endl;
|
||||
|
||||
// switch off the writing to the color bit planes.
|
||||
osg::ColorMask* colourMask = new osg::ColorMask;
|
||||
colourMask->setMask(false,false,false,false);
|
||||
osg::StencilTwoSided* stencil = new osg::StencilTwoSided;
|
||||
stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS,0,~0u);
|
||||
stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::DECR_WRAP);
|
||||
stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS,0,~0u);
|
||||
stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::INCR_WRAP);
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::ALWAYS,0,~0u);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::DECR);
|
||||
|
||||
osg::StateSet* ss_sv1 = geode->getOrCreateStateSet();
|
||||
ss_sv1->setRenderBinDetails(1, "RenderBin");
|
||||
ss_sv1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
ss_sv1->setAttribute(colourMask);
|
||||
|
||||
ss_sv1->setAttributeAndModes(new osg::CullFace(osg::CullFace::FRONT), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
osg::ColorMask* colourMask = new osg::ColorMask(false, false, false, false);
|
||||
|
||||
osg::StateSet* ss_sv1 = geode->getOrCreateStateSet();
|
||||
ss_sv1->setRenderBinDetails(0, "RenderBin");
|
||||
ss_sv1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
ss_sv1->setAttribute(colourMask);
|
||||
ss_sv1->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
|
||||
geode->addDrawable(shadowVolume.get());
|
||||
|
||||
camera->addChild(geode.get());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"STENCIL_TWO_PASSES seleteced"<<std::endl;
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::ALWAYS,0,~0u);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
|
||||
|
||||
osg::ColorMask* colourMask = new osg::ColorMask(false, false, false, false);
|
||||
|
||||
osg::StateSet* ss_sv1 = geode->getOrCreateStateSet();
|
||||
ss_sv1->setRenderBinDetails(0, "RenderBin");
|
||||
ss_sv1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
ss_sv1->setAttribute(colourMask);
|
||||
ss_sv1->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
geode->addDrawable(shadowVolume.get());
|
||||
|
||||
camera->addChild(geode.get());
|
||||
}
|
||||
|
||||
camera->addChild(geode.get());
|
||||
}
|
||||
|
||||
|
||||
// render scene graph adding contribution of light
|
||||
{
|
||||
osg::Group* second_model_group = new osg::Group;
|
||||
second_model_group->addChild(model.get());
|
||||
@@ -363,7 +395,6 @@ int main(int argc, char** argv)
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
|
||||
ss1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
|
||||
|
||||
osg::BlendFunc* blend = new osg::BlendFunc;
|
||||
blend->setFunction(osg::BlendFunc::ONE, osg::BlendFunc::ONE);
|
||||
ss1->setAttributeAndModes(blend, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
@@ -381,16 +412,11 @@ int main(int argc, char** argv)
|
||||
|
||||
viewer.setSceneData(group.get());
|
||||
|
||||
|
||||
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
|
||||
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Warning: Stencil buffer required, but not yet switched on."<<std::endl;
|
||||
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize();
|
||||
|
||||
osgDB::writeNodeFile(*group,"test.osg");
|
||||
|
||||
while (!viewer.done())
|
||||
{
|
||||
if (updateLightPosition)
|
||||
|
||||
201
include/osg/StencilTwoSided
Normal file
201
include/osg/StencilTwoSided
Normal file
@@ -0,0 +1,201 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSG_STENCILTWOSIDED
|
||||
#define OSG_STENCILTWOSIDED 1
|
||||
|
||||
#include <osg/Stencil>
|
||||
|
||||
namespace osg {
|
||||
|
||||
#ifndef GL_STENCIL_TEST_TWO_SIDE
|
||||
#define GL_STENCIL_TEST_TWO_SIDE 0x8910
|
||||
#endif
|
||||
|
||||
/** Encapsulate OpenGL two sided glStencilFunc/Op/Mask functions.
|
||||
*/
|
||||
class OSG_EXPORT StencilTwoSided : public StateAttribute
|
||||
{
|
||||
public :
|
||||
|
||||
|
||||
StencilTwoSided();
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
StencilTwoSided(const StencilTwoSided& stencil,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_StateAttribute(osg, StencilTwoSided, STENCIL);
|
||||
|
||||
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
|
||||
virtual int compare(const StateAttribute& sa) const;
|
||||
|
||||
virtual bool getModeUsage(ModeUsage& usage) const
|
||||
{
|
||||
usage.usesMode(GL_STENCIL_TEST);
|
||||
usage.usesMode(GL_STENCIL_TEST_TWO_SIDE);
|
||||
return true;
|
||||
}
|
||||
|
||||
enum Face
|
||||
{
|
||||
FRONT = 0,
|
||||
BACK = 1
|
||||
};
|
||||
|
||||
enum Function
|
||||
{
|
||||
NEVER = GL_NEVER,
|
||||
LESS = GL_LESS,
|
||||
EQUAL = GL_EQUAL,
|
||||
LEQUAL = GL_LEQUAL,
|
||||
GREATER = GL_GREATER,
|
||||
NOTEQUAL = GL_NOTEQUAL,
|
||||
GEQUAL = GL_GEQUAL,
|
||||
ALWAYS = GL_ALWAYS
|
||||
};
|
||||
|
||||
inline void setFunction(Face face, Function func,int ref,unsigned int mask)
|
||||
{
|
||||
_func[face] = func;
|
||||
_funcRef[face] = ref;
|
||||
_funcMask[face] = mask;
|
||||
}
|
||||
|
||||
inline void setFunction(Face face, Function func) { _func[face] = func; }
|
||||
inline Function getFunction(Face face) const { return _func[face]; }
|
||||
|
||||
inline void setFunctionRef(Face face, int ref) { _funcRef[face]=ref; }
|
||||
inline int getFunctionRef(Face face) const { return _funcRef[face]; }
|
||||
|
||||
inline void setFunctionMask(Face face, unsigned int mask) { _funcMask[face]=mask; }
|
||||
inline unsigned int getFunctionMask(Face face) const { return _funcMask[face]; }
|
||||
|
||||
|
||||
enum Operation
|
||||
{
|
||||
KEEP = GL_KEEP,
|
||||
ZERO = GL_ZERO,
|
||||
REPLACE = GL_REPLACE,
|
||||
INCR = GL_INCR,
|
||||
DECR = GL_DECR,
|
||||
INVERT = GL_INVERT,
|
||||
INCR_WRAP = GL_INCR_WRAP,
|
||||
DECR_WRAP = GL_DECR_WRAP
|
||||
};
|
||||
|
||||
/** set the operations to apply when the various stencil and depth
|
||||
* tests fail or pass. First parameter is to control the operation
|
||||
* when the stencil test fails. The second parameter is to control the
|
||||
* operation when the stencil test passes, but depth test fails. The
|
||||
* third parameter controls the operation when both the stencil test
|
||||
* and depth pass. Ordering of parameter is the same as if using
|
||||
* glStencilOp(,,).*/
|
||||
inline void setOperation(Face face, Operation sfail, Operation zfail, Operation zpass)
|
||||
{
|
||||
_sfail[face] = sfail;
|
||||
_zfail[face] = zfail;
|
||||
_zpass[face] = zpass;
|
||||
}
|
||||
|
||||
/** set the operation when the stencil test fails.*/
|
||||
inline void setStencilFailOperation(Face face, Operation sfail) { _sfail[face] = sfail; }
|
||||
|
||||
/** get the operation when the stencil test fails.*/
|
||||
inline Operation getStencilFailOperation(Face face) const { return _sfail[face]; }
|
||||
|
||||
/** set the operation when the stencil test passes but the depth test fails.*/
|
||||
inline void setStencilPassAndDepthFailOperation(Face face, Operation zfail) { _zfail[face]=zfail; }
|
||||
|
||||
/** get the operation when the stencil test passes but the depth test fails.*/
|
||||
inline Operation getStencilPassAndDepthFailOperation(Face face) const { return _zfail[face]; }
|
||||
|
||||
/** set the operation when both the stencil test and the depth test pass.*/
|
||||
inline void setStencilPassAndDepthPassOperation(Face face, Operation zpass) { _zpass[face]=zpass; }
|
||||
|
||||
/** get the operation when both the stencil test and the depth test pass.*/
|
||||
inline Operation getStencilPassAndDepthPassOperation(Face face) const { return _zpass[face]; }
|
||||
|
||||
|
||||
inline void setWriteMask(Face face, unsigned int mask) { _writeMask[face] = mask; }
|
||||
|
||||
inline unsigned int getWriteMask(Face face) const { return _writeMask[face]; }
|
||||
|
||||
|
||||
virtual void apply(State& state) const;
|
||||
|
||||
public:
|
||||
|
||||
/** Extensions class which encapsulates the querying of extensions and
|
||||
* associated function pointers, and provide convenience wrappers to
|
||||
* check for the extensions or use the associated functions.
|
||||
*/
|
||||
class OSG_EXPORT Extensions : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
Extensions(unsigned int contextID);
|
||||
|
||||
Extensions(const Extensions& rhs);
|
||||
|
||||
void lowestCommonDenominator(const Extensions& rhs);
|
||||
|
||||
void setupGLExtenions(unsigned int contextID);
|
||||
|
||||
void setStencilTwoSidedSupported(bool flag) { _isStencilTwoSidedSupported=flag; }
|
||||
bool isStencilTwoSidedSupported() const { return _isStencilTwoSidedSupported; }
|
||||
|
||||
void glActiveStencilFace(GLenum face) const;
|
||||
|
||||
protected:
|
||||
|
||||
~Extensions() {}
|
||||
|
||||
bool _isStencilTwoSidedSupported;
|
||||
|
||||
void* _glActiveStencilFace;
|
||||
};
|
||||
|
||||
/** Function to call to get the extension of a specified context.
|
||||
* If the Exentsion object for that context has not yet been created
|
||||
* 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
|
||||
* will only be created with the graphics context associated with ContextID.
|
||||
*/
|
||||
static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized);
|
||||
|
||||
/** The setExtensions method 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 setExtensions(unsigned int contextID,Extensions* extensions);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~StencilTwoSided();
|
||||
|
||||
Function _func[2];
|
||||
int _funcRef[2];
|
||||
unsigned int _funcMask[2];
|
||||
|
||||
Operation _sfail[2];
|
||||
Operation _zfail[2];
|
||||
Operation _zpass[2];
|
||||
|
||||
unsigned int _writeMask[2];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -197,7 +197,16 @@ class OSGSHADOW_EXPORT ShadowVolumeGeometry : public osg::Drawable
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ShadowVolumeGeometry*>(obj)!=NULL; }
|
||||
virtual const char* libraryName() const { return "osgShadow"; }
|
||||
virtual const char* className() const { return "ShadowVolumeGeometry"; }
|
||||
|
||||
enum DrawMode
|
||||
{
|
||||
GEOMETRY,
|
||||
STENCIL_TWO_PASS,
|
||||
STENCIL_TWO_SIDED
|
||||
};
|
||||
|
||||
void setDrawMode(DrawMode mode) { _drawMode = mode; }
|
||||
DrawMode getDrawMode() const { return _drawMode; }
|
||||
|
||||
typedef std::vector<osg::Vec3> Vec3List;
|
||||
typedef std::vector<GLuint> UIntList;
|
||||
@@ -223,6 +232,7 @@ class OSGSHADOW_EXPORT ShadowVolumeGeometry : public osg::Drawable
|
||||
|
||||
virtual ~ShadowVolumeGeometry() {}
|
||||
|
||||
DrawMode _drawMode;
|
||||
Vec3List _vertices;
|
||||
Vec3List _normals;
|
||||
UIntList _indices;
|
||||
|
||||
@@ -95,6 +95,7 @@ CXXFILES =\
|
||||
StateAttribute.cpp\
|
||||
StateSet.cpp\
|
||||
Stencil.cpp\
|
||||
StencilTwoSided.cpp\
|
||||
Switch.cpp\
|
||||
TexEnvCombine.cpp\
|
||||
TexEnv.cpp\
|
||||
|
||||
160
src/osg/StencilTwoSided.cpp
Normal file
160
src/osg/StencilTwoSided.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osg/StencilTwoSided>
|
||||
#include <osg/State>
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
StencilTwoSided::StencilTwoSided()
|
||||
{
|
||||
// set up same defaults as glStencilFunc.
|
||||
_func[FRONT] = _func[BACK] = ALWAYS;
|
||||
_funcRef[FRONT] = _funcRef[BACK] = 0;
|
||||
_funcMask[FRONT] = _funcMask[BACK] = ~0u;
|
||||
|
||||
// set up same defaults as glStencilOp.
|
||||
_sfail[FRONT] = _sfail[BACK] = KEEP;
|
||||
_zfail[FRONT] = _zfail[BACK] = KEEP;
|
||||
_zpass[FRONT] = _zpass[BACK] = KEEP;
|
||||
|
||||
_writeMask[FRONT] = _writeMask[BACK] = ~0u;
|
||||
}
|
||||
|
||||
StencilTwoSided::StencilTwoSided(const StencilTwoSided& stencil,const CopyOp& copyop):
|
||||
StateAttribute(stencil,copyop)
|
||||
{
|
||||
_func[FRONT] = stencil._func[FRONT];
|
||||
_funcRef[FRONT] = stencil._funcRef[FRONT];
|
||||
_funcMask[FRONT] = stencil._funcMask[FRONT];
|
||||
_sfail[FRONT] = stencil._sfail[FRONT];
|
||||
_zfail[FRONT] = stencil._zfail[FRONT];
|
||||
_zpass[FRONT] = stencil._zpass[FRONT];
|
||||
_writeMask[FRONT] = stencil._writeMask[FRONT];
|
||||
|
||||
_func[BACK] = stencil._func[BACK];
|
||||
_funcRef[BACK] = stencil._funcRef[BACK];
|
||||
_funcMask[BACK] = stencil._funcMask[BACK];
|
||||
_sfail[BACK] = stencil._sfail[BACK];
|
||||
_zfail[BACK] = stencil._zfail[BACK];
|
||||
_zpass[BACK] = stencil._zpass[BACK];
|
||||
_writeMask[BACK] = stencil._writeMask[BACK];
|
||||
}
|
||||
|
||||
StencilTwoSided::~StencilTwoSided()
|
||||
{
|
||||
}
|
||||
|
||||
int StencilTwoSided::compare(const StateAttribute& sa) const
|
||||
{
|
||||
// check the types are equal and then create the rhs variable
|
||||
// used by the COMPARE_StateAttribute_Parameter macro's below.
|
||||
COMPARE_StateAttribute_Types(StencilTwoSided,sa)
|
||||
|
||||
// compare each parameter in turn against the rhs.
|
||||
COMPARE_StateAttribute_Parameter(_func[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_funcRef[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_funcMask[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_sfail[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_zfail[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_zpass[FRONT])
|
||||
COMPARE_StateAttribute_Parameter(_writeMask[FRONT])
|
||||
|
||||
COMPARE_StateAttribute_Parameter(_func[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_funcRef[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_funcMask[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_sfail[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_zfail[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_zpass[BACK])
|
||||
COMPARE_StateAttribute_Parameter(_writeMask[BACK])
|
||||
|
||||
return 0; // passed all the above comparison macro's, must be equal.
|
||||
}
|
||||
|
||||
void StencilTwoSided::apply(State& state) const
|
||||
{
|
||||
const unsigned int contextID = state.getContextID();
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
|
||||
if (!extensions->isStencilTwoSidedSupported())
|
||||
return;
|
||||
|
||||
extensions->glActiveStencilFace(GL_BACK);
|
||||
glStencilOp((GLenum)_sfail[BACK],(GLenum)_zfail[BACK],(GLenum)_zpass[BACK]);
|
||||
glStencilMask(_writeMask[BACK]);
|
||||
glStencilFunc((GLenum)_func[BACK],_funcRef[BACK],_funcMask[BACK]);
|
||||
|
||||
extensions->glActiveStencilFace(GL_FRONT);
|
||||
glStencilOp((GLenum)_sfail[FRONT],(GLenum)_zfail[FRONT],(GLenum)_zpass[FRONT]);
|
||||
glStencilMask(_writeMask[FRONT]);
|
||||
glStencilFunc((GLenum)_func[FRONT],_funcRef[FRONT],_funcMask[FRONT]);
|
||||
}
|
||||
|
||||
|
||||
typedef buffered_value< ref_ptr<StencilTwoSided::Extensions> > BufferedExtensions;
|
||||
static BufferedExtensions s_extensions;
|
||||
|
||||
StencilTwoSided::Extensions* StencilTwoSided::getExtensions(unsigned int contextID,bool createIfNotInitalized)
|
||||
{
|
||||
if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID);
|
||||
return s_extensions[contextID].get();
|
||||
}
|
||||
|
||||
void StencilTwoSided::setExtensions(unsigned int contextID,Extensions* extensions)
|
||||
{
|
||||
s_extensions[contextID] = extensions;
|
||||
}
|
||||
|
||||
StencilTwoSided::Extensions::Extensions(unsigned int contextID)
|
||||
{
|
||||
setupGLExtenions(contextID);
|
||||
}
|
||||
|
||||
StencilTwoSided::Extensions::Extensions(const Extensions& rhs):
|
||||
Referenced()
|
||||
{
|
||||
_isStencilTwoSidedSupported = rhs._isStencilTwoSidedSupported;
|
||||
_glActiveStencilFace = rhs._glActiveStencilFace;
|
||||
}
|
||||
|
||||
|
||||
void StencilTwoSided::Extensions::lowestCommonDenominator(const Extensions& rhs)
|
||||
{
|
||||
if (!rhs._isStencilTwoSidedSupported) _isStencilTwoSidedSupported = false;
|
||||
|
||||
if (!rhs._glActiveStencilFace) _glActiveStencilFace = 0;
|
||||
|
||||
}
|
||||
|
||||
void StencilTwoSided::Extensions::setupGLExtenions(unsigned int contextID)
|
||||
{
|
||||
_isStencilTwoSidedSupported = isGLExtensionSupported(contextID,"GL_EXT_stencil_two_side");
|
||||
|
||||
_glActiveStencilFace = osg::getGLExtensionFuncPtr("glActiveStencilFace","glActiveStencilFaceEXT");
|
||||
}
|
||||
|
||||
void StencilTwoSided::Extensions::glActiveStencilFace(GLenum face) const
|
||||
{
|
||||
if (_glActiveStencilFace)
|
||||
{
|
||||
typedef void (APIENTRY * ActiveStencilFaceProc) (GLenum);
|
||||
((ActiveStencilFaceProc)_glActiveStencilFace)(face);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glActiveStencilFace not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include <osgShadow/OccluderGeometry>
|
||||
|
||||
#include <osg/Notify>
|
||||
@@ -23,6 +27,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
OccluderGeometry::OccluderGeometry()
|
||||
@@ -762,7 +767,7 @@ void OccluderGeometry::computeShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
|
||||
// directional light.
|
||||
osg::Vec3 lightdirection( -lightpos.x(), -lightpos.y(), -lightpos.z());
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Directional light"<<std::endl;
|
||||
// osg::notify(osg::NOTICE)<<"Directional light"<<std::endl;
|
||||
|
||||
// choose the base plane
|
||||
const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
|
||||
@@ -822,12 +827,12 @@ void OccluderGeometry::computeShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
|
||||
|
||||
osg::Plane basePlane(0.0, 0.0, 1.0, 0.0);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Positional light"<<std::endl;
|
||||
// osg::notify(osg::NOTICE)<<"Positional light"<<std::endl;
|
||||
UIntList silhouetteIndices;
|
||||
computeLightPositionSlihouetteEdges(lightposition, silhouetteIndices);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"basePlane "<<basePlane[0]<<" "<<basePlane[1]<<" "<<basePlane[2]<<" "<<basePlane[3]<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"lightpos = "<<std::endl;
|
||||
// osg::notify(osg::NOTICE)<<"basePlane "<<basePlane[0]<<" "<<basePlane[1]<<" "<<basePlane[2]<<" "<<basePlane[3]<<std::endl;
|
||||
// osg::notify(osg::NOTICE)<<"lightpos = "<<std::endl;
|
||||
const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
|
||||
|
||||
for(UIntList::iterator itr = silhouetteIndices.begin();
|
||||
@@ -881,7 +886,7 @@ void OccluderGeometry::computeShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
|
||||
svg.dirtyBound();
|
||||
|
||||
osg::Timer_t t1 = osg::Timer::instance()->tick();
|
||||
osg::notify(osg::NOTICE)<<"computeShadowVolumeGeometry "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
|
||||
// osg::notify(osg::NOTICE)<<"computeShadowVolumeGeometry "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
|
||||
}
|
||||
|
||||
void OccluderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
@@ -918,7 +923,8 @@ osg::BoundingBox OccluderGeometry::computeBound() const
|
||||
//
|
||||
// ShadowVolumeGeometry
|
||||
//
|
||||
ShadowVolumeGeometry::ShadowVolumeGeometry()
|
||||
ShadowVolumeGeometry::ShadowVolumeGeometry():
|
||||
_drawMode(GEOMETRY)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -929,23 +935,60 @@ ShadowVolumeGeometry::ShadowVolumeGeometry(const ShadowVolumeGeometry& oc, const
|
||||
|
||||
void ShadowVolumeGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
renderInfo.getState()->disableAllVertexArrays();
|
||||
|
||||
renderInfo.getState()->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
|
||||
|
||||
if (!_normals.empty())
|
||||
if (_drawMode==GEOMETRY)
|
||||
{
|
||||
renderInfo.getState()->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) );
|
||||
osg::State* state = renderInfo.getState();
|
||||
|
||||
state->disableAllVertexArrays();
|
||||
|
||||
state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
|
||||
|
||||
if (!_normals.empty())
|
||||
{
|
||||
state->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
glNormal3f(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
glColor4f(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glDrawArrays( GL_QUADS, 0, _vertices.size() );
|
||||
}
|
||||
else
|
||||
else if (_drawMode==STENCIL_TWO_PASS)
|
||||
{
|
||||
glNormal3f(0.0f, 0.0f, 0.0f);
|
||||
osg::State* state = renderInfo.getState();
|
||||
|
||||
state->disableAllVertexArrays();
|
||||
state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
|
||||
|
||||
// draw front faces of shadow volume
|
||||
glCullFace(GL_BACK);
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR);
|
||||
|
||||
glDrawArrays( GL_QUADS, 0, _vertices.size() );
|
||||
|
||||
// draw back faces of shadow volume
|
||||
glCullFace(GL_FRONT);
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_DECR);
|
||||
|
||||
glDrawArrays( GL_QUADS, 0, _vertices.size() );
|
||||
|
||||
state->haveAppliedAttribute(osg::StateAttribute::CULLFACE);
|
||||
state->haveAppliedAttribute(osg::StateAttribute::STENCIL);
|
||||
|
||||
}
|
||||
else // stencil two sided, note state all set up separately.
|
||||
{
|
||||
osg::State* state = renderInfo.getState();
|
||||
|
||||
state->disableAllVertexArrays();
|
||||
state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
|
||||
|
||||
|
||||
glColor4f(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glDrawArrays( GL_QUADS, 0, _vertices.size() );
|
||||
glDrawArrays( GL_QUADS, 0, _vertices.size() );
|
||||
}
|
||||
}
|
||||
|
||||
osg::BoundingBox ShadowVolumeGeometry::computeBound() const
|
||||
|
||||
Reference in New Issue
Block a user