osgEarth 2.1.1
|
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(); }
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 ); }
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 ); }
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 ); }
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.