OpenWalnut  1.4.0
WGEPostprocessorSSAO.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 <osg/Camera>
00026 
00027 #include "../WGETextureUtils.h"
00028 #include "../shaders/WGEPropertyUniform.h"
00029 #include "../shaders/WGEShaderPropertyDefine.h"
00030 
00031 #include "WGEPostprocessorSSAO.h"
00032 
00033 WGEPostprocessorSSAO::WGEPostprocessorSSAO():
00034     WGEPostprocessor( "SSAO",
00035                       "SSAO is a special ambient occlusion technique." )
00036 {
00037 }
00038 
00039 WGEPostprocessorSSAO::WGEPostprocessorSSAO( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
00040                                                           const WGEPostprocessor::PostprocessorInput& gbuffer ):
00041     WGEPostprocessor( "SSAO",
00042                       "SSAO is a special ambient occlusion technique." )
00043 {
00044     // the SSAO algorithm has some parameters. Provide these parameters to the user
00045     WPropInt ssaoSamples = m_properties->addProperty( "Samples", "The number of samples to take in screen-space. Higher values produce better "
00046                                                                  "quality but can reduce FPS dramatically.", 16 );
00047     ssaoSamples->setMin( 1 );
00048     ssaoSamples->setMax( 128 );
00049 
00050     WPropDouble ssaoRadius = m_properties->addProperty( "Radius", "The radius around the pixel to sample for occluders in pixels.", 10.0 );
00051     ssaoRadius->setMin( 0.0 );
00052     ssaoRadius->setMax( 500.0 );
00053 
00054     WPropDouble ssaoTotalStrength = m_properties->addProperty( "Total Strength", "The strength of the effect. Higher values emphasize the effect.",
00055                                                                                  2.0 );
00056     ssaoTotalStrength->setMin( 0.0 );
00057     ssaoTotalStrength->setMax( 100.0 );
00058 
00059     WPropDouble ssaoStrength = m_properties->addProperty( "Strength", "This defines the influence of one occluder to the overall AO effect.", 1.0 );
00060     ssaoStrength->setMin( 0.0 );
00061     ssaoStrength->setMax( 1.0 );
00062 
00063     WPropDouble ssaoFalloff = m_properties->addProperty( "Falloff", "Define the edge at which a depth difference between two pixels is assumed to "
00064                                                                     "be non-zero.", 0.0 );
00065     ssaoFalloff->setMin( 0.0 );
00066     ssaoFalloff->setMax( 1.0 );
00067 
00068     // Use the standard postprocessor uber-shader
00069     WGEShader::RefPtr s = new WGEShader( "WGEPostprocessor" );
00070     s->setDefine( "WGE_POSTPROCESSOR_SSAO" );
00071 
00072     // also add the m_effectOnly property as shader preprocessor
00073     s->addPreprocessor( m_effectOnlyPreprocessor );
00074     s->addPreprocessor( WGEShaderPreprocessor::SPtr(
00075         new WGEShaderPropertyDefine< WPropInt >( "WGE_POSTPROCESSOR_SSAO_SAMPLES", ssaoSamples ) )
00076     );
00077 
00078     // create the rendering pass
00079     osg::ref_ptr< WGEOffscreenTexturePass > pass = offscreen->addTextureProcessingPass( s, "SSAO" );
00080     pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ssaoTotalStrength", ssaoTotalStrength ) );
00081     pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ssaoStrength", ssaoStrength ) );
00082     pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ssaoRadius", ssaoRadius ) );
00083     pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ssaoFalloff", ssaoFalloff ) );
00084 
00085     // attach color0 output
00086     m_resultTextures.push_back( pass->attach( WGECamera::COLOR_BUFFER0, GL_RGB ) );
00087 
00088     // provide the Gbuffer input
00089     size_t gBufUnitOffset = gbuffer.bind( pass );
00090 
00091     // this effect needs some additional noise texture:
00092     // some of the post-processors need some white noise, like the ssao
00093     const size_t size = 64;
00094     osg::ref_ptr< WGETexture2D > randTex = wge::genWhiteNoiseTexture( size, size, 3 );
00095     pass->bind( randTex, gBufUnitOffset );
00096 }
00097 
00098 WGEPostprocessorSSAO::~WGEPostprocessorSSAO()
00099 {
00100     // cleanup
00101 }
00102 
00103 WGEPostprocessor::SPtr WGEPostprocessorSSAO::create( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
00104     const WGEPostprocessor::PostprocessorInput& gbuffer ) const
00105 {
00106     return WGEPostprocessor::SPtr( new WGEPostprocessorSSAO( offscreen, gbuffer ) );
00107 }