Thursday, January 12, 2012

Render-to-texture in OpenSceneGraph

 // Create a render-to-texture camera with an absolute
 // reference frame and pre-render
 osg::ref_ptr<osg::Camera> camera = new osg::Camera();
 camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
 camera->setRenderOrder(osg::Camera::PRE_RENDER);

 // Set the camera's projection matrix to reflect the
 // world of the geometries that will appear in the texture
 camera->setProjectionMatrixAsOrtho2D(minx, maxx, miny, maxy);

 //Set the camera's viewport to the same size of the texture
 camera->setViewport(0, 0, textureWidth, textureHeight);

 // Set the camera's clear color and masks
 camera->setClearColor(clearColor);
 camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 //Create the texture image
 osg::ref_ptr<osg::Image> image = new osg::Image();
 image->allocateImage(textureWidth,
                      textureHeight,
                      1,   // 2D texture is 1 pixel deep
                      GL_RGBA,
                      GL_UNSIGNED_BYTE);
 image->setInternalTextureFormat(GL_RGBA8);

 // Create the texture object and set the image
 osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D();
 texture2D->setImage(image);

 // Attach the texture to the camera. You can also attach
 // the image to the camera instead. Attaching the image may
 // work better in the Windows Remote Desktop
 camera->attach(osg::Camera::COLOR_BUFFER, texture2D.get());

 // Add the geometries that will appear in the texture to the camera
 camera->addChild(geometriesInTexture);

 // Create a geode to display the texture
 osg::ref_ptr<osg::Geode> geode = new osg::Geode();

 // Create a geometry for the geode
 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
 geode->addDrawable(geometry);

 // The coordinates can be different if we want to display the
 // texture at a location different from the coordinates of the
 // geometries inside the texture
 osg::ref_ptr<osg::Vec3Array> vertexArray = new osg::Vec3Array();
 vertexArray->push_back(osg::Vec3(minx, miny, minz));
 vertexArray->push_back(osg::Vec3(maxx, miny, minz));
 vertexArray->push_back(osg::Vec3(maxx, maxy, minz));
 vertexArray->push_back(osg::Vec3(minx, maxy, minz));
 geometry->setVertexArray(vertexArray);

 // The geometry color for the texture mapping should be white
 // (1.f, 1.f, 1.f, 1.f) so that color blending won't affect
 // the texture real color
 osg::ref_ptr<osg::Vec4Array> colorArray = new osg::Vec4Array();
 colorArray->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f));
 geometry->setColorArray(colorArray);
 geometry->setColorBinding(osg::Geometry::BIND_OVERALL);

 // We are using the entire texture by using the four corners
 // of the texture coordinates
 osg::ref_ptr<osg::Vec2Array> texCoordArray = new osg::Vec2Array();
 texCoordArray->push_back(osg::Vec2(0.f, 0.f));
 texCoordArray->push_back(osg::Vec2(1.f, 0.f));
 texCoordArray->push_back(osg::Vec2(1.f, 1.f));
 texCoordArray->push_back(osg::Vec2(0.f, 1.f));
 geometry->setTexCoordArray(0, texCoordArray);

 // We always create a square texture.
 geometry->addPrimitiveSet(
    new osg::DrawArrays(GL_TRIANGLE_FAN, 0, 4));

 // Add the texture to the geode
 geode->getOrCreateStateSet()->setTextureAttributeAndModes(
    0, texture2D, osg::StateAttribute::ON);

 // Make sure that we are using color blending
 // and the transparent bin, since the features may not
 // cover the entire texture and the empty
 // space should be transparent.
 geode->getOrCreateStateSet()->setRenderingHint(
    osg::StateSet::TRANSPARENT_BIN);
 osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
 blendFunc->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 geode->getOrCreateStateSet()->setAttributeAndModes(blendFunc);

 // Add both the rtt camera and the geode to the scene graph
 sceneGraph->addChild(camera);
 sceneGraph->addChild(geode);

* NOTE: If we only want to render one frame on the texture, we can remove the camera from the scene graph after the frame is rendered. The geode will still display the static texture in the scene graph properly.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.