|
osgEarth 2.1.1
|
Inheritance diagram for osgEarth::Symbology::StencilVolumeNode:
Collaboration diagram for osgEarth::Symbology::StencilVolumeNode:Public Member Functions | |
| StencilVolumeNode (bool preRenderChildrenToDepthBuffer=false, bool inverted=false) | |
| StencilVolumeNode (const StencilVolumeNode &rhs, const osg::CopyOp &op=osg::CopyOp::DEEP_COPY_ALL) | |
| META_Node (osgEarth::Symbology, StencilVolumeNode) | |
| virtual void | traverse (osg::NodeVisitor &nv) |
| int | setBaseRenderBin (int bin) |
| void | addVolumes (osg::Node *node, bool onNextUpdate=true) |
| virtual bool | addChild (Node *child) |
| virtual bool | insertChild (unsigned int index, Node *child) |
| virtual bool | removeChildren (unsigned int pos, unsigned int numChildrenToRemove) |
| virtual bool | replaceChild (Node *origChild, Node *newChild) |
| virtual bool | setChild (unsigned int i, Node *node) |
| virtual osg::BoundingSphere | computeBound () const |
Static Public Member Functions | |
| static osg::Node * | createFullScreenQuad (const osg::Vec4f &color) |
Protected Member Functions | |
| void | init () |
| void | addQueuedVolumes () |
Protected Attributes | |
| osg::ref_ptr< osg::Group > | _root |
| osg::Group * | _stencilGroup1 |
| osg::Group * | _stencilGroup2 |
| osg::Group * | _depthPass |
| osg::Group * | _renderPass |
| bool | _inverted |
| bool | _preRenderChildrenToDepthBuffer |
| Threading::Mutex | _addVolumesMutex |
| std::queue< osg::ref_ptr < osg::Node > > | _volumesToAdd |
Definition at line 32 of file StencilVolumeNode.
| StencilVolumeNode::StencilVolumeNode | ( | bool | preRenderChildrenToDepthBuffer = false, |
| bool | inverted = false |
||
| ) |
Constructs a stencil masking node.
| preRenderChildrenToDepthBuffer | Normally, this node will render the stencil volumes first and then render the children (which will be masked by the stencil). If you need to pre-render the children to the depth buffer, set this to TRUE. You need to do this is you are creating a straight render mask. |
| inverted | Inverts the stencil buffer, masking the opposite pixels that would normally be masked. |
Definition at line 86 of file StencilVolumeNode.cpp.
: osgEarth::MaskNode(), _stencilGroup1( 0L ), _stencilGroup2( 0L ), _depthPass( 0L ), _renderPass( 0L ), _inverted( inverted ), _preRenderChildrenToDepthBuffer( preRenderChildrenToDepthBuffer ) { init(); }
Here is the call graph for this function:| StencilVolumeNode::StencilVolumeNode | ( | const StencilVolumeNode & | rhs, |
| const osg::CopyOp & | op = osg::CopyOp::DEEP_COPY_ALL |
||
| ) |
Copy constructor
Definition at line 98 of file StencilVolumeNode.cpp.
: osgEarth::MaskNode( rhs, op ), _root( rhs._root.get() ), _stencilGroup1( rhs._stencilGroup1 ), _stencilGroup2( rhs._stencilGroup2 ), _depthPass( rhs._depthPass ), _renderPass( rhs._renderPass ), _inverted( rhs._inverted ), _preRenderChildrenToDepthBuffer( rhs._preRenderChildrenToDepthBuffer ) { //nop }
| bool StencilVolumeNode::addChild | ( | Node * | child | ) | [virtual] |
Override all the osg::Group methods:
Definition at line 174 of file StencilVolumeNode.cpp.
{
if ( !child ) return false;
dirtyBound();
if ( _depthPass ) _depthPass->addChild( child );
return _renderPass->addChild( child );
}
| void StencilVolumeNode::addQueuedVolumes | ( | ) | [protected] |
Definition at line 153 of file StencilVolumeNode.cpp.
{
Threading::ScopedMutexLock lock( _addVolumesMutex );
while( !_volumesToAdd.empty() )
{
osg::Node* node = _volumesToAdd.front().get();
if ( _stencilGroup1 )
_stencilGroup1->addChild( node );
if ( _stencilGroup2 )
_stencilGroup2->addChild( node );
_volumesToAdd.pop();
}
ADJUST_UPDATE_TRAV_COUNT( this, -1 );
}
Here is the caller graph for this function:| void StencilVolumeNode::addVolumes | ( | osg::Node * | node, |
| bool | onNextUpdate = true |
||
| ) |
Definition at line 135 of file StencilVolumeNode.cpp.
{
if ( onNextUpdate )
{
Threading::ScopedMutexLock lock( _addVolumesMutex );
_volumesToAdd.push( node );
ADJUST_UPDATE_TRAV_COUNT( this, 1 );
}
else
{
if ( _stencilGroup1 )
_stencilGroup1->addChild( node );
if ( _stencilGroup2 )
_stencilGroup2->addChild( node );
}
}
| osg::BoundingSphere StencilVolumeNode::computeBound | ( | ) | const [virtual] |
Definition at line 207 of file StencilVolumeNode.cpp.
{
if ( _depthPass ) return _depthPass->computeBound();
else return _renderPass->computeBound();
}
| osg::Node * StencilVolumeNode::createFullScreenQuad | ( | const osg::Vec4f & | color | ) | [static] |
Generates a full screen quad that you can use to colorize stencil volumes
Definition at line 47 of file StencilVolumeNode.cpp.
{
// make a full screen quad:
osg::Geometry* quad = new osg::Geometry();
osg::Vec3Array* verts = new osg::Vec3Array(4);
(*verts)[0].set( 0, 1, 0 );
(*verts)[1].set( 0, 0, 0 );
(*verts)[2].set( 1, 0, 0 );
(*verts)[3].set( 1, 1, 0 );
quad->setVertexArray( verts );
quad->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
osg::Vec4Array* colors = new osg::Vec4Array(1);
(*colors)[0] = color;
quad->setColorArray( colors );
quad->setColorBinding( osg::Geometry::BIND_OVERALL );
osg::Geode* quad_geode = new osg::Geode();
quad_geode->addDrawable( quad );
osg::StateSet* quad_ss = quad->getOrCreateStateSet();
quad_ss->setMode( GL_CULL_FACE, OFF_PROTECTED );
quad_ss->setMode( GL_DEPTH_TEST, OFF_PROTECTED );
quad_ss->setMode( GL_LIGHTING, OFF_PROTECTED );
osg::MatrixTransform* abs = new osg::MatrixTransform();
abs->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
abs->setMatrix( osg::Matrix::identity() );
abs->addChild( quad_geode );
osg::Projection* proj = new osg::Projection();
proj->setMatrix( osg::Matrix::ortho(0, 1, 0, 1, 0, -1) );
proj->addChild( abs );
proj->getOrCreateStateSet()->setMode( GL_BLEND, 1 );
return proj;
}
| void StencilVolumeNode::init | ( | ) | [protected] |
Definition at line 225 of file StencilVolumeNode.cpp.
{
_root = new osg::Group();
int baseBin = 100;
// First, if we need to render the children to the depth buffer, create a depth
// buffer only pass. This is necessary if we are masking out terrain, for example. We have
// to populate the depth buffer before this algoritm can work.
if ( _preRenderChildrenToDepthBuffer )
{
_depthPass = new osg::Group();
_depthPass->setName( "StencilVolumeNode::depth_pass" );
osg::StateSet* ss = _depthPass->getOrCreateStateSet();
ss->setAttributeAndModes(new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
//ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), ON_AND_PROTECTED);
ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS), ON_AND_PROTECTED);
ss->setRenderBinDetails( baseBin++, "RenderBin" );
_root->addChild( _depthPass );
}
// Create the stenciled geometry pass:
// For now we are hard-coding these to what are hopefully "safe" values.
// In the future we hope to rewrite this as a custom StencilVolumeNode that
// will automatically detect extension availability at draw time and choose
// the optimal GL rendering path.
const Capabilities& caps = osgEarth::Registry::instance()->getCapabilities();
bool s_EXT_stencil_wrap = caps.supportsStencilWrap(); //true;
bool s_EXT_stencil_two_side = caps.supportsTwoSidedStencil(); //false;
// zFail=true if more compute intensive, but lets you get inside the volume.
// Again, a custom node will give us a better opportunity to choose between zFail and zPass based on
// the eye location (you only need zFail if you camera is inside the volume).
bool zFail = true;
OE_DEBUG << "Stencil buffer wrap = " << s_EXT_stencil_wrap << std::endl;
if ( s_EXT_stencil_two_side )
{
OE_DEBUG << "Two-sided stenciling" << std::endl;
osg::StencilTwoSided::Operation incrOp = s_EXT_stencil_wrap ? osg::StencilTwoSided::INCR_WRAP : osg::StencilTwoSided::INCR;
osg::StencilTwoSided::Operation decrOp = s_EXT_stencil_wrap ? osg::StencilTwoSided::DECR_WRAP : osg::StencilTwoSided::DECR;
_stencilGroup1 = new osg::Group();
//osg::Group* stencil_group = new osg::Group();
osg::StateSet* ss = _stencilGroup1->getOrCreateStateSet();
ss->setRenderBinDetails( baseBin++, "RenderBin" );
if ( zFail )
{
osg::StencilTwoSided* stencil = new osg::StencilTwoSided();
stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS, 1, ~0u);
stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, incrOp, osg::StencilTwoSided::KEEP);
stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS, 1, ~0u);
stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, decrOp, osg::StencilTwoSided::KEEP);
ss->setAttributeAndModes( stencil, ON_AND_PROTECTED );
}
else
{
osg::StencilTwoSided* stencil = new osg::StencilTwoSided();
stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS, 1, ~0u);
stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, incrOp);
stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS, 1, ~0u);
stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, decrOp);
ss->setAttributeAndModes( stencil, ON_AND_PROTECTED );
}
ss->setAttributeAndModes(new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
ss->setAttributeAndModes(new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
_root->addChild( _stencilGroup1 );
}
else
{
OE_INFO << "One-sided stenciling" << std::endl;
if ( !zFail ) // Z-Pass
{
_stencilGroup1 = new osg::Group();
osg::StateSet* front_ss = _stencilGroup1->getOrCreateStateSet();
front_ss->setRenderBinDetails( baseBin++, "RenderBin" );
// incrementing stencil op for front faces:
osg::Stencil* front_stencil = new osg::Stencil();
front_stencil->setFunction( osg::Stencil::ALWAYS, 1, ~0u );
osg::Stencil::Operation incrOp = s_EXT_stencil_wrap ? osg::Stencil::INCR_WRAP : osg::Stencil::INCR;
front_stencil->setOperation( osg::Stencil::KEEP, osg::Stencil::KEEP, incrOp );
front_ss->setAttributeAndModes( front_stencil, ON_AND_PROTECTED );
front_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
front_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), ON_AND_PROTECTED);
front_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
_root->addChild( _stencilGroup1 );
// decrementing stencil op for back faces:
_stencilGroup2 = new osg::Group();
osg::StateSet* back_ss = _stencilGroup2->getOrCreateStateSet();
back_ss->setRenderBinDetails( baseBin++, "RenderBin" );
osg::Stencil* back_stencil = new osg::Stencil();
back_stencil->setFunction( osg::Stencil::ALWAYS, 1, ~0u );
osg::Stencil::Operation decrOp = s_EXT_stencil_wrap ? osg::Stencil::DECR_WRAP : osg::Stencil::DECR;
back_stencil->setOperation( osg::Stencil::KEEP, osg::Stencil::KEEP, decrOp );
back_ss->setAttributeAndModes( back_stencil, ON_AND_PROTECTED );
back_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
back_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::FRONT), ON_AND_PROTECTED);
back_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
_root->addChild( _stencilGroup2 );
}
else
{
// incrementing stencil op for back faces:
{
_stencilGroup1 = new osg::Group();
osg::StateSet* front_ss = _stencilGroup1->getOrCreateStateSet();
front_ss->setRenderBinDetails( baseBin++, "RenderBin" );
osg::Stencil* front_stencil = new osg::Stencil();
front_stencil->setFunction( osg::Stencil::ALWAYS ); //, 1, ~0u );
osg::Stencil::Operation incrOp = s_EXT_stencil_wrap ? osg::Stencil::INCR_WRAP : osg::Stencil::INCR;
front_stencil->setOperation( osg::Stencil::KEEP, incrOp, osg::Stencil::KEEP );
front_ss->setAttributeAndModes( front_stencil, ON_AND_PROTECTED );
front_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
front_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::FRONT), ON_AND_PROTECTED);
front_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
_root->addChild( _stencilGroup1 );
}
// decrementing stencil buf for front faces
{
_stencilGroup2 = new osg::Group();
osg::StateSet* back_ss = _stencilGroup2->getOrCreateStateSet();
back_ss->setRenderBinDetails( baseBin++, "RenderBin" );
osg::Stencil* back_stencil = new osg::Stencil();
back_stencil->setFunction( osg::Stencil::ALWAYS ); //, 1, ~0u );
osg::Stencil::Operation decrOp = s_EXT_stencil_wrap ? osg::Stencil::DECR_WRAP : osg::Stencil::DECR;
back_stencil->setOperation( osg::Stencil::KEEP, decrOp, osg::Stencil::KEEP );
back_ss->setAttributeAndModes( back_stencil, ON_AND_PROTECTED );
back_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
back_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), ON_AND_PROTECTED);
back_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
_root->addChild( _stencilGroup2 );
}
}
}
// NOW build the full-screen quad mask that will paint the volume:
_renderPass = new osg::Group();
_renderPass->setName( "StencilVolumeNode::render_pass" );
osg::Stencil* quad_stencil = new osg::Stencil();
osg::Stencil::Function func = _inverted ? osg::Stencil::EQUAL : osg::Stencil::NOTEQUAL;
quad_stencil->setFunction( func, 128, (unsigned int)~0 );
// this will conveniently re-clear the stencil buffer in prep for the next pass:
quad_stencil->setOperation( osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE );
osg::StateSet* renderSS = _renderPass->getOrCreateStateSet();
renderSS->setAttributeAndModes( quad_stencil, ON_AND_PROTECTED );
renderSS->setRenderBinDetails( baseBin++, "RenderBin" );
// if we did a pre-render depth pass, adjust the depth buffer function to account for that
if ( _preRenderChildrenToDepthBuffer )
{
renderSS->setAttributeAndModes( new osg::Depth( osg::Depth::LEQUAL ), osg::StateAttribute::ON );
}
// testing
//renderSS->setMode( GL_DEPTH_TEST, OFF_AND_PROTECTED );
//renderSS->setAttributeAndModes( new osg::Depth( osg::Depth::ALWAYS ), ON_AND_PROTECTED );
_root->addChild( _renderPass );
}
Here is the call graph for this function:
Here is the caller graph for this function:| bool StencilVolumeNode::insertChild | ( | unsigned int | index, |
| Node * | child | ||
| ) | [virtual] |
Definition at line 181 of file StencilVolumeNode.cpp.
{
if ( !child ) return false;
dirtyBound();
if ( _depthPass ) _depthPass->insertChild( index, child );
return _renderPass->insertChild( index, child );
}
| osgEarth::Symbology::StencilVolumeNode::META_Node | ( | osgEarth::Symbology | , |
| StencilVolumeNode | |||
| ) |
| bool StencilVolumeNode::removeChildren | ( | unsigned int | pos, |
| unsigned int | numChildrenToRemove | ||
| ) | [virtual] |
Definition at line 188 of file StencilVolumeNode.cpp.
{
dirtyBound();
if ( _depthPass ) _depthPass->removeChildren( pos, numChildrenToRemove );
return _renderPass->removeChildren( pos, numChildrenToRemove );
}
| bool StencilVolumeNode::replaceChild | ( | Node * | origChild, |
| Node * | newChild | ||
| ) | [virtual] |
Definition at line 194 of file StencilVolumeNode.cpp.
{
dirtyBound();
if ( _depthPass ) _depthPass->replaceChild( origChild, newChild );
return _renderPass->replaceChild( origChild, newChild );
}
| int StencilVolumeNode::setBaseRenderBin | ( | int | bin | ) |
Definition at line 113 of file StencilVolumeNode.cpp.
{
if ( _depthPass )
{
_depthPass->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
}
if ( _stencilGroup1 )
{
_stencilGroup1->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
}
if ( _stencilGroup2 )
{
_stencilGroup2->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
}
if ( _renderPass )
{
_renderPass->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
}
return bin;
}
| bool StencilVolumeNode::setChild | ( | unsigned int | i, |
| Node * | node | ||
| ) | [virtual] |
Definition at line 200 of file StencilVolumeNode.cpp.
{
dirtyBound();
if ( _depthPass ) _depthPass->setChild( i, node );
return _renderPass->setChild( i, node );
}
| void StencilVolumeNode::traverse | ( | osg::NodeVisitor & | nv | ) | [virtual] |
Definition at line 214 of file StencilVolumeNode.cpp.
{
if ( nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR && _volumesToAdd.size() > 0 )
{
addQueuedVolumes();
}
_root->accept( nv );
}
Here is the call graph for this function:Definition at line 99 of file StencilVolumeNode.
osg::Group* osgEarth::Symbology::StencilVolumeNode::_depthPass [protected] |
Definition at line 94 of file StencilVolumeNode.
bool osgEarth::Symbology::StencilVolumeNode::_inverted [protected] |
Definition at line 96 of file StencilVolumeNode.
Definition at line 97 of file StencilVolumeNode.
osg::Group* osgEarth::Symbology::StencilVolumeNode::_renderPass [protected] |
Definition at line 95 of file StencilVolumeNode.
osg::ref_ptr<osg::Group> osgEarth::Symbology::StencilVolumeNode::_root [protected] |
Definition at line 91 of file StencilVolumeNode.
osg::Group* osgEarth::Symbology::StencilVolumeNode::_stencilGroup1 [protected] |
Definition at line 92 of file StencilVolumeNode.
osg::Group* osgEarth::Symbology::StencilVolumeNode::_stencilGroup2 [protected] |
Definition at line 93 of file StencilVolumeNode.
std::queue< osg::ref_ptr<osg::Node> > osgEarth::Symbology::StencilVolumeNode::_volumesToAdd [protected] |
Definition at line 100 of file StencilVolumeNode.
1.7.3