OSGFX Realization Mode Analysis

Source: Internet
Author: User
Tags addchild
Introduction

OSGFX is an additional library of OSG, an architectural tool for implementing reusable special effects that can be added to OSG nodes. It contains a series of predefined special effects, osg3.2 mainly in the following: Anisotropic Lighting anisotropic illumination bump texture cartoon rendering characterization line cubic map specular highlight contour Line

The specific class structure is shown in the following figure:

use

Osgfx::effect is a group node, and we only need to add the node that needs to be set to the Osgfx::effect node when we use it. For example: When you need to add a wireframe effect to a Geode node, you can do so in the following ways:

	Osg::geode *geode = new Osg::geode;
	Geode->adddrawable (New osg::shapedrawable (New Osg::box (OSG::VEC3 (), 2));
        Declare the effect node and add Geode to it
	osgfx::outline *outline = new Osgfx::outline;
	Outline->addchild (Geode);
	Outline->setcolor (OSG::VEC4 (1.0, 1.0, 0.0, 1.0));
	Outline->setwidth (5.0f);
principle

The implementation principle of OSGFX is actually to construct multiple render state sets, which can render multiple rendering objects in the scene. In the Osgscribe example, to achieve the effect of portraying lines on a model, you need to add two of the nodes of the drawing object to achieve two rendering effects:

RootNode needs to be added two times Loadedmodel//One time with the default render state to render//another to render (tick) with the render state set in decorator Osg::node *loadedmodel = osgdb::
Readnodefile ("Cow.osgt");
osg::group* rootnode = new Osg::group;
osg::group* decorator = new Osg::group;
Rootnode->addchild (Loadedmodel);
Rootnode->addchild (decorator);  

Decorator->addchild (Loadedmodel);
Set the osg::stateset* Stateset = new Osg::stateset for the tick rendering state
OSG::P olygonoffset* polyoffset = new OSG::P olygonoffset;
Polyoffset->setfactor ( -1.0f);
Polyoffset->setunits ( -1.0f);
OSG::P olygonmode* polymode = new OSG::P Olygonmode;
Polymode->setmode (OSG::P olygonmode::front_and_back,osg::P olygonmode::line);
Stateset->setattributeandmodes (Polyoffset,osg::stateattribute::override|osg::stateattribute::on);

Stateset->setattributeandmodes (Polymode,osg::stateattribute::override|osg::stateattribute::on);
osg::material* Material = new Osg::material;
Stateset->setattributeandmodes (Material,osg::stateattribute::override|osg::stateattribute::on); Stateset->setmode (Gl_lighting,osg::stateattribute::override|osg::stateattribute::off);

Stateset->settexturemode (0,gl_texture_2d,osg::stateattribute::override|osg::stateattribute::off); Decorator->setstateset (Stateset);
This is a bit cumbersome, but because it has to be done in the scene node tree structure (because our node Osg::node has only one _stateset member, there are no more render states). However, if you manipulate the state tree of the OSG rendering directly, you can do so without adding multiple times to the scene (nodes to be rendered), for example, as follows:

The OpenGL code
//object itself is actually rendered two times
Glpolygonoffset (1.0, 1.0) in order to achieve simultaneous display of entities and mesh objects;
Drawscene ();
Glpolygonmode (Gl_front_and_back, gl_line);
Drawscene ();
The same code that is represented in OSG by the scene tree structure is the way it is in the osgscribe example above. Another approach is implemented by directly manipulating the branching content of the OSG state tree, with the following schematic code:

void Usernode::traverse (osg::nodevisitor& nv) function
Osgutil::cullvisitor *CV = dynamic_cast<osgutil:: Cullvisitor> (&NV);
if (CV) 
{
//stateset1 save Polygonoffset State set
//stateset2 save Polygonmode State set
	Cv->pushstateset ( STATESET1);
	Node::traverse (CV);
	Cv->popstateset ();
	Cv->pushstateset (Stateset2);
	Node::traverse (CV);
	Cv->popstateset ();
}
The construction of the state tree in OSG is done in the process of cullvisitor traversing and cropping the scene tree. These are the basic principles of the OSGFX Library architecture, and we look at how the OSGFX is done in detail:

First of all to implement a custom effect effect, we need to overload the Define_techniques function, generally in this function we need to define the implementation of custom effects technology (Osgfx::technique), The so-called technology is actually a series of stateset collections, and the set of techniques to add to effect (addtechnique), Reference outline implementation code:

    BOOL Outline::d efine_techniques ()
    {
        _technique = new Outlinetechnique;
        Addtechnique (_technique);

        SetWidth (_width);
        SetColor (_color);

        return true;
    }
The next thing to do is to implement a custom technique, and to implement a custom technique requires overloading the define_passes function, which defines many of the rendered state sets Stateset ( The Stateset1 and Stateset2 described above are defined here and added), and we also refer to the implementation code in Outlinetechnique:

           {osg::stateset* state = new Osg::stateset;
                osg::stencil* stencil = new Osg::stencil;
                Stencil->setfunction (osg::stencil::always, 1, ~0u);
                                      Stencil->setoperation (Osg::stencil::keep, Osg::stencil::keep,
                Osg::stencil::replace);

                State->setattributeandmodes (stencil, override_on);
            Addpass (state);
                } {osg::stateset* state = new Osg::stateset;
                osg::stencil* stencil = new Osg::stencil;
                Stencil->setfunction (osg::stencil::notequal, 1, ~0u);
                                      Stencil->setoperation (Osg::stencil::keep, Osg::stencil::keep,
                Osg::stencil::replace);
				State->setattributeandmodes (stencil, override_on);
   ... addpass (state);         } 
It defines two stateset and is added to the technique so that it is rendered two times during rendering, respectively, and is rendered in its own defined rendering state.

Let's take a look at the rendered code: As we said above should be done in the Cullvisitor, see the source code also just to verify that we think, it is in the technique traverse (), its implementation directly calls the Traverse_implement:

void Technique::traverse_implementation (osg::nodevisitor& NV, effect* FX)
{
    if (_passes.empty ()) {
        Define_passes ();
    }

    Special actions must be taken if the node visitor is actually a cullvisitor
    osgutil::cullvisitor *CV = dynamic_cast <osgutil::cullvisitor *> (&NV);

    for (int i=0; i<getnumpasses (); ++i) 
	{
        if (CV) {
            cv->pushstateset (_passes[i].get ());
        }
        Osg::node *override = Getoverridechild (i);
        if (override) {
            override->accept (nv);
        } else {
            fx->inherited_traverse (nv);
        }
        if (CV) {
            cv->popstateset ();}}
}
is not very familiar with it, just like the demo pseudo-code above us. In addition, we need to know where the technique traverse function is called. It is called in the Traverse function of effect, and the technique traverse function is called to complete the construction of the rendering tree when the scene begins to traverse. The Traverse function code for Osgfx::effect is as follows:

void Effect::traverse (osg::nodevisitor& nv)
{ 
   ...
   
   if (Tech) {
        Tech->traverse (NV, this);
    } else {
        if (nv.gettraversalmode () = = Osg::nodevisitor::traverse_ All_children) {
            inherited_traverse (nv);}}
}
Example

Here is an example of a simple and practical osgfx::outline, and other special effects class effect are used in a similar way:

#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/Geode>
#include < osgga/guieventhandler>
#include <osgFX/Outline>
#include <osg/ShapeDrawable>


void int Main (int argc, char **argv)
{
	Osg::geode *geode = new Osg::geode;
	Geode->adddrawable (New osg::shapedrawable (New Osg::box (OSG::VEC3 (), 2));

	Osgfx::outline *outline = new Osgfx::outline;
	Outline->addchild (Geode);
	Outline->setcolor (OSG::VEC4 (1.0, 1.0, 0.0, 1.0));
	Outline->setwidth (5.0f);

	Osgviewer::viewer Viewer;

	Osg::group *root = new Osg::group;
	Root->addchild (outline);
	Viewer.setupviewinwindow (+, +, +);
	Viewer.setscenedata (root);
	The use of the outline class requires a first 0 empty stencilbuffer
	unsigned int clearmask = Viewer.getcamera ()->getclearmask ();
	Viewer.getcamera ()->setclearmask (Clearmask | Gl_stencil_buffer_bit);
	Viewer.getcamera ()->setclearstencil (0);
	Viewer.run ();
}

Compile run:






Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.