OpenWalnut  1.5.0dev
WGEPostprocessorHalftone.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 <osg/Camera>
26 
27 #include "../shaders/WGEPropertyUniform.h"
28 #include "../shaders/WGEShaderPropertyDefine.h"
29 #include "WGEPostprocessorGauss.h"
30 #include "WGEPostprocessorEdgeEnhance.h"
31 #include "WGEPostprocessorMergeOp.h"
32 
33 #include "WGEPostprocessorHalftone.h"
34 
36  WGEPostprocessor( "Halftone",
37  "Halftone is a dithering effect to emphasize certain structures of a surface." )
38 {
39 }
40 
41 WGEPostprocessorHalftone::WGEPostprocessorHalftone( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
42  const WGEPostprocessor::PostprocessorInput& gbuffer ):
43  WGEPostprocessor( "Halftone",
44  "Halftone is a dithering effect to emphasize certain structures of a surface." )
45 {
46  // the Halftone algorithm has some parameters. Provide these parameters to the user
47  WPropDouble ditherRotationMatrixAngle = m_properties->addProperty( "Rotation angle",
48  "Rotate the dither effect by this angle.", 30.0 );
49  ditherRotationMatrixAngle->setMin( 0 );
50  ditherRotationMatrixAngle->setMax( 180 );
51 
52  WPropDouble ditherTexSize = m_properties->addProperty( "Texture Size",
53  "Write me.", 4.0 );
54  ditherTexSize->setMin( 0 );
55  ditherTexSize->setMax( 10 );
56 
57  WPropDouble ditherCrossHatchThreshold = m_properties->addProperty( "Cross Hatch Threshold",
58  "Write me.", 0.9 );
59  ditherCrossHatchThreshold->setMin( 0 );
60  ditherCrossHatchThreshold->setMax( 10 );
61 
62  WPropDouble ditherClip = m_properties->addProperty( "Dither Clip",
63  "Write me.", 0.6 );
64  ditherClip->setMin( 0.0 );
65  ditherClip->setMax( 1.0 );
66 
67  WPropColor hatchColor = m_properties->addProperty( "Hatch Color", "Write", WColor( 0.1, 0.1, 0.1, 1.0 ) );
68 
69  //////////////////////////////////////////////////////////////////
70  // Use EdgeEnhance Processor
71 
72  // We need edges. Let the edge postprocessor do the work for us
74  WGEPostprocessor::SPtr edgeProcessor = edgeProto.create( offscreen, gbuffer );
75  // we want mipmaping for the edge texture
76  edgeProcessor->getOutput()->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
77  edgeProcessor->getProperties()->getProperty( "Effect Only" )->toPropBool()->set( true );
78  // Allow user to config our sub-processor
79  m_properties->addProperty( edgeProcessor->getProperties() );
80 
81  //////////////////////////////////////////////////////////////////
82  // Build our Halftone Processor
83 
84  // use the standard postprocessor uber-shader
85  WGEShader::RefPtr s = new WGEShader( "WGEPostprocessor" );
86  s->setDefine( "WGE_POSTPROCESSOR_HALFTONE" );
87 
88  // also add the m_effectOnly property as shader preprocessor
89  s->addPreprocessor( m_effectOnlyPreprocessor );
90 
91  // create the Halftone rendering pass
92  osg::ref_ptr< WGEOffscreenTexturePass > htPass = offscreen->addTextureProcessingPass( s, "Halftone" );
93  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ditherRotMatrixAngle", ditherRotationMatrixAngle ) );
94  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ditherTexSize", ditherTexSize ) );
95  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ditherCrossHatchThresh", ditherCrossHatchThreshold ) );
96  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_ditherClip", ditherClip ) );
97  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropColor >( "u_hatchColor", hatchColor ) );
98 
99  //////////////////////////////////////////////////////////////////
100  // Build a Gauss Filter for shader
101 
102 
103  // attach color0 output
104  m_resultTextures.push_back( htPass->attach( osg::Camera::COLOR_BUFFER0, GL_RGBA ) );
105 
106  // provide the Gbuffer input, with several mipmap levels
107  gbuffer.m_depthTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
108  gbuffer.m_normalTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
109  gbuffer.m_tangentTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
110 
111  size_t gBufUnitOffset = gbuffer.bind( htPass );
112 
113  // this effect needs some additional noise texture:
114  const size_t size = 64;
115  osg::ref_ptr< WGETexture2D > randTex = wge::genWhiteNoiseTexture( size, size, 3 );
116  htPass->bind( randTex, gBufUnitOffset );
117  htPass->bind( edgeProcessor->getOutput(), gBufUnitOffset + 1 );
118 
119  // also utilize the pre-blend scale
120  m_effectScale->setHidden( false );
121  htPass->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_effectPreBlendScale", m_effectScale ) );
122 }
123 
125 {
126  // cleanup
127 }
128 
129 WGEPostprocessor::SPtr WGEPostprocessorHalftone::create( osg::ref_ptr< WGEOffscreenRenderNode > offscreen,
130  const WGEPostprocessor::PostprocessorInput& gbuffer ) const
131 {
132  return WGEPostprocessor::SPtr( new WGEPostprocessorHalftone( offscreen, gbuffer ) );
133 }
Edge enhancing postprocessor.
virtual WGEPostprocessor::SPtr create(osg::ref_ptr< WGEOffscreenRenderNode > offscreen, const PostprocessorInput &gbuffer) const
Create instance.
virtual ~WGEPostprocessorHalftone()
Destructor.
virtual WGEPostprocessor::SPtr create(osg::ref_ptr< WGEOffscreenRenderNode > offscreen, const PostprocessorInput &gbuffer) const
Create instance.
WGEPostprocessorHalftone()
Default constructor.
This class encapsulates a G-Buffer.
osg::ref_ptr< osg::Texture2D > m_normalTexture
Normal in RGB.
osg::ref_ptr< osg::Texture2D > m_tangentTexture
Tangent in RGB.
osg::ref_ptr< osg::Texture2D > m_depthTexture
Depth.
size_t bind(osg::ref_ptr< WGEOffscreenRenderPass > to) const
Attaches these textures to the specified renderpass.
The base class for all custom post-processors.
WGEShaderPreprocessor::SPtr m_effectOnlyPreprocessor
For convenience, this is a shader preprocessor controlled by m_effectOnly property.
WPropGroup m_properties
All the properties of the post-processor.
WPropDouble m_effectScale
Scale the effect prior to blending it.
std::shared_ptr< WGEPostprocessor > SPtr
Convenience typedef for an osg::ref_ptr< WGEPostprocessor >.
std::vector< osg::ref_ptr< osg::Texture2D > > m_resultTextures
The textures contain the result.
Class implementing a uniform which can be controlled by a property instance.
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
osg::ref_ptr< WGEShader > RefPtr
Convenience typedef for an osg::ref_ptr.
Definition: WGEShader.h:53
osg::ref_ptr< WGETexture< osg::Texture1D > > genWhiteNoiseTexture(size_t sizeX, size_t channels)
This generates an 1D texture only containing white noise in its channels.