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