Commit c755b631 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[ADD] - added GLSL code injector, offscreen gauss and merge operators ...

parent 204f5aac
......@@ -88,7 +88,14 @@ WGEPostprocessingNode::WGEPostprocessingNode( osg::ref_ptr< osg::Camera > refere
osg::ref_ptr< WGEOffscreenFinalPass > output = offscreen->addFinalOnScreenPass( new WGEShader( "WGEPostprocessorCombiner" ),
"Output" );
output->bind( processor->getOutput(), 0 );
output->bind( processor->getDepth(), 1 );
// does this processor provide a depth?
osg::ref_ptr< osg::Texture2D > depthTex = processor->getDepth();
if( !depthTex )
{
depthTex = buf.m_depthTexture;
}
output->bind( depthTex, 1 );
// add the offscreen renderer and the original node to the switch
addChild( offscreen );
......
......@@ -23,32 +23,24 @@
//---------------------------------------------------------------------------
#include <string>
#include <vector>
#include "WGEPostprocessorEdgeEnhance.h"
#include "WGEPostprocessorCelShading.h"
#include "WGEPostprocessorGauss.h"
#include "WGEPostprocessor.h"
WGEPostprocessor::WGEPostprocessor( std::string name, std::string description ):
WPrototyped(),
m_name( name ),
m_description( description )
{
}
WGEPostprocessor::WGEPostprocessor( osg::ref_ptr< WGEOffscreenRenderNode > /* offscreen */,
const WGEPostprocessor::PostprocessorInput& gbuffer,
std::string name,
std::string description ):
WPrototyped(),
m_resultTexture( gbuffer.m_colorTexture ),
m_depthTexture( gbuffer.m_depthTexture ),
m_resultTextures(),
m_depthTexture(),
m_properties( boost::shared_ptr< WProperties >( new WProperties( "Settings for " + name, "Post-processing properties" ) ) ),
m_name( name ),
m_description( description )
{
// there is always one property:
m_effectOnly = m_properties->addProperty( "Effect only", "If active, the plain effect will be shown instead a combination of effect "
m_effectOnly = m_properties->addProperty( "Effect Only", "If active, the plain effect will be shown instead a combination of effect "
"and color. This settings does not affect all postprocessors.", false );
// for convenience, also create a preprocessor for this property
......@@ -66,9 +58,14 @@ WPropGroup WGEPostprocessor::getProperties() const
return m_properties;
}
osg::ref_ptr< osg::Texture2D > WGEPostprocessor::getOutput() const
osg::ref_ptr< osg::Texture2D > WGEPostprocessor::getOutput( size_t idx ) const
{
return m_resultTextures[ idx ];
}
const std::vector< osg::ref_ptr< osg::Texture2D > >& WGEPostprocessor::getOutputList() const
{
return m_resultTexture;
return m_resultTextures;
}
osg::ref_ptr< osg::Texture2D > WGEPostprocessor::getDepth() const
......@@ -76,6 +73,47 @@ osg::ref_ptr< osg::Texture2D > WGEPostprocessor::getDepth() const
return m_depthTexture;
}
WGEPostprocessor::PostprocessorInput::PostprocessorInput()
{
// leave them uni-initialized
}
WGEPostprocessor::PostprocessorInput::PostprocessorInput( std::vector< osg::ref_ptr< osg::Texture2D > > from )
{
if( from.size() > 0 )
{
m_colorTexture = from[0];
}
if( from.size() > 1 )
{
m_normalTexture = from[1];
}
if( from.size() > 2 )
{
m_parameterTexture = from[2];
}
if( from.size() > 3 )
{
m_tangentTexture = from[3];
}
if( from.size() > 4 )
{
m_depthTexture = from[4];
}
}
WGEPostprocessor::PostprocessorInput::PostprocessorInput( osg::ref_ptr< osg::Texture2D > color,
osg::ref_ptr< osg::Texture2D > normal,
osg::ref_ptr< osg::Texture2D > parameter,
osg::ref_ptr< osg::Texture2D > tangent,
osg::ref_ptr< osg::Texture2D > depth ):
m_colorTexture( color ),
m_normalTexture( normal ),
m_parameterTexture( parameter ),
m_tangentTexture( tangent ),
m_depthTexture( depth )
{
}
WGEPostprocessor::PostprocessorInput WGEPostprocessor::PostprocessorInput::attach( osg::ref_ptr< WGEOffscreenRenderPass > from )
{
PostprocessorInput buf;
......@@ -106,7 +144,7 @@ WGEPostprocessor::ProcessorList WGEPostprocessor::getPostprocessors()
// create prototypes of the postprocessors OW knows about
postprocs.push_back( WGEPostprocessor::SPtr( new WGEPostprocessorEdgeEnhance() ) );
postprocs.push_back( WGEPostprocessor::SPtr( new WGEPostprocessorCelShading() ) );
postprocs.push_back( WGEPostprocessor::SPtr( new WGEPostprocessorGauss() ) );
return postprocs;
}
......
......@@ -58,6 +58,34 @@ public:
class PostprocessorInput
{
public:
/**
* Constructs an instance from a given list of textures. The order in the list define color, normal, parameter, tangent, depth. There are
* no restrictions to the input list. If textures are missing, the corresponding textures in the GBuffer are missing.
*
* \param from source list
*/
explicit PostprocessorInput( std::vector< osg::ref_ptr< osg::Texture2D > > from );
/**
* Construct GBuffer with an explicit list of textures.
*
* \param color color texture
* \param normal normal texture
* \param parameter parameter texture
* \param tangent tangent texture
* \param depth depth texture
*/
PostprocessorInput( osg::ref_ptr< osg::Texture2D > color,
osg::ref_ptr< osg::Texture2D > normal,
osg::ref_ptr< osg::Texture2D > parameter,
osg::ref_ptr< osg::Texture2D > tangent,
osg::ref_ptr< osg::Texture2D > depth );
/**
* Constructor creates empty GBuffer. All textures are un-initialized.
*/
PostprocessorInput();
/**
* Attaches the needed textures to the specified render pass and returns the G-Buffer
*
......@@ -138,7 +166,8 @@ public:
virtual ~WGEPostprocessor();
/**
* Create instance. Uses the protected constructor. Implement it if you derive from this class!
* Create instance. Uses the protected constructor. Implement it if you derive from this class! This is called whenever your postprocessor is
* applied to the standard render-output. You can add your own constructors and creators for other cases.
*
* \param offscreen use this offscreen node to add your texture pass'
* \param gbuffer the input textures you should use
......@@ -155,12 +184,21 @@ public:
/**
* Returns the result texture. Use this to continue processing.
*
* \param idx which output. Each postprocessor returns at least one texture in index 0, which also is the default value
*
* \return the result texture
*/
virtual osg::ref_ptr< osg::Texture2D > getOutput() const;
virtual osg::ref_ptr< osg::Texture2D > getOutput( size_t idx = 0 ) const;
/**
* This processor can produce multiple outputs. Grab them here. This vector always contains at least the first filtered texture in unit 0.
*
* \return the vector as copy.
*/
const std::vector< osg::ref_ptr< osg::Texture2D > >& getOutputList() const;
/**
* Returns the new depth texture. Allows you to modify the depth values. By default, this is the input depth texture.
* Returns the new depth texture. Allows you to modify the depth values. By default, this is NULL. Check this!
*
* \return the depth texture
*/
......@@ -181,20 +219,9 @@ public:
virtual const std::string getDescription() const;
protected:
/**
* Constructor. Call this constructor from your derived class.
*
* \param offscreen use this offscreen node to add your texture pass'
* \param gbuffer the input textures you should use
* \param name a name for this postprocessor
* \param description a useful description
*/
WGEPostprocessor( osg::ref_ptr< WGEOffscreenRenderNode > offscreen, const PostprocessorInput& gbuffer,
std::string name, std::string description );
/**
* The texture contains the result
* The textures contain the result. Add at least one result texture
*/
osg::ref_ptr< osg::Texture2D > m_resultTexture;
std::vector< osg::ref_ptr< osg::Texture2D > > m_resultTextures;
/**
* The texture contains the new depth
......
......@@ -36,7 +36,7 @@ WGEPostprocessorCelShading::WGEPostprocessorCelShading():
WGEPostprocessorCelShading::WGEPostprocessorCelShading( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
const WGEPostprocessor::PostprocessorInput& gbuffer ):
WGEPostprocessor( offscreen, gbuffer, "Cel Shading",
WGEPostprocessor( "Cel Shading",
"This postprocessor reduces color by binning colors." )
{
// we also provide a property
......@@ -61,7 +61,7 @@ WGEPostprocessorCelShading::WGEPostprocessorCelShading( osg::ref_ptr< WGEOffscre
pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropInt >( "u_celShadingBins", bins ) );
// attach color0 output
m_resultTexture = pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGBA );
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGBA ) );
// provide the Gbuffer input
gbuffer.bind( pass );
......
......@@ -37,7 +37,7 @@ WGEPostprocessorEdgeEnhance::WGEPostprocessorEdgeEnhance():
WGEPostprocessorEdgeEnhance::WGEPostprocessorEdgeEnhance( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
const WGEPostprocessor::PostprocessorInput& gbuffer ):
WGEPostprocessor( offscreen, gbuffer, "Edge Enhance",
WGEPostprocessor( "Edge Enhance",
"Edge detection filter to emphasize edges in complex geometry." )
{
// we also provide a property
......@@ -65,7 +65,7 @@ WGEPostprocessorEdgeEnhance::WGEPostprocessorEdgeEnhance( osg::ref_ptr< WGEOffsc
pass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_edgeEdgeThresholdLower", edgeThresholdL ) );
// attach color0 output
m_resultTexture = pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGB );
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGB ) );
// provide the Gbuffer input
gbuffer.bind( pass );
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <osg/Camera>
#include "../shaders/WGEPropertyUniform.h"
#include "../shaders/WGEShaderPropertyDefineOptions.h"
#include "WGEPostprocessorGauss.h"
WGEPostprocessorGauss::WGEPostprocessorGauss():
WGEPostprocessor( "Gauss Filtering",
"Gauss filter all specified input textures." )
{
}
WGEPostprocessorGauss::WGEPostprocessorGauss( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
osg::ref_ptr< osg::Texture2D > tex0,
osg::ref_ptr< osg::Texture2D > tex1,
osg::ref_ptr< osg::Texture2D > tex2,
osg::ref_ptr< osg::Texture2D > tex3,
osg::ref_ptr< osg::Texture2D > tex4,
osg::ref_ptr< osg::Texture2D > tex5,
osg::ref_ptr< osg::Texture2D > tex6,
osg::ref_ptr< osg::Texture2D > tex7 ):
WGEPostprocessor( "Gauss Filtering",
"Gauss filter all specified input textures." )
{
// Use the standard postprocessor uber-shader
WGEShader::RefPtr s = new WGEShader( "WGEPostprocessor" );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS" );
// also add the m_effectOnly property as shader preprocessor
s->addPreprocessor( m_effectOnlyPreprocessor );
// create the rendering pass
osg::ref_ptr< WGEOffscreenTexturePass > pass = offscreen->addTextureProcessingPass( s, "Gauss Filter" );
// for each of the textures do:
// attach color0 output and bind tex0
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGBA ) );
pass->bind( tex0, 0 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT0" );
// attach color1 output and bind tex1
if( tex1 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER1, GL_RGBA ) );
pass->bind( tex1, 1 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT1" );
}
// attach color2 output and bind tex2
if( tex2 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER2, GL_RGBA ) );
pass->bind( tex2, 2 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT2" );
}
// attach color3 output and bind tex3
if( tex3 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER3, GL_RGBA ) );
pass->bind( tex3, 3 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT3" );
}
// attach color4 output and bind tex4
if( tex4 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER4, GL_RGBA ) );
pass->bind( tex4, 4 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT4" );
}
// attach color5 output and bind tex5
if( tex5 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER5, GL_RGBA ) );
pass->bind( tex5, 5 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT5" );
}
// attach color6 output and bind tex6
if( tex6 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER6, GL_RGBA ) );
pass->bind( tex6, 6 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT6" );
}
// attach color7 output and bind tex7
if( tex7 )
{
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER7, GL_RGBA ) );
pass->bind( tex7, 7 );
s->setDefine( "WGE_POSTPROCESSOR_GAUSS_UNIT7" );
}
}
WGEPostprocessorGauss::~WGEPostprocessorGauss()
{
// cleanup
}
WGEPostprocessor::SPtr WGEPostprocessorGauss::create( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
const WGEPostprocessor::PostprocessorInput& gbuffer ) const
{
return WGEPostprocessor::SPtr( new WGEPostprocessorGauss( offscreen, gbuffer.m_colorTexture ) );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WGEPOSTPROCESSORGAUSS_H
#define WGEPOSTPROCESSORGAUSS_H
#include <boost/shared_ptr.hpp>
#include <osg/Texture2D>
#include "WGEPostprocessor.h"
/**
* Gauss filtering of the input. It does filter all the textures you bind on it and returns a gauss filtered version. If you want to define the
* exact list of textures to filter in one pass, use the alternative \ref create call.
*/
class WGEPostprocessorGauss: public WGEPostprocessor
{
public:
/**
* Convenience typedef for a boost::shared_ptr< WGEPostprocessorGauss >.
*/
typedef boost::shared_ptr< WGEPostprocessorGauss > SPtr;
/**
* Convenience typedef for a boost::shared_ptr< const WGEPostprocessorGauss >.
*/
typedef boost::shared_ptr< const WGEPostprocessorGauss > ConstSPtr;
/**
* Default constructor.
*/
WGEPostprocessorGauss();
/**
* Constructor. We implement a public constructor which can take more textures as input
*
* \param offscreen use this offscreen node to add your texture pass'
* \param tex0 texture to filter
* \param tex1 texture to filter
* \param tex2 texture to filter
* \param tex3 texture to filter
* \param tex4 texture to filter
* \param tex5 texture to filter
* \param tex6 texture to filter
* \param tex7 texture to filter
*/
WGEPostprocessorGauss( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
osg::ref_ptr< osg::Texture2D > tex0,
osg::ref_ptr< osg::Texture2D > tex1 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex2 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex3 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex4 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex5 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex6 = osg::ref_ptr< osg::Texture2D >(),
osg::ref_ptr< osg::Texture2D > tex7 = osg::ref_ptr< osg::Texture2D >() );
/**
* Destructor.
*/
virtual ~WGEPostprocessorGauss();
/**
* Create instance. Uses the protected constructor. Implement it if you derive from this class!
*
* \param offscreen use this offscreen node to add your texture pass'
* \param gbuffer the input textures you should use
*/
virtual WGEPostprocessor::SPtr create( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
const PostprocessorInput& gbuffer ) const;
protected:
private:
};
#endif // WGEPOSTPROCESSORGAUSS_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <string>
#include <osg/Camera>
#include "../shaders/WGEPropertyUniform.h"
#include "../shaders/WGEShaderPropertyDefineOptions.h"
#include "WGEPostprocessorMergeOp.h"
WGEPostprocessorMergeOp::WGEPostprocessorMergeOp():
WGEPostprocessor( "MergeOp",
"MergeOp - combines all input textures in a user defined way." )
{
}
WGEPostprocessorMergeOp::WGEPostprocessorMergeOp( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
osg::ref_ptr< osg::Texture2D > tex0,
osg::ref_ptr< osg::Texture2D > tex1,
osg::ref_ptr< osg::Texture2D > tex2,
osg::ref_ptr< osg::Texture2D > tex3,
osg::ref_ptr< osg::Texture2D > tex4,
osg::ref_ptr< osg::Texture2D > tex5,
osg::ref_ptr< osg::Texture2D > tex6,
osg::ref_ptr< osg::Texture2D > tex7 ):
WGEPostprocessor( "MergeOp",
"MergeOp - combines all input textures in a user defined way." ),
m_codeInjector( new WGEShaderCodeInjector( "WGE_POSTPROCESSOR_MERGEOP_CODE" ) )
{
// Use the standard postprocessor uber-shader
m_mergeOpShader = new WGEShader( "WGEPostprocessor" );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP" );
m_mergeOpShader->addPreprocessor( m_codeInjector );
// also add the m_effectOnly property as shader preprocessor
m_mergeOpShader->addPreprocessor( m_effectOnlyPreprocessor );
// create the rendering pass
osg::ref_ptr< WGEOffscreenTexturePass > pass = offscreen->addTextureProcessingPass( m_mergeOpShader, "MergeOp" );
// for each of the textures do:
// attach color0 output and bind tex0
m_resultTextures.push_back( pass->attach( osg::Camera::COLOR_BUFFER0, GL_RGBA ) );
pass->bind( tex0, 0 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT0" );
// attach color1 output and bind tex1
if( tex1 )
{
pass->bind( tex1, 1 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT1" );
}
// attach color2 output and bind tex2
if( tex2 )
{
pass->bind( tex2, 2 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT2" );
}
// attach color3 output and bind tex3
if( tex3 )
{
pass->bind( tex3, 3 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT3" );
}
// attach color4 output and bind tex4
if( tex4 )
{
pass->bind( tex4, 4 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT4" );
}
// attach color5 output and bind tex5
if( tex5 )
{
pass->bind( tex5, 5 );
m_mergeOpShader->setDefine( "WGE_POSTPROCESSOR_MERGEOP_UNIT5" );
}
// attach color6 output and bind tex6
if( tex6 )
{