Hi Robert -- I'd like to make a change to how multisampled FBO works. In short summary: I want to allow applications to optionally disable the depth buffer bit in the call to glBlitFramebuffer, so that only color is copied.

In order to render multisampled to a texture, (with pre-GL3.2) we need to render into a multisampled renderbuffer then glBlitFramebuffer into the texture. (I've attached some very simple code that exercises this code path.) To support glBlitFramebuffer, there needs to be two FBOs: one with multisampled renderbuffers attached (call it "FBO A"), and one with the texture attached (call it "FBO B").

OSG creates these FBOs during RenderStage::runCameraSetUp. OSG correctly assumes that I need both color and depth multisampled renderbuffers attached to FBO A. This is correct and is exactly what I want. OSG creates this for me.

However, OSG _incorrectly_ assumes that I also want a depth renderbuffer attached to FBO B, and it creates and attaches one. In fact, this is not always necessary and is wasteful of GPU memory when it's not needed. I'm only interested in the color buffer, and I don't need the depth buffer.

The problem is compounded during the glBlitFramebuffer call (occurs in RenderStage::drawInner). The code determines that since both FBO A and FBO B have color and depth attachments, that it must blit both color and depth. Specifically, when it calls glBlitFramebuffer, the mask parameter is (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT). This is unnecessary and inefficient. It causes the blit to copy extra data that is not needed.

I understand that the depth attachment to FBO B might be needed in some cases, and it's impossible for OSG to know whether it's needed or not needed. So, I propose that OSG continue to work this way by default, but osg::Camera should support some type of interface that allows the application to tell OSG that the depth attachment in FBO B is not needed, so that OSG won't bother to create it and won't include it in the blit.

I'm on vacation/holiday Oct 4-9, and I'll be glad to make this change after I return from my break.

All this investigation was done with v2.8.2. I've been unable to see how things work with current svn head due to server issues and recent code changes that prevent me from building (as noted in another post).

Finally, I'm going to need this change in order to work around an apparent driver bug that I'm encountering on OSX with dual GF8800 cards driving four monitors. If the resolve blit is performed with both depth and color, it hangs my entire desktop (yuck). Removing the unnecessary depth bit from the blit call avoids this issue. I'm still reviewing the OpenGL spec to understand whether this is a driver bug or a problem with OSG's usage.

Anyhow, let me know what you think. Thanks for your review time on this change.
--
Paul Martz
Skew Matrix Software LLC
_http://www.skew-matrix.com_ <http://www.skew-matrix.com/>
+1 303 859 9466

// Copyright (c) 2008 Skew Matrix Software LLC. All rights reserved.

#include <osg/Node>
#include <osg/Camera>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>

#include <string>


const int winW( 800 ), winH( 600 );


osg::Node*
postRender( osgViewer::Viewer& viewer )
{
    osg::Camera* rootCamera( viewer.getCamera() );

    // Create the texture; we'll use this as our color buffer.
    // Note it has no image data; not required.
    osg::Texture2D* tex = new osg::Texture2D;
    tex->setTextureWidth( winW );
    tex->setTextureHeight( winH );
    tex->setInternalFormat( GL_RGBA );
    tex->setBorderWidth( 0 );
    tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
    tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST );

    // Attach the texture to the camera. Tell it to use multisampling.
    // Internally, OSG allocates a multisampled renderbuffer, renders to it,
    // and at the end of the frame performs a BlitFramebuffer into our texture.
    rootCamera->attach( osg::Camera::COLOR_BUFFER0, tex, 0, 0, false, 8, 8 );
    rootCamera->setRenderTargetImplementation( 
osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::FRAME_BUFFER );


    // Configure postRenderCamera to draw fullscreen textured quad
    osg::ref_ptr< osg::Camera > postRenderCamera( new osg::Camera );
    postRenderCamera->setClearColor( osg::Vec4( 0., 1., 0., 1. ) ); // should 
never see this.
    postRenderCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER, 
osg::Camera::FRAME_BUFFER );

    postRenderCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
    postRenderCamera->setRenderOrder( osg::Camera::POST_RENDER );
    postRenderCamera->setViewMatrix( osg::Matrixd::identity() );
    postRenderCamera->setProjectionMatrix( osg::Matrixd::identity() );

    osg::Geode* geode( new osg::Geode );
    geode->addDrawable( osg::createTexturedQuadGeometry(
        osg::Vec3( -1,-1,0 ), osg::Vec3( 2,0,0 ), osg::Vec3( 0,2,0 ) ) );
    geode->getOrCreateStateSet()->setTextureAttributeAndModes(
        0, tex, osg::StateAttribute::ON );
    geode->getOrCreateStateSet()->setMode( GL_LIGHTING, 
osg::StateAttribute::OFF );

    postRenderCamera->addChild( geode );

    return( postRenderCamera.release() );
}

int
main( int argc, char** argv )
{
    osg::setNotifyLevel( osg::INFO );

    osg::ref_ptr< osg::Group > root( new osg::Group );
    root->addChild( osgDB::readNodeFile( "cow.osg" ) );
    if( root->getNumChildren() == 0 )
        return( 1 );

    osgViewer::Viewer viewer;
    viewer.setThreadingModel( osgViewer::ViewerBase::SingleThreaded );
    viewer.setUpViewInWindow( 10, 30, winW, winH );
    viewer.setSceneData( root.get() );
    viewer.realize();

    root->addChild( postRender( viewer ) );

    // Clear to white to make AA extremely obvious.
    viewer.getCamera()->setClearColor( osg::Vec4( 1., 1., 1., 1. ) );

    return( viewer.run() );
}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to