1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
25
#include "../../common/WPropertyHelper.h"
27
#include "../shaders/WGEShaderPropertyDefineOptions.h"
28
#include "../WGEUtils.h"
30
#include "WGEPostprocessingNode.h"
32
WGEPostprocessingNode::WGEPostprocessingNode( osg::ref_ptr< osg::Camera > reference, size_t width, size_t height, bool noHud ):
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" ) ) )
39
// create both render pass
40
m_render = m_offscreen->addGeometryRenderPass(
44
m_postprocess = m_offscreen->addFinalOnScreenPass( m_postProcessShader, "Post-processed" );
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 );
54
// add the offscreen renderer and the original node to the switch
56
addChild( m_offscreen );
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." )
64
m_infoText->setPurpose( PV_PURPOSE_INFORMATION );
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 );
71
// First: Create a list with name, description and shader define which is used to enable it
72
typedef WGEShaderPropertyDefineOptionsTools::NameDescriptionDefineTuple Tuple;
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" ) );
85
// Second: create the Shader option object and the corresponding property automatically:
86
WGEShaderPropertyDefineOptions< WPropSelection >::SPtr activePostprocessorsOpts(
87
WGEShaderPropertyDefineOptionsTools::createSelection(
89
"Select the post-processings you want.",
94
m_activePostprocessors = activePostprocessorsOpts->getProperty();
95
// avoid that a user selects nothing
96
WPropertyHelper::PC_NOTEMPTY::addTo( m_activePostprocessors );
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 );
105
WGEPostprocessingNode::~WGEPostprocessingNode()
108
m_render->detach( osg::Camera::COLOR_BUFFER0 );
109
m_render->detach( osg::Camera::COLOR_BUFFER1 );
112
WPropGroup WGEPostprocessingNode::getProperties() const
117
void WGEPostprocessingNode::insert( osg::ref_ptr< osg::Node > node, WGEShader::RefPtr shader )
119
// the shader needs an own preprocessor.
120
WGEShaderPreprocessor::SPtr preproc( new WGEShaderPropertyDefineOptions< WPropBool >(
121
m_active, "WGE_POSTPROCESSING_DISABLED", "WGE_POSTPROCESSING_ENABLED" )
124
// we need to inject some code to the shader at this point.
125
shader->addPreprocessor( preproc );
127
// do it thread-safe as we promise to be thread-safe
128
NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
129
// to keep track of which node is associated with which shader and preprocessor:
130
w->get()[ node ] = std::make_pair( shader, preproc );
132
// insert node to group node of all children
133
m_childs->insert( node );
136
void WGEPostprocessingNode::remove( osg::ref_ptr< osg::Node > node )
138
// do it thread-safe as we promise to be thread-safe
139
NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
141
// remove the item from our map
142
NodeShaderAssociation::Iterator item = w->get().find( node );
144
if( item != w->get().end() )
146
// we need to remove the preprocessor from the shader.
147
( *item ).second.first->removePreprocessor( ( *item ).second.second );
148
w->get().erase( item );
151
// although we may not find the node in our association list, try to remove it
152
m_childs->remove( node );
155
void WGEPostprocessingNode::clear()
157
// do it thread-safe as we promise to be thread-safe
158
NodeShaderAssociation::WriteTicket w = m_nodeShaderAssociation.getWriteTicket();
160
// remove from node-shader association list
161
for( NodeShaderAssociation::Iterator iter = w->get().begin(); iter != w->get().end(); ++iter )
163
( *iter ).second.first->removePreprocessor( ( *iter ).second.second );
167
// remove the node from the render group
171
void WGEPostprocessingNode::setEnabled( bool enable )
173
m_active->set( enable );