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:
Robert Osfield
2007-01-18 22:32:18 +00:00
parent ba9e355550
commit ccc8a922a6
7 changed files with 514 additions and 65 deletions

View File

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

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

View File

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

View File

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

View File

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