OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WGEPostprocessingNode.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include "../../common/WPropertyHelper.h"
26 
27 #include "../shaders/WGEShaderPropertyDefineOptions.h"
28 #include "../WGEUtils.h"
29 
30 #include "WGEPostprocessingNode.h"
31 
32 WGEPostprocessingNode::WGEPostprocessingNode( osg::ref_ptr< osg::Camera > reference, size_t width, size_t height, bool noHud ):
33  osg::Switch(),
34  m_offscreen( new WGEOffscreenRenderNode( reference, width, height, noHud ) ),
35  m_childs( new WGEGroupNode() ),
36  m_postProcessShader( new WGEShader( "WGEPostprocessor" ) ),
37  m_properties( boost::shared_ptr< WProperties >( new WProperties( "Post-processing", "Post-processing properties" ) ) )
38 {
39  // create both render pass
40  m_render = m_offscreen->addGeometryRenderPass(
41  m_childs,
42  "Rendered"
43  );
44  m_postprocess = m_offscreen->addFinalOnScreenPass( m_postProcessShader, "Post-processed" );
45 
46  // link them together with the corresponding textures
47  osg::ref_ptr< osg::Texture2D > renderColorTexture = m_render->attach( osg::Camera::COLOR_BUFFER0 );
48  osg::ref_ptr< osg::Texture2D > renderNormalTexture = m_render->attach( osg::Camera::COLOR_BUFFER1 );
49  osg::ref_ptr< osg::Texture2D > renderDepthTexture = m_render->attach( osg::Camera::DEPTH_BUFFER );
50  m_postprocess->bind( renderColorTexture, 0 );
51  m_postprocess->bind( renderNormalTexture, 1 );
52  m_postprocess->bind( renderDepthTexture, 2 );
53 
54  // add the offscreen renderer and the original node to the switch
55  addChild( m_childs );
56  addChild( m_offscreen );
57 
58  // some info text:
59  m_infoText = m_properties->addProperty( "Hint", "This is for advanced users.",
60  std::string( "The post-processing has to be seen as facility to create appealing images. The here offered options are not all "
61  "possibilities. The most powerful effects can be achieved by using custom combinations (using custom GLSL code) of "
62  "post-processors and is recommended for <b>advanced users</b> only." )
63  );
64  m_infoText->setPurpose( PV_PURPOSE_INFORMATION );
65 
66  // add some properties here:
67  m_active = m_properties->addProperty( "Enable", "If set, post-processing is enabled.", true );
68  m_showHUD = m_properties->addProperty( "Show HUD", "If set, the intermediate textures are shown.", false );
69 
70  // Post-processings:
71  // First: Create a list with name, description and shader define which is used to enable it
73  std::vector< Tuple > namesAndDefs;
74  namesAndDefs.push_back( Tuple( "Color Only", "No Post-Processing.", "WGE_POSTPROCESSOR_COLOR" ) );
75  namesAndDefs.push_back( Tuple( "Smoothed Color", "Smoothed Color Image using Gauss Filter.", "WGE_POSTPROCESSOR_GAUSSEDCOLOR" ) );
76  namesAndDefs.push_back( Tuple( "PPL - Phong", "Per-Pixel-Lighting using Phong.", "WGE_POSTPROCESSOR_PPLPHONG" ) );
77  namesAndDefs.push_back( Tuple( "Cel-Shading", "Under-sampling of the color for cartoon-like shading.", "WGE_POSTPROCESSOR_CELSHADING" ) );
78  namesAndDefs.push_back( Tuple( "Depth-Cueing", "Use the Depth to fade out the pixel's brightness.", "WGE_POSTPROCESSOR_DEPTHFADING" ) );
79  namesAndDefs.push_back( Tuple( "Edge", "Edge of Rendered Geometry.", "WGE_POSTPROCESSOR_EDGE" ) );
80  namesAndDefs.push_back( Tuple( "Depth", "Depth Value only.", "WGE_POSTPROCESSOR_DEPTH" ) );
81  namesAndDefs.push_back( Tuple( "Smoothed Depth", "Gauss-Smoothed Depth Value only.", "WGE_POSTPROCESSOR_GAUSSEDDEPTH" ) );
82  namesAndDefs.push_back( Tuple( "Normal", "Geometry Normal.", "WGE_POSTPROCESSOR_NORMAL" ) );
83  namesAndDefs.push_back( Tuple( "Custom", "Provide Your Own Post-processing-Code.", "WGE_POSTPROCESSOR_CUSTOM" ) );
84 
85  // Second: create the Shader option object and the corresponding property automatically:
88  "Post-processors",
89  "Select the post-processings you want.",
91  namesAndDefs
92  )
93  );
94  m_activePostprocessors = activePostprocessorsOpts->getProperty();
95  // avoid that a user selects nothing
97 
98  // let the props control some stuff
99  addUpdateCallback( new WGESwitchCallback< WPropBool >( m_active ) );
100  m_offscreen->getTextureHUD()->addUpdateCallback( new WGENodeMaskCallback( m_showHUD ) );
101  // let the activePostprocessors property control the options in the shader:
102  m_postProcessShader->addPreprocessor( activePostprocessorsOpts );
103 }
104 
106 {
107  // cleanup
108  m_render->detach( osg::Camera::COLOR_BUFFER0 );
109  m_render->detach( osg::Camera::COLOR_BUFFER1 );
110 }
111 
113 {
114  return m_properties;
115 }
116 
117 void WGEPostprocessingNode::insert( osg::ref_ptr< osg::Node > node, WGEShader::RefPtr shader )
118 {
119  // the shader needs an own preprocessor.
121  m_active, "WGE_POSTPROCESSING_DISABLED", "WGE_POSTPROCESSING_ENABLED" )
122  );
123 
124  // we need to inject some code to the shader at this point.
125  shader->addPreprocessor( preproc );
126 
127  // do it thread-safe as we promise to be thread-safe
129  // to keep track of which node is associated with which shader and preprocessor:
130  w->get()[ node ] = std::make_pair( shader, preproc );
131 
132  // insert node to group node of all children
133  m_childs->insert( node );
134 }
135 
136 void WGEPostprocessingNode::remove( osg::ref_ptr< osg::Node > node )
137 {
138  // do it thread-safe as we promise to be thread-safe
140 
141  // remove the item from our map
142  NodeShaderAssociation::Iterator item = w->get().find( node );
143 
144  if( item != w->get().end() )
145  {
146  // we need to remove the preprocessor from the shader.
147  ( *item ).second.first->removePreprocessor( ( *item ).second.second );
148  w->get().erase( item );
149  }
150 
151  // although we may not find the node in our association list, try to remove it
152  m_childs->remove( node );
153 }
154 
156 {
157  // do it thread-safe as we promise to be thread-safe
159 
160  // remove from node-shader association list
161  for( NodeShaderAssociation::Iterator iter = w->get().begin(); iter != w->get().end(); ++iter )
162  {
163  ( *iter ).second.first->removePreprocessor( ( *iter ).second.second );
164  }
165  w->get().clear();
166 
167  // remove the node from the render group
168  m_childs->clear();
169 }
170 
172 {
173  m_active->set( enable );
174 }
175