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