Hi,
I'm currently implementing parts of a distributed rendering framework which uses OSG amongst other render nodes. Rendering, compositing (on CPU) and displaying assembled frame buffers already works. One current task is to move the composition of tiles/objects from CPU to GPU using OSG. I try to achieve this using 2 render target textures for ping pong rendering like in the osggameoflife example, the current target attached to the camera, the last target bound to a screen aligned quad facing the camera. Tiles that yet have to be composited are bound to a smaller quad in front of the screen aligned quad, thus the old rtt plus the new tile are rendered to the current RTT. After each tile the textures are swapped. For object composition based on depth this approach has to be modified later, but the basic setup is the same. When the full frame is assembled a second camera is used to read back the assembled frame buffer. All this works fine for the first two tiles, but then both RTTs are cleared (completely black - not even clear color) before rendering/composition continues. To narrow down the problem i tried the same approach with more than 2 textures, but to my surprise it still cleared all textures after two tiles and then again after every single tile until all textures have been used once. Afterwards the pattern repeated itself. If only two tiles need to be composited the textures get cleared before read back, for some other amounts of tiles a composited image with one or two visible tiles is read back, the rest of the frame is just black. Setting the OSGNOTIFYLEVEL to info or even debug did not reveal any errors. The incoming and outgoing frame buffers aren't the problem either, as reading back into such buffers works for our OSGRenderNode and displaying such buffers on a screen aligned quad works for our OSGDisplayNode as well.

Does anyone have any idea why my RTTs get cleared regularly? Hopefully someone here can help me with this problem.

I'm using OSG 2.8.2 (with animationnode and ply plugin from the dev branches) under Ubuntu 9.04 (64bit) with two NVidia 9600GT (each with its own X screen to distribute render nodes to GPUs, but the AssemblyNode is set to screen 0). I have attached the (in my opinion) relevant code fragments below. I could attach the full source code for this node if required, but unfortunately i cannot provide the rest of the framework and its dependencies for testing as it is too large and i'm not even sure whether i would be allowed to do that ;).

Best regards and thanks in advance,
Luciano


The following code is used for initializing images/textures and cameras:

//initialize images/textures
        m_image = new osg::Image; //for read back after composition
        m_tile_image = new osg::Image; //holds the newest tile to be composited
        m_clear_image[0] = new osg::Image; //empty images used to
        m_clear_image[1] = new osg::Image; //initialize rtts
        m_image_tex = new osg::TextureRectangle; //tile texture
        m_render_texture[0] = new osg::TextureRectangle; //rtt1
        m_render_texture[1] = new osg::TextureRectangle; //rtt2
        
        //m_type currently is GL_RGB
        //m_x/y_resolution is the full frame resolution
        //m_tile_width/height is the tile resolution
m_image->allocateImage(m_x_resolution, m_y_resolution, 1, m_type, GL_UNSIGNED_BYTE); //full frame resolution m_tile_image->allocateImage(m_tile_width, m_tile_height, 1, m_type, GL_UNSIGNED_BYTE); //tile resolution m_clear_image[0]->allocateImage(m_x_resolution, m_y_resolution, 1, m_type, GL_UNSIGNED_BYTE); m_clear_image[1]->allocateImage(m_x_resolution, m_y_resolution, 1, m_type, GL_UNSIGNED_BYTE);
        
        //tile texture
        m_image_tex->setTextureSize(m_tile_width, m_tile_height);
        m_image_tex->setInternalFormat(m_type);
        m_image_tex->setImage(m_tile_image.get());
        
        //RTTs
        m_render_texture[0]->setTextureSize(m_x_resolution, m_y_resolution);
        m_render_texture[0]->setInternalFormat(m_type);
        m_render_texture[0]->setImage(m_clear_image[0].get());
        m_render_texture[0]->setUnRefImageDataAfterApply(false);
m_render_texture[1]->setTextureSize(m_x_resolution, m_y_resolution);
        m_render_texture[1]->setInternalFormat(m_type);
        m_render_texture[1]->setImage(m_clear_image[1].get());
        m_render_texture[1]->setUnRefImageDataAfterApply(false);

