For all those out there who wonder if it is possible, please find attached an 
example program that illustrates, how to use :

- composite viewer with 2 views
- both rendering the same scene
- both using a post render camera to apply  postpro effects

If you run the example with --rtt argument, the main camera per view renders to 
a texture, and the post-render camera renders the texture on a quad. 

for now, there are no shader programs used, I simply render the texture on the 
quad. but it would be no problem to add a shader to the quad's stateset.

Important stuff I stumbled upon:
- when using multiple views that overlap, make sure the topmost view has the 
lowest post-render index, since its content has to be rendered first. and 
applied on the quad last.
- no matter where the final viewport is located on screen, the rtt camera 
always renders from the origin of the framebuffer. this means for a viewport of 
(x,y,w,h) you have to set the viewport of the rtt-camera to (0,0,w,h).

I hope my little example program can help somebody.

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=51214#51214



/*
 * This sample program illustrates the use of RTT cameras to render to texture 
and
 * post render cameras to render the texture again on a quad.
 *
 * Daniel Schmid 22.11.2012
 */


#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/io_utils>
#include <osgGA/StateSetManipulator>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Renderer>
#include <osg/Vec3>

#include <iostream>

using namespace osg;

int postrenderindex = 5;

void setRTTandHUDCamera(osgViewer::View& viewer, int a_width, int a_height)
{
  osg::Camera* maincamera = viewer.getCamera();
  osg::Viewport* l_Viewport = maincamera->getViewport();

  unsigned int x = l_Viewport->x();
  unsigned int y = l_Viewport->y();
  unsigned int tex_width = l_Viewport->width();
  unsigned int tex_height = l_Viewport->height();

  osg::Texture2D* texture = new osg::Texture2D;
  texture->setTextureSize(tex_width, tex_height);
  texture->setResizeNonPowerOfTwoHint(false);
  texture->setInternalFormat(GL_RGBA);
  texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
  texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);

  // set up the render to texture of main camera.
  {
      maincamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

      // IMPORTANT: no matter where final viewport is, the framebuffer is 
always referred to zero origin
      maincamera->setViewport(0, 0, tex_width, tex_height);

      // tell the camera to use OpenGL frame buffer object where supported.
      
maincamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);

      // attach the texture and use it as the color buffer.
      maincamera->attach(osg::Camera::COLOR_BUFFER, texture, 0, 0, false, 4, 4);

  }

  // create the quad to visualize.
  osg::Vec3 corner = osg::Vec3(x, y, 0.0f);
  osg::Vec3 heightVec = osg::Vec3(0.0f, tex_height, 0.0f);
  osg::Vec3 widthVec  = osg::Vec3(tex_width, 0.0f, 0.0f);

  osg::Geometry* geom = osg::createTexturedQuadGeometry(corner, widthVec, 
heightVec);

  // setup default state set
  geom->setStateSet(new osg::StateSet());
  geom->setUseDisplayList(false);

  // new we need to add the texture to the Drawable, we do so by creating a
  // StateSet to contain the Texture StateAttribute.
  osg::StateSet* stateset = geom->getOrCreateStateSet();
  stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
  stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

  // setup post render camera
  {
     osg::Geode* geode = new osg::Geode();
     geode->addDrawable(geom);

     // set up the camera to render the textured quad
     osg::Camera* camera = new osg::Camera;
     camera->setRenderer(new osgViewer::Renderer(camera));

     // IMPORTANT: the topmost view has to have the lowest index
     camera->setRenderOrder(osg::Camera::POST_RENDER, postrenderindex--);

     camera->setGraphicsContext(maincamera->getGraphicsContext());
     camera->setViewport(0, 0, a_width, a_height);

     camera->setProjectionMatrix(osg::Matrix::ortho2D(0, a_width , 0, 
a_height));
     camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     camera->setViewMatrix(osg::Matrix::identity());

     // only clear the depth buffer
     camera->setClearMask(0);

     // add subgraph to render
     camera->addChild(geode);
  }
}

class RTTEventHandler : public osgGA::GUIEventHandler
{
public:
  bool bInitialized;
  int width;
  int height;
  RTTEventHandler(int a_width, int a_height)
  {
    bInitialized = false;
    width        = a_width;
    height       = a_height;
  }

  virtual bool handle(const osgGA::GUIEventAdapter& a_ea, 
osgGA::GUIActionAdapter& a_aa)
  {
    osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&a_aa);
    if (!myview) return false;

    if (!bInitialized)
    {
      setRTTandHUDCamera(*myview, width, height);
      bInitialized = true;
    }

  }

  virtual void getUsage(osg::ApplicationUsage& usage) const {}
};

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // load the nodes from the commandline arguments.
    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);

    // if not loaded assume no arguments passed in, try use default mode 
instead.
    if (!loadedModel) loadedModel = osgDB::readNodeFile("cow.osgt");
  
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << 
std::endl;
        return 1;
    }
    
    // construct the viewer.
    osgViewer::CompositeViewer viewer(arguments);

    osg::GraphicsContext::WindowingSystemInterface* wsi = 
osg::GraphicsContext::getWindowingSystemInterface();
    unsigned int width, height;
    wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, 
height);

    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new 
osg::GraphicsContext::Traits;
    traits->x = 0;
    traits->y = 0;
    traits->width = width;
    traits->height = height;
    traits->windowDecoration = false;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;

    osg::ref_ptr<osg::GraphicsContext> gc = 
osg::GraphicsContext::createGraphicsContext(traits.get());
    if (gc.valid())
    {
        osg::notify(osg::INFO)<<"  GraphicsWindow has been created 
successfully."<<std::endl;

        // need to ensure that the window is cleared make sure that the 
complete window is set the correct colour
        // rather than just the parts of the window that are under the camera's 
viewports
        gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
        gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    else
    {
        osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created 
successfully."<<std::endl;
    }

    osgViewer::View* view1 = new osgViewer::View;
    view1->setName("View 1");
    viewer.addView(view1);

    view1->setSceneData( loadedModel );
    view1->getCamera()->setName("Camera 1");
    view1->getCamera()->setClearColor(osg::Vec4(1.0, 0 , 0, 1.0));
    view1->getCamera()->setViewport(new osg::Viewport(0, 0, width, height));
    view1->getCamera()->setGraphicsContext(gc.get());

    // add the state manipulator
    view1->addEventHandler( new 
osgGA::StateSetManipulator(view1->getCamera()->getOrCreateStateSet()) );

    // add the stats handler
    view1->addEventHandler(new osgViewer::StatsHandler);
    view1->addEventHandler(new osgViewer::HelpHandler);


    osgViewer::View* view2 = new osgViewer::View;
    view2->setName("View 2");
    viewer.addView(view2);
    view2->setSceneData( loadedModel );
    view2->getCamera()->setName("Camera 2");
    view2->getCamera()->setClearColor(osg::Vec4(1.0, 1.0 , 0, 1.0));
    view2->getCamera()->setViewport(new osg::Viewport(width / 2, height / 2, 
width / 4, height / 4));
    view2->getCamera()->setGraphicsContext(gc.get());

    if (arguments.read("--rtt"))
    {
      view1->addEventHandler(new RTTEventHandler(width, height));
      view2->addEventHandler(new RTTEventHandler(width, height));
    }

    return viewer.run();
}

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to