OpenWalnut  1.4.0
WGEShader.h
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 #ifndef WGESHADER_H
26 #define WGESHADER_H
27 
28 #include <map>
29 #include <string>
30 
31 #include <boost/filesystem.hpp>
32 #include <boost/signals2/signal.hpp>
33 
34 #include <osg/NodeCallback>
35 #include <osg/Program>
36 #include <osg/Shader>
37 
38 #include "../../common/WPathHelper.h"
39 #include "../../common/WSharedAssociativeContainer.h"
40 
41 #include "WGEShaderDefine.h"
42 #include "WGEShaderPreprocessor.h"
43 
44 /**
45  * Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
46  */
47 class WGEShader: public osg::Program
48 {
49 public:
50  /**
51  * Convenience typedef for an osg::ref_ptr
52  */
53  typedef osg::ref_ptr< WGEShader > RefPtr;
54 
55  /**
56  * Convenience typedef for an osg::ref_ptr; const
57  */
58  typedef osg::ref_ptr< const WGEShader > ConstRefPtr;
59 
60  /**
61  * Default constructor. Loads the specified shader programs. The path that can be specified is optional but allows modules to load their own
62  * local shaders. The search order for shader files is as follows: 1. search, 2. search/shaders, 3. WPathHelper::getShaderPath()
63  *
64  * \param name the name of the shader. It gets searched in the shader path.
65  * \param search the local search path. If not specified, the global shader path is used.
66  */
67  WGEShader( std::string name, boost::filesystem::path search = WPathHelper::getShaderPath() );
68 
69  /**
70  * Destructor.
71  */
72  virtual ~WGEShader();
73 
74  /**
75  * Apply this shader to the specified node. Use this method to ensure, that reload events can be handled properly during the
76  * update cycle.
77  *
78  * \param node the node where the program should be registered to.
79  */
80  virtual void apply( osg::ref_ptr< osg::Node > node );
81 
82  /**
83  * If enabled, activate our program in the GL pipeline, performing any rebuild operations that might be pending. In addition to the standard
84  * OSG functionality, it also loads/reloads the shader source from file.
85  *
86  * \param state the state to apply the shader program to.
87  */
88  virtual void applyDirect( osg::State& state ); // NOLINT <- ensure this matches the official OSG API by using a non-const ref
89 
90  /**
91  * Removes the shader from the specified node.
92  *
93  * \param node the node where the program is registered to.
94  */
95  virtual void deactivate( osg::ref_ptr< osg::Node > node );
96 
97  /**
98  * Initiate a reload of the shader during the next update cycle.
99  */
100  virtual void reload();
101 
102  /**
103  * Sets a define which is include into the shader source code. This allows the preprocessor to turn on/off several parts of your code. In GLSL
104  * defines are a better choice when compared with a lot of branches (if-statements).
105  *
106  * \param key The name of the define
107  * \param value The value of the define. If this is not specified, the define can be used as simple ifdef switch.
108  *
109  * \return the define object allowing later control
110  */
111  template < typename T >
112  typename WGEShaderDefine< T >::SPtr setDefine( std::string key, T value );
113 
114  /**
115  * Sets a define which is include into the shader source code. This allows the preprocessor to turn on/off several parts of your code. In GLSL
116  * defines are a better choice when compared with a lot of branches (if-statements).
117  *
118  * \param key The name of the define
119  *
120  * \return the switch allowing to control the define
121  */
122  WGEShaderDefineSwitch::SPtr setDefine( std::string key );
123 
124  /**
125  * Adds the specified preprocessor to this shader. The preprocessor is able to force shader reloads.
126  *
127  * \param preproc the preprocessor to add.
128  */
130 
131  /**
132  * Removes the specified preprocessor. Changes inside the preprocessor won't cause any updates anymore.
133  *
134  * \param preproc the preprocessor to remove. If not exists: nothing is done.
135  */
137 
138  /**
139  * Removes all preprocessors. Be careful with this one since it removes the WGESHaderVersionPreprocessor too, which is mandatory.
140  */
141  void clearPreprocessors();
142 
143 protected:
144  /**
145  * This method searches and processes all includes in the shader source. The filenames in the include statement are assumed to
146  * be relative to this shader's path. It simply unrolls the code.
147  *
148  * \param filename the filename of the shader to process.
149  * \param optional denotes whether a "file not found" is critical or not
150  * \param level the inclusion level. This is used to avoid cycles.
151  *
152  * \return the processed source.
153  */
154  std::string processShaderRecursive( const std::string filename, bool optional = false, int level = 0 );
155 
156  /**
157  * This method searches and processes all includes in the shader source. The filenames in the include statement are assumed to
158  * be relative to this shader's path. It additionally applies preprocessors.
159  *
160  * \see processShaderRecursive
161  *
162  * \param filename the filename of the shader to process.
163  * \param optional denotes whether a "file not found" is critical or not
164  *
165  * \return the processed source.
166  */
167  std::string processShader( const std::string filename, bool optional = false );
168 
169  /**
170  * This completely reloads the shader file and processes it. It also resets m_reload to false.
171  */
172  void reloadShader();
173 
174  /**
175  * Handles all state changes in m_reload and m_deactivated. It ensure that the shader programs are bound properly or deactivated.
176  */
177  void updatePrograms();
178 
179  /**
180  * String that stores the location of all shader files
181  */
182  boost::filesystem::path m_shaderPath;
183 
184  /**
185  * The name of the shader. It is used to construct the actual filename to load.
186  */
187  std::string m_name;
188 
189  /**
190  * Flag denoting whether a shader should be reloaded.
191  */
192  bool m_reload;
193 
194  /**
195  * True if the shaders have been loaded successfully previously.
196  */
198 
199  /**
200  * Flag denoting whether a shader should be deactivated.
201  */
203 
204  /**
205  * Connection object to the reload signal from WGraphbicsEngine.
206  */
207  boost::signals2::connection m_reloadSignalConnection;
208 
209  /**
210  * The list of preprocessors - Type
211  */
213 
214  /**
215  * List of all pre-processing that need to be applied to this shader instance
216  */
218 
219  /**
220  * This preprocessor needs to be run LAST. It handles version-statements in GLSL.
221  */
223 
224  /**
225  * the vertex shader object
226  */
227  osg::ref_ptr< osg::Shader > m_vertexShader;
228 
229  /**
230  * the fragment shader object
231  */
232  osg::ref_ptr< osg::Shader > m_fragmentShader;
233 
234  /**
235  * the geometry shader object
236  */
237  osg::ref_ptr< osg::Shader > m_geometryShader;
238 
239  /**
240  * Update callback which handles the shader reloading.
241  * This ensures thread safe modification of the osg node.
242  */
243  class SafeUpdaterCallback : public osg::NodeCallback
244  {
245  public:
246  /**
247  * Constructor. Creates a new callback.
248  *
249  * \param shader the shader which needs to be updated.
250  */
251  explicit SafeUpdaterCallback( WGEShader* shader );
252 
253  /**
254  * Callback method called by the NodeVisitor when visiting a node.
255  * This inserts and removes enqueued nodes from this group node instance.
256  *
257  * \param node the node calling this update
258  * \param nv The node visitor which performs the traversal. Should be an
259  * update visitor.
260  */
261  virtual void operator()( osg::Node* node, osg::NodeVisitor* nv );
262 
263  protected:
264  /**
265  * The shader belonging to the node currently getting updated.
266  */
268  };
269 
270 private:
271 };
272 
273 template < typename T >
274 typename WGEShaderDefine< T >::SPtr WGEShader::setDefine( std::string key, T value )
275 {
276  typename WGEShaderDefine< T >::SPtr def;
277 
278  // try to find the define. If it exists, set it. If not, add it.
280  for( PreprocessorsList::ConstIterator pp = r->get().begin(); pp != r->get().end(); ++pp )
281  {
282  typename WGEShaderDefine< T >::SPtr define = boost::dynamic_pointer_cast< WGEShaderDefine< T > >( ( *pp ).first );
283  if( define && ( define->getName() == key ) )
284  {
285  define->setValue( value );
286  def = define;
287  break;
288  }
289  }
290  r.reset();
291 
292  // did not find it. Add.
293  if( !def )
294  {
295  def = typename WGEShaderDefine< T >::SPtr( new WGEShaderDefine< T >( key, value ) );
296  addPreprocessor( def );
297  }
298  return def;
299 }
300 
301 #endif // WGESHADER_H
302 
bool m_reload
Flag denoting whether a shader should be reloaded.
Definition: WGEShader.h:192
void updatePrograms()
Handles all state changes in m_reload and m_deactivated.
Definition: WGEShader.cpp:177
osg::ref_ptr< osg::Shader > m_vertexShader
the vertex shader object
Definition: WGEShader.h:227
SafeUpdaterCallback(WGEShader *shader)
Constructor.
Definition: WGEShader.cpp:193
PreprocessorsList m_preprocessors
List of all pre-processing that need to be applied to this shader instance.
Definition: WGEShader.h:217
Update callback which handles the shader reloading.
Definition: WGEShader.h:243
std::map< WGEShaderPreprocessor::SPtr, boost::signals2::connection >::const_iterator ConstIterator
A typedef for the correct const iterator useful to traverse this sequence container.
std::string m_name
The name of the shader.
Definition: WGEShader.h:187
static boost::filesystem::path getShaderPath()
The path to the global shaders.
Definition: WPathHelper.cpp:99
virtual void reload()
Initiate a reload of the shader during the next update cycle.
Definition: WGEShader.cpp:117
WSharedAssociativeContainer< std::map< WGEShaderPreprocessor::SPtr, boost::signals2::connection > > PreprocessorsList
The list of preprocessors - Type.
Definition: WGEShader.h:212
virtual void deactivate(osg::ref_ptr< osg::Node > node)
Removes the shader from the specified node.
Definition: WGEShader.cpp:98
void reloadShader()
This completely reloads the shader file and processes it.
Definition: WGEShader.cpp:122
void clearPreprocessors()
Removes all preprocessors.
Definition: WGEShader.cpp:384
std::string processShader(const std::string filename, bool optional=false)
This method searches and processes all includes in the shader source.
Definition: WGEShader.cpp:334
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
osg::ref_ptr< WGEShader > RefPtr
Convenience typedef for an osg::ref_ptr.
Definition: WGEShader.h:53
virtual void apply(osg::ref_ptr< osg::Node > node)
Apply this shader to the specified node.
Definition: WGEShader.cpp:79
osg::ref_ptr< osg::Shader > m_fragmentShader
the fragment shader object
Definition: WGEShader.h:232
std::string processShaderRecursive(const std::string filename, bool optional=false, int level=0)
This method searches and processes all includes in the shader source.
Definition: WGEShader.cpp:206
virtual void applyDirect(osg::State &state)
If enabled, activate our program in the GL pipeline, performing any rebuild operations that might be ...
Definition: WGEShader.cpp:92
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader...
Definition: WGEShader.h:47
bool m_shaderLoaded
True if the shaders have been loaded successfully previously.
Definition: WGEShader.h:197
void setValue(const ValueType &value)
Sets the new value for this define.
osg::ref_ptr< osg::Shader > m_geometryShader
the geometry shader object
Definition: WGEShader.h:237
void removePreprocessor(WGEShaderPreprocessor::SPtr preproc)
Removes the specified preprocessor.
Definition: WGEShader.cpp:372
boost::filesystem::path m_shaderPath
String that stores the location of all shader files.
Definition: WGEShader.h:182
WGEShader(std::string name, boost::filesystem::path search=WPathHelper::getShaderPath())
Default constructor.
Definition: WGEShader.cpp:49
WGEShader * m_shader
The shader belonging to the node currently getting updated.
Definition: WGEShader.h:267
virtual ~WGEShader()
Destructor.
Definition: WGEShader.cpp:73
std::string getName() const
Returns the name of the define.
bool m_deactivated
Flag denoting whether a shader should be deactivated.
Definition: WGEShader.h:202
This class provides a common interface for thread-safe access to associative containers (set...
boost::shared_ptr< WGEShaderPreprocessor > SPtr
Shared pointer for this class.
osg::ref_ptr< const WGEShader > ConstRefPtr
Convenience typedef for an osg::ref_ptr; const.
Definition: WGEShader.h:58
WGEShaderPreprocessor::SPtr m_versionPreprocessor
This preprocessor needs to be run LAST.
Definition: WGEShader.h:222
This class is able to provide arbitrary values as define statements in GLSL code. ...
boost::shared_ptr< WGEShaderDefine< ValueType > > SPtr
Shared pointer for this class.
void addPreprocessor(WGEShaderPreprocessor::SPtr preproc)
Adds the specified preprocessor to this shader.
Definition: WGEShader.cpp:359
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
Callback method called by the NodeVisitor when visiting a node.
Definition: WGEShader.cpp:198
boost::shared_ptr< WSharedObjectTicketRead< std::map< WGEShaderPreprocessor::SPtr, boost::signals2::connection > > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:62
boost::signals2::connection m_reloadSignalConnection
Connection object to the reload signal from WGraphbicsEngine.
Definition: WGEShader.h:207
WGEShaderDefine< T >::SPtr setDefine(std::string key, T value)
Sets a define which is include into the shader source code.
Definition: WGEShader.h:274