OpenWalnut  1.4.0
WGEPostprocessorLineAO.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 "../shaders/WGEPropertyUniform.h"
00028 #include "../shaders/WGEShaderPropertyDefine.h"
00029 #include "WGEPostprocessorGauss.h"
00030 #include "WGEPostprocessorMergeOp.h"
00031 
00032 #include "WGEPostprocessorLineAO.h"
00033 
00034 WGEPostprocessorLineAO::WGEPostprocessorLineAO():
00035     WGEPostprocessor( "LineAO",
00036                       "LineAO is a special ambient occlusion technique optimized for dense line and tube rendering." )
00037 {
00038 }
00039 
00040 WGEPostprocessorLineAO::WGEPostprocessorLineAO( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
00041                                                           const WGEPostprocessor::PostprocessorInput& gbuffer ):
00042     WGEPostprocessor( "LineAO",
00043                       "LineAO is a special ambient occlusion technique optimized for dense line and tube rendering." )
00044 {
00045     // the LineAO algorithm has some parameters. Provide these parameters to the user
00046     WPropInt lineaoSamples = m_properties->addProperty( "Samples", "The number of samples to take in screen-space. Higher values produce better "
00047                                                                  "quality but can reduce FPS dramatically.", 32 );
00048     lineaoSamples->setMin( 1 );
00049     lineaoSamples->setMax( 128 );
00050 
00051     WPropInt lineaoScalers = m_properties->addProperty( "Hemispheres", "The number of hemispheres to sample around each pixel. Higher values "
00052                                                                        "produce better quality but can reduce FPS dramatically.", 3 );
00053     lineaoScalers->setMin( 1 );
00054     lineaoScalers->setMax( 8 );
00055 
00056     WPropDouble lineaoRadiusSS = m_properties->addProperty( "Radius", "The radius around the pixel to sample for occluders in pixels.", 2.0 );
00057     lineaoRadiusSS->setMin( 0.0 );
00058     lineaoRadiusSS->setMax( 100.0 );
00059 
00060     WPropDouble lineaoTotalStrength = m_properties->addProperty( "Total Strength", "The strength of the effect. Higher values emphasize the effect.",
00061                                                                                  1.0 );
00062     lineaoTotalStrength->setMin( 0.0 );
00063     lineaoTotalStrength->setMax( 5.0 );
00064 
00065     WPropDouble lineaoDensityWeight = m_properties->addProperty( "Density Weight", "The strength of the occluder influence in relation to the "
00066                                                                                    "geometry density. The higher the value, the larger the "
00067                                                                                    "influence. Low values remove the drop-shadow effect. "
00068                                                                                    "This defines the influence of one occluder to the overall "
00069                                                                                    "AO effect.", 1.0 );
00070     lineaoDensityWeight->setMin( 0.001 );
00071     lineaoDensityWeight->setMax( 2.0 );
00072 
00073     WPropBool lineaoUseGaussedNDMap = m_properties->addProperty( "Use Gaussed ND-Map", "When enabling, the LineAO algorithm uses a scale-base "
00074                                                                                        "pyramid for sampling the depth and normal maps. Unlike "
00075                                                                                        "described in the paper, this is turned off by default to "
00076                                                                                        "ensure that details of far occluders are retained (the "
00077                                                                                        "images look crispier).", false );
00078     WPropBool lineaoUseOccluderLight = m_properties->addProperty( "Use Occluder Light", "When enabling, the LineAO algorithm uses the light "
00079                                                                                         "reflected by the occluder as contribution to ambient "
00080                                                                                         "light energy of the pixel. This creates a more realistic "
00081                                                                                         "rendering but might brighten areas you might want to stay "
00082                                                                                         "dark.", true );
00083 
00084     // NOTE: The paper proposes to use a gaussian pyramid of the depth and normal maps. We skip this step. Skipping this causes the AO to look
00085     // more crispy and more detailed at local scope.
00086 
00087     // use the standard postprocessor uber-shader
00088     WGEShader::RefPtr s = new WGEShader( "WGEPostprocessor" );
00089     s->setDefine( "WGE_POSTPROCESSOR_LINEAO" );
00090 
00091     // also add the m_effectOnly property as shader preprocessor
00092     s->addPreprocessor( m_effectOnlyPreprocessor );
00093     s->addPreprocessor( WGEShaderPreprocessor::SPtr(
00094         new WGEShaderPropertyDefine< WPropInt >( "WGE_POSTPROCESSOR_LINEAO_SCALERS", lineaoScalers ) )
00095     );
00096     s->addPreprocessor( WGEShaderPreprocessor::SPtr(
00097         new WGEShaderPropertyDefine< WPropInt >( "WGE_POSTPROCESSOR_LINEAO_SAMPLES", lineaoSamples ) )
00098     );
00099 
00100     s->addPreprocessor( WGEShaderPreprocessor::SPtr(
00101         new WGEShaderPropertyDefineOptions< WPropBool >( lineaoUseGaussedNDMap, "WGE_POSTPROCESSOR_LINEAO_USEDIRECTNDMAP",
00102                                                                                 "WGE_POSTPROCESSOR_LINEAO_USEGAUSSPYRAMID" ) )
00103     );
00104 
00105     s->addPreprocessor( WGEShaderPreprocessor::SPtr(
00106         new WGEShaderPropertyDefineOptions< WPropBool >( lineaoUseOccluderLight, "WGE_POSTPROCESSOR_LINEAO_NOOCCLUDERLIGHT",
00107                                                                                  "WGE_POSTPROCESSOR_LINEAO_OCCLUDERLIGHT" ) )
00108     );
00109 
00110     // create the LineAO rendering pass
00111     osg::ref_ptr< WGEOffscreenTexturePass > lineAOPass = offscreen->addTextureProcessingPass( s, "LineAO" );
00112     lineAOPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_lineaoDensityWeight", lineaoDensityWeight ) );
00113     lineAOPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_lineaoTotalStrength", lineaoTotalStrength ) );
00114     lineAOPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_lineaoRadiusSS", lineaoRadiusSS ) );
00115 
00116     // attach color0 output
00117     m_resultTextures.push_back( lineAOPass->attach( WGECamera::COLOR_BUFFER0, GL_RGB ) );
00118 
00119     // provide the Gbuffer input, with several mipmap levels
00120     gbuffer.m_depthTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
00121     gbuffer.m_normalTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
00122     gbuffer.m_tangentTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
00123 
00124     size_t gBufUnitOffset = gbuffer.bind( lineAOPass );
00125 
00126     // this effect needs some additional noise texture:
00127     const size_t size = 64;
00128     osg::ref_ptr< WGETexture2D > randTex = wge::genWhiteNoiseTexture( size, size, 3 );
00129     lineAOPass->bind( randTex, gBufUnitOffset );
00130 
00131     // also utilize the pre-blend scale
00132     m_effectScale->setHidden( false );
00133     lineAOPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_effectPreBlendScale", m_effectScale ) );
00134 }
00135 
00136 WGEPostprocessorLineAO::~WGEPostprocessorLineAO()
00137 {
00138     // cleanup
00139 }
00140 
00141 WGEPostprocessor::SPtr WGEPostprocessorLineAO::create( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
00142     const WGEPostprocessor::PostprocessorInput& gbuffer ) const
00143 {
00144     return WGEPostprocessor::SPtr( new WGEPostprocessorLineAO( offscreen, gbuffer ) );
00145 }