OpenWalnut
1.2.5
|
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