OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
WGEPostprocessingNode.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include "../../common/WPropertyHelper.h"
00026 
00027 #include "../shaders/WGEShaderPropertyDefineOptions.h"
00028 #include "../WGEUtils.h"
00029 
00030 #include "WGEPostprocessingNode.h"
00031 
00032 WGEPostprocessingNode::WGEPostprocessingNode( osg::ref_ptr< osg::Camera > reference, size_t width, size_t height, bool noHud ):
00033     osg::Switch(),
00034     m_offscreen( new WGEOffscreenRenderNode( reference, width, height, noHud ) ),
00035     m_childs( new WGEGroupNode() ),
00036     m_postProcessShader( new WGEShader( "WGEPostprocessor" ) ),
00037     m_properties( boost::shared_ptr< WProperties >( new WProperties( "Post-processing", "Post-processing properties" ) ) )
00038 {
00039     // create both render pass
00040     m_render = m_offscreen->addGeometryRenderPass(
00041         m_childs,
00042         "Rendered"
00043     );
00044     m_postprocess = m_offscreen->addFinalOnScreenPass( m_postProcessShader, "Post-processed" );
00045 
00046     // link them together with the corresponding textures
00047     osg::ref_ptr< osg::Texture2D > renderColorTexture = m_render->attach( osg::Camera::COLOR_BUFFER0 );
00048     osg::ref_ptr< osg::Texture2D > renderNormalTexture = m_render->attach( osg::Camera::COLOR_BUFFER1 );
00049     osg::ref_ptr< osg::Texture2D > renderDepthTexture = m_render->attach( osg::Camera::DEPTH_BUFFER );
00050     m_postprocess->bind( renderColorTexture, 0 );
00051     m_postprocess->bind( renderNormalTexture, 1 );
00052     m_postprocess->bind( renderDepthTexture, 2 );
00053 
00054     // add the offscreen renderer and the original node to the switch
00055     addChild( m_childs );
00056     addChild( m_offscreen );
00057 
00058     // some info text:
00059     m_infoText = m_properties->addProperty( "Hint", "This is for advanced users.",
00060         std::string( "The post-processing has to be seen as facility to create appealing images. The here offered options are not all "
00061                      "possibilities. The most powerful effects can be achieved by using custom combinations (using custom GLSL code) of "
00062                      "post-processors and is recommended for <b>advanced users</b> only." )
00063     );
00064     m_infoText->setPurpose( PV_PURPOSE_INFORMATION );
00065 
00066     // add some properties here:
00067     m_active = m_properties->addProperty( "Enable", "If set, post-processing is enabled.", true );
00068     m_showHUD = m_properties->addProperty( "Show HUD", "If set, the intermediate textures are shown.", false );
00069 
00070     // Post-processings:
00071     // First: Create a list with name, description and shader define which is used to enable it
00072     typedef WGEShaderPropertyDefineOptionsTools::NameDescriptionDefineTuple Tuple;
00073     std::vector< Tuple > namesAndDefs;
00074     namesAndDefs.push_back( Tuple( "Color Only",   "No Post-Processing.",                               "WGE_POSTPROCESSOR_COLOR" ) );
00075     namesAndDefs.push_back( Tuple( "Smoothed Color", "Smoothed Color Image using Gauss Filter.",        "WGE_POSTPROCESSOR_GAUSSEDCOLOR" ) );
00076     namesAndDefs.push_back( Tuple( "PPL - Phong",   "Per-Pixel-Lighting using Phong.",                  "WGE_POSTPROCESSOR_PPLPHONG" ) );
00077     namesAndDefs.push_back( Tuple( "Cel-Shading",  "Under-sampling of the color for cartoon-like shading.", "WGE_POSTPROCESSOR_CELSHADING" ) );
00078     namesAndDefs.push_back( Tuple( "Depth-Cueing", "Use the Depth to fade out the pixel's brightness.", "WGE_POSTPROCESSOR_DEPTHFADING" ) );
00079     namesAndDefs.push_back( Tuple( "Edge",         "Edge of Rendered Geometry.",                        "WGE_POSTPROCESSOR_EDGE" ) );
00080     namesAndDefs.push_back( Tuple( "Depth",        "Depth Value only.",                                 "WGE_POSTPROCESSOR_DEPTH" ) );
00081     namesAndDefs.push_back( Tuple( "Smoothed Depth", "Gauss-Smoothed Depth Value only.",                "WGE_POSTPROCESSOR_GAUSSEDDEPTH" ) );
00082     namesAndDefs.push_back( Tuple( "Normal",       "Geometry Normal.",                                  "WGE_POSTPROCESSOR_NORMAL" ) );
00083     namesAndDefs.push_back( Tuple( "Custom", "Provide Your Own Post-processing-Code.",                  "WGE_POSTPROCESSOR_CUSTOM" ) );
00084 
00085     // Second: create the Shader option object and the corresponding property automatically:
00086     WGEShaderPropertyDefineOptions< WPropSelection >::SPtr activePostprocessorsOpts(
00087         WGEShaderPropertyDefineOptionsTools::createSelection(
00088             "Post-processors",
00089             "Select the post-processings you want.",
00090             m_properties,
00091             namesAndDefs
00092         )
00093     );
00094     m_activePostprocessors = activePostprocessorsOpts->getProperty();
00095     // avoid that a user selects nothing
00096     WPropertyHelper::PC_NOTEMPTY::addTo( m_activePostprocessors );
00097 
00098     // let the props control some stuff
00099     addUpdateCallback( new WGESwitchCallback< WPropBool >( m_active ) );
00100     m_offscreen->getTextureHUD()->addUpdateCallback( new WGENodeMaskCallback( m_showHUD ) );
00101     // let the activePostprocessors property control the options in the shader:
00102     m_postProcessShader->addPreprocessor( activePostprocessorsOpts );
00103 }
00104 
00105 WGEPostprocessingNode::~WGEPostprocessingNode()
00106 {
00107     // cleanup
00108     m_render->detach( osg::Camera::COLOR_BUFFER0 );
00109     m_render->detach( osg::Camera::COLOR_BUFFER1 );
00110 }
00111 
00112 WPropGroup WGEPostprocessingNode::getProperties() const
00113 {
00114     return m_properties;
00115 }
00116 
00117 void WGEPostprocessingNode::insert( osg::ref_ptr< osg::Node > node, WGEShader::RefPtr shader )
00118 {
00119     // the shader needs an own preprocessor.
00120     WGEShaderPreprocessor::SPtr preproc( new WGEShaderPropertyDefineOptions< WPropBool >(
00121         m_active, "WGE_POSTPROCESSING_DISABLED", "WGE_POSTPROCESSING_ENABLED" )
00122     );
00123 
00124     // we need to inject some code to the shader at this point.
00125     shader->addPreprocessor( preproc );
00126 
00127     // do it thread-safe as we promise to be thread-safe
00128     NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
00129     // to keep track of which node is associated with which shader and preprocessor:
00130     w->get()[ node ] = std::make_pair( shader, preproc );
00131 
00132     // insert node to group node of all children
00133     m_childs->insert( node );
00134 }
00135 
00136 void WGEPostprocessingNode::remove( osg::ref_ptr< osg::Node > node )
00137 {
00138     // do it thread-safe as we promise to be thread-safe
00139     NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
00140 
00141     // remove the item from our map
00142     NodeShaderAssociation::Iterator item = w->get().find( node );
00143 
00144     if( item != w->get().end() )
00145     {
00146         // we need to remove the preprocessor from the shader.
00147         ( *item ).second.first->removePreprocessor( ( *item ).second.second );
00148         w->get().erase( item );
00149     }
00150 
00151     // although we may not find the node in our association list, try to remove it
00152     m_childs->remove( node );
00153 }
00154 
00155 void WGEPostprocessingNode::clear()
00156 {
00157     // do it thread-safe as we promise to be thread-safe
00158     NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
00159 
00160     // remove from node-shader association list
00161     for( NodeShaderAssociation::Iterator iter = w->get().begin(); iter != w->get().end(); ++iter )
00162     {
00163         ( *iter ).second.first->removePreprocessor( ( *iter ).second.second );
00164     }
00165     w->get().clear();
00166 
00167     // remove the node from the render group
00168     m_childs->clear();
00169 }
00170 
00171 void WGEPostprocessingNode::setEnabled( bool enable )
00172 {
00173     m_active->set( enable );
00174 }
00175 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends