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