//set up camera to always show our textured quad without any rotation.
//FRAME_BUFFER is used for debug display, using FBO results in the same texture clearing problem
{
        m_tile_camera = new osg::Camera();
        m_tile_camera->setGraphicsContext(gc.get());
        m_tile_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER)
        m_tile_camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        m_tile_camera->setClearColor(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
        
m_tile_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
m_tile_camera->setProjectionMatrixAsOrtho( 0.f, m_x_resolution, 0.f, m_y_resolution, 0.1, 500.f );
        m_tile_camera->setViewMatrix(osg::Matrix::identity());
        m_tile_camera->setViewport( 0, 0, m_x_resolution, m_y_resolution );
m_tile_camera->addChild(m_frame_geode.get()); //screen aligned quad used for last rtt m_tile_camera->addChild(m_matrix.get()); //translated quad used for incoming tile texture

                m_root->addChild(m_tile_camera.get());
}
        
//this camera is only used to read back the fully assembled frame.
{
        m_camera = new osg::Camera();
        
m_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
        m_camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        m_camera->setClearColor( osg::Vec4(0.3f, 0.0f, 0.0f, 1.0f) );
        
m_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
m_camera->setProjectionMatrixAsOrtho( 0.f, m_x_resolution, 0.f, m_y_resolution, 0.1, 500.f );
        m_camera->setViewMatrix(osg::Matrix::identity());
        m_camera->setViewport( 0, 0, m_x_resolution, m_y_resolution );
        m_camera->setRenderOrder( osg::Camera::POST_RENDER );
m_camera->addChild(m_frame_geode.get()); //screen aligned quad used for last rtt
        }



This is the code which gets called whenever a new tile arrives at the AssemblyNode:

//set color and depth image to in_buffer data
//this step is needed because we cannot assign buffer data to textures directly //in_buffer contains a memory block containing an image rendered by OSG or any of our other render nodes m_tile_image->setImage(m_tile_width, m_tile_height, 1, m_type, m_type, GL_UNSIGNED_BYTE, (unsigned char*) in_buffer->getData(), osg::Image::NO_DELETE);

m_image_tex->setImage(m_tile_image.get());

//translate tile quad to correct position
m_matrix->setMatrix(osg::Matrix::translate(input_data.m_tile_x_position, input_data.m_tile_y_position, 0.1));

//bind last rtt to screen aligned quad
m_frame_quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, m_render_texture[m_tex_index].get(), osg::StateAttribute::ON);

//switch rtt index
if(m_tex_index == 0) m_tex_index = 1;
else m_tex_index = 0;
MESSAGE_STREAM("Render target texture index " << m_tex_index << endl);

//bind tile texture to tile quad
m_tile_quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, m_image_tex.get(), osg::StateAttribute::ON);//tile

//setup camera
m_tile_camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER), m_render_texture[m_tex_index].get());

//composite/render
m_renderer->frame();

//detach textures
//detaching or not did not make any difference
//m_camera->detach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER));
//m_tile_quad->getOrCreateStateSet()->removeTextureAttribute(0, m_image_tex->getType()); //m_frame_quad->getOrCreateStateSet()->removeTextureAttribute(0, m_render_texture[m_tex_index?0:1]->getType());
//m_clear_image[m_tex_index]->dirty();

//release received tile buffer
in_buffer->release();



And finally this code is used to read back the assembled frame after an endOfFrame event (re-using the render camera for read back did not work, so i've used another camera) :

MESSAGE_STREAM("End of frame> readback from GPU> texture index " << m_tex_index << endl);
        int buffer_size = m_x_resolution * m_y_resolution * m_color_bpp/8;
        m_out_buffer = getNewBuffer(buffer_size);
        m_out_buffer->setUsed(buffer_size);
                        
m_image->setImage(m_x_resolution, m_y_resolution, 1, m_type, m_type, GL_UNSIGNED_BYTE, (unsigned char*) m_out_buffer->getData(), osg::Image::NO_DELETE);
                
        //bind last used render target texture to screen aligned quad
m_frame_quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, m_render_texture[m_tex_index].get(), osg::StateAttribute::ON);
                
        //attach image to camera for read back
        m_camera->attach(osg::Camera::COLOR_BUFFER, m_image.get(), 0, 0);
                
        //add camera to scene graph
        //m_camera faces the screen aligned quad
        m_root->addChild(m_camera.get());
        m_root->removeChild(m_tile_camera.get());
                
        //read back image from GPU
        m_renderer->frame();
                
        //change cameras
        m_root->addChild(m_tile_camera.get());
        m_root->removeChild(m_camera.get());
                
        //reset textures - todo
        //m_render_texture[0]->setImage(m_clear_image[0].get());
        //m_render_texture[1]->setImage(m_clear_image[1].get());
        
        //send out_buffer to a display node (e.g. OSGDisplayNode)       
        return m_out_buffer;
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to