Just for the record, in case someone need to implement it or something
similar, the code below is what has worked for me.

  The capping geometry in _capPlane is just a plane covering the whole
screen, just for testing the effect. It should fit the clipping plane(s) to
see it correctly.

  Thank you very much for your help, Robert.

-----------------------8<-------------8<-------------8<-------------8<-------------8<-------------

class CappingTechnique : public osgFX::Technique {

private:
    osg::Node *_capPlane;

public:
    //virtual bool validate(osg::State&) const
    //{ return true; }

    /// Constructor
    CappingTechnique()
    {
        // Build the plane to draw with the stencil mask
        osg::Geometry *geometry = new osg::Geometry();
        osg::Vec3Array *vertices = new osg::Vec3Array();
        osg::Vec4Array *colors = new osg::Vec4Array();

        vertices->push_back(osg::Vec3(-1.0, -1.0, 0.0));
        vertices->push_back(osg::Vec3(-1.0, 1.0, 0.0));
        vertices->push_back(osg::Vec3(1.0, 1.0, 0.0));
        vertices->push_back(osg::Vec3(1.0, -1.0, 0.0));
        geometry->setVertexArray(vertices);
        colors->push_back(osg::Vec4(1.0, 0.0, 1.0, 1.0));
        geometry->setColorArray(colors);
        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
        geometry->addPrimitiveSet(new
osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

        osg::Geode *geode = new osg::Geode();
        geode->addDrawable(geometry);

        osg::Transform *trans = new osg::Transform();
        trans->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
        trans->addChild( geode );

        osg::Projection *proj = new
osg::Projection(osg::Matrix::ortho2D(-1,1,-1,1));
        proj->addChild( trans );

        _capPlane = proj;

    }

protected:
    virtual void define_passes()
    {
        // pass #0
        {
            osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
            osg::Stencil *stencil = new osg::Stencil;
            stencil->setFunction(osg::Stencil::ALWAYS, 0x0, ~0);
            stencil->setOperation(osg::Stencil::INVERT,
osg::Stencil::INVERT, osg::Stencil::INVERT);
            ss->setAttributeAndModes(stencil, osg::StateAttribute::ON |
osg::StateAttribute::OVERRIDE);
            ss->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
            addPass(ss.get());
        }
        // pass #1
        {
            osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
            osg::Stencil *stencil = new osg::Stencil;
            stencil->setFunction(osg::Stencil::NOTEQUAL, 0x0, ~0);
            stencil->setOperation(osg::Stencil::ZERO, osg::Stencil::ZERO,
osg::Stencil::ZERO);
            ss->setAttributeAndModes(stencil, osg::StateAttribute::ON |
osg::StateAttribute::OVERRIDE);
            osg::Depth *depth = new osg::Depth();
            depth->setWriteMask(false);
            ss->setAttributeAndModes( depth, osg::StateAttribute::ON );
            addPass(ss.get());
        }
    }

    virtual osg::Node *getOverrideChild(int pass)
    {
        switch(pass) {
            case 1:    // Second pass (pass #1) draws the cap plane
                return _capPlane;
                break;
            default:
                return NULL;
                break;
        }
    }
};

-----------------------8<-------------8<-------------8<-------------8<-------------8<-------------


On Thu, Sep 2, 2010 at 5:19 PM, Robert Milharcic <
[email protected]> wrote:

>
>
> You can use osgFX node kit framework to implement described capping
> tehnique. You do that by inheriting osgFX::Effect class. In your derived
> class you have to override/implement  virtual bool define_techniques()
> member of the osgFX::Effect class  like this:
>
>
>
>  bool CappingEffect::define_techniques()
>
> {
>
>     CappingTechnique* technique = new CappingTechnique(this);
>
>     addTechnique(technique);
>
>     return true;
>
> }
>
>
>
> CappingTechnique must inherit from osgFX::Technique. In the derived class
> you will have to  implement virtual bool validate(osg::State&) const,
> virtual void define_passes() and optionally virtual osg::Node*
> getOverrideChild(int pass) like this:
>
>
>
> bool CappingTechnique::validate(osg::State&) const
>
> {
>
>                 return true;
>
> }
>
>
>
> bool CappingTechnique:: define_passes()
>
> {
>
>     // pass #1
>
>     {
>
>         osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
>
>        ... setup states for  stencil operation
>
>         addPass(ss.get());
>
>     }
>
>     // implement pass #2
>
>     {
>
>         osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
>
>        ... setup states for solid color draw
>
>         addPass(ss.get());
>
>     }
>
> }
>
>
>
> You can optionally implement getOverrideChild (int pass) to supply some
> other graph for a particlular pass. You then add your group to the
> CappingEffect (the osgFX::Effect inherits from osg::Group node) and
> CappingEffect  to the camera.
>
>
>
> Robert Milharcic
>
>
>
> *From:* [email protected] [mailto:
> [email protected]] *On Behalf Of *Javier Taibo
> *Sent:* Thursday, September 02, 2010 1:09 PM
> *To:* [email protected]
> *Subject:* [osg-users] draw callbacks
>
>
>
>   Hi,
>
>   I have some solid geometry clipped by some clipping planes in an OSG
> application. I am trying to use the capping technique described in chapter
> 10 of the Red Book using the stencil buffer. I have successfully implemented
> this technique in raw OpenGL, but I would like to use it whithin the OSG
> application. The technique is based on storing on the stencil buffer the
> regions that are "open" and then in a later pass draw a solid color in these
> regions.
>
>   I have put the clipped geometry under an osg::Camera node with the
> stencil function configured. To do the second pass (the one that draws the
> caps in the regions marked in the stencil), I am trying to use a post-draw
> callback with the OpenGL calls (saving and restoring the states to avoid
> breaking things). The problem is that I need to set the NESTED rendering
> order to see all the scene graph, and when I do it, the post-draw callback
> is not called anymore.
>
>   I do not have full control over the application, so the solution I am
> looking for has to be "transparent" to the rest of the scene graph. I must
> activate this behaviour to a group in the scene graph without breaking
> anything outside this branch.  What is the best way to do it? camera
> post-draw callbacks? rendering bins? any other?
>
>   I am not very familiar with render passes in OSG, so the way I am trying
> is probably not the best way. I would appreciate any suggestion, advice or
> pointer to any related documentation or source code.
>
>
>   Thanks in advance.
>
>
>   Javier Taibo.
>
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to