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