From d32cd203a25f87690278988b166ace88b080b039 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 9 Dec 2014 19:20:05 +0000 Subject: [PATCH] From Wand Rui, "I've rewritten the osgblenddrawbuffers example to use the new BlendFunci and Capability classes. Hope it will tell others how to make use of the new functionality and why they are important in modern MRT-based applications." git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14587 16af8721-9629-0410-8352-f15c8da7e697 --- examples/CMakeLists.txt | 1 + examples/osgblenddrawbuffers/CMakeLists.txt | 7 + .../osgblenddrawbuffers.cpp | 147 ++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 examples/osgblenddrawbuffers/CMakeLists.txt create mode 100644 examples/osgblenddrawbuffers/osgblenddrawbuffers.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index eec6791cb..d2d383da3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -27,6 +27,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgautocapture) ADD_SUBDIRECTORY(osgautotransform) ADD_SUBDIRECTORY(osgbillboard) + ADD_SUBDIRECTORY(osgblenddrawbuffers) ADD_SUBDIRECTORY(osgblendequation) ADD_SUBDIRECTORY(osgcallback) ADD_SUBDIRECTORY(osgcamera) diff --git a/examples/osgblenddrawbuffers/CMakeLists.txt b/examples/osgblenddrawbuffers/CMakeLists.txt new file mode 100644 index 000000000..8f39db418 --- /dev/null +++ b/examples/osgblenddrawbuffers/CMakeLists.txt @@ -0,0 +1,7 @@ +#this file is automatically generated + + +SET(TARGET_SRC osgblenddrawbuffers.cpp ) +SET(TARGET_ADDED_LIBRARIES osgGA ) +#### end var setup ### +SETUP_EXAMPLE(osgblenddrawbuffers) diff --git a/examples/osgblenddrawbuffers/osgblenddrawbuffers.cpp b/examples/osgblenddrawbuffers/osgblenddrawbuffers.cpp new file mode 100644 index 000000000..91ef96dc8 --- /dev/null +++ b/examples/osgblenddrawbuffers/osgblenddrawbuffers.cpp @@ -0,0 +1,147 @@ +/* OpenSceneGraph example, osgblenddrawbuffers. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +osg::Camera* createMRTCamera( std::vector& attachedTextures ) +{ + osg::ref_ptr camera = new osg::Camera; + camera->setClearColor( osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); + camera->setClearMask( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); + camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); + camera->setRenderOrder( osg::Camera::PRE_RENDER ); + + for ( int i=0; i<4; ++i ) + { + osg::Texture2D* tex = new osg::Texture2D; + tex->setTextureSize( 1024, 1024 ); + tex->setInternalFormat( GL_RGBA ); + tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR ); + tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR ); + attachedTextures.push_back( tex ); + + camera->setViewport( 0, 0, tex->getTextureWidth(), tex->getTextureHeight() ); + camera->attach( osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), tex ); + } + return camera.release(); +} + +osg::Camera* createHUDCamera( double left, double right, double bottom, double top ) +{ + osg::ref_ptr camera = new osg::Camera; + camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF ); + camera->setClearMask( GL_DEPTH_BUFFER_BIT ); + camera->setRenderOrder( osg::Camera::POST_RENDER ); + camera->setAllowEventFocus( false ); + camera->setProjectionMatrix( osg::Matrix::ortho2D(left, right, bottom, top) ); + camera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); + return camera.release(); +} + +int main( int argc, char **argv ) +{ + osg::ArgumentParser arguments(&argc, argv); + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates how to enable/disable blending on specified draw buffers in multi-rendering-target cases."); + + std::vector textures; + bool useGlobalBlending = false; + if ( arguments.read("--no-draw-buffers") ) useGlobalBlending = true; + + // Create a camera to output multi-rendering-targets (MRT) + osg::Camera* mrtCam = createMRTCamera( textures ); + mrtCam->addChild( osgDB::readNodeFile("cessna.osgt") ); + + // Create shader program to be used + const char* mrtFragmentCode = { + "void main() {\n" + " gl_FragData[0] = gl_Color * vec4(1.0, 1.0, 1.0, 0.7);\n" + " gl_FragData[1] = vec4(0.0, 1.0, 1.0, 0.0);\n" + " gl_FragData[2] = vec4(1.0, 0.0, 1.0, 0.3);\n" + " gl_FragData[3] = vec4(1.0, 1.0, 0.0, 1.0);\n" + "}\n" + }; + osg::ref_ptr program = new osg::Program; + program->addShader( new osg::Shader(osg::Shader::FRAGMENT, mrtFragmentCode) ); + + osg::StateSet* ss = mrtCam->getOrCreateStateSet(); + ss->setAttributeAndModes( program.get() ); + + // Apply blending to the original scene in MRT + if ( !useGlobalBlending ) + { + // Only enable blending on the first draw buffer so other three outputs are + // totally opaque, which is important for MRT cases + ss->setAttribute( new osg::Enablei(GL_BLEND, 0) ); + ss->setAttribute( new osg::Disablei(GL_BLEND, 1) ); + ss->setAttribute( new osg::Disablei(GL_BLEND, 2) ); + ss->setAttribute( new osg::Disablei(GL_BLEND, 3) ); + + // Accept different blend/colormask attributes on multiple render targets + osg::ref_ptr blend0 = new osg::BlendFunci(0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + osg::ref_ptr colormask3 = new osg::ColorMaski(3, false, true, false, true); + ss->setAttribute( blend0.get() ); + ss->setAttributeAndModes( colormask3.get() ); + } + else + { + // When separated blending is disabled, all rendering targets will be affected + // by its alpha channel and you will see each output blended with the background. + // + // This causes a big program in situations like deferred shading because we may + // have to save different scene data to MRT 'GBuffer', in which alpha channels are + // used to store certain attributes rather than opacity. These attributes can be + // reused in following post-processing steps. + // + // For such targets, alpha blending must be disabled; otherwise it will mess the + // output. That is why this example exists! + osg::ref_ptr blend = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ss->setAttributeAndModes( blend.get() ); + } + + // Create some quads to be shown on screen to contain the MRT result + osg::ref_ptr quad = new osg::Geode; + for ( unsigned int i=0; igetOrCreateStateSet()->setTextureAttributeAndModes( 0, textures[i] ); + quad->addDrawable( geom ); + } + + osg::Camera* hudCam = createHUDCamera( 0.0, 1.0, 0.0, 1.0 ); + hudCam->addChild( quad.get() ); + + // Construct scene graph and viewer + osg::ref_ptr root = new osg::Group; + root->addChild( mrtCam ); + root->addChild( hudCam ); + + osgViewer::Viewer viewer; + viewer.setSceneData( root.get() ); + return viewer.run(); +}