OpenWalnut 1.2.5

WGEShader.h

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 #ifndef WGESHADER_H
00026 #define WGESHADER_H
00027 
00028 #include <list>
00029 #include <map>
00030 #include <string>
00031 
00032 // Use filesystem version 2 for compatibility with newer boost versions.
00033 #ifndef BOOST_FILESYSTEM_VERSION
00034     #define BOOST_FILESYSTEM_VERSION 2
00035 #endif
00036 #include <boost/filesystem.hpp>
00037 #include <boost/signals2/signal.hpp>
00038 
00039 #include <osg/NodeCallback>
00040 #include <osg/Program>
00041 #include <osg/Shader>
00042 
00043 #include "../../common/WPathHelper.h"
00044 #include "../../common/WSharedAssociativeContainer.h"
00045 #include "../WExportWGE.h"
00046 #include "WGEShaderDefine.h"
00047 #include "WGEShaderPreprocessor.h"
00048 
00049 /**
00050  * Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
00051  */
00052 class WGE_EXPORT WGEShader: public osg::Program
00053 {
00054 public:
00055     /**
00056      * Convenience typedef for an osg::ref_ptr
00057      */
00058     typedef osg::ref_ptr< WGEShader > RefPtr;
00059 
00060     /**
00061      * Convenience typedef for an osg::ref_ptr; const
00062      */
00063     typedef osg::ref_ptr< const WGEShader > ConstRefPtr;
00064 
00065     /**
00066      * Default constructor. Loads the specified shader programs. The path that can be specified is optional but allows modules to load their own
00067      * local shaders. The search order for shader files is as follows: 1. search, 2. search/shaders, 3. WPathHelper::getShaderPath()
00068      *
00069      * \param name the name of the shader. It gets searched in the shader path.
00070      * \param search the local search path. If not specified, the global shader path is used.
00071      */
00072     WGEShader( std::string name, boost::filesystem::path search = WPathHelper::getShaderPath() );
00073 
00074     /**
00075      * Destructor.
00076      */
00077     virtual ~WGEShader();
00078 
00079     /**
00080      * Apply this shader to the specified node. Use this method to ensure, that reload events can be handled properly during the
00081      * update cycle.
00082      *
00083      * \param node the node where the program should be registered to.
00084      */
00085     virtual void apply( osg::ref_ptr< osg::Node > node );
00086 
00087     /**
00088      * If enabled, activate our program in the GL pipeline, performing any rebuild operations that might be pending. In addition to the standard
00089      * OSG functionality, it also loads/reloads the shader source from file.
00090      *
00091      * \param state the state to apply the shader program to.
00092      */
00093     virtual void applyDirect( osg::State& state );  // NOLINT <- ensure this matches the official OSG API by using a non-const ref
00094 
00095     /**
00096      * Removes the shader from the specified node.
00097      *
00098      * \param node the node where the program is registered to.
00099      */
00100     virtual void deactivate( osg::ref_ptr< osg::Node > node );
00101 
00102     /**
00103      * Initiate a reload of the shader during the next update cycle.
00104      */
00105     virtual void reload();
00106 
00107     /**
00108      * 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
00109      * defines are a better choice when compared with a lot of branches (if-statements).
00110      *
00111      * \param key The name of the define
00112      * \param value The value of the define. If this is not specified, the define can be used as simple ifdef switch.
00113      *
00114      * \return the define object allowing later control
00115      */
00116     template < typename T >
00117     typename WGEShaderDefine< T >::SPtr setDefine( std::string key, T value );
00118 
00119     /**
00120      * 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
00121      * defines are a better choice when compared with a lot of branches (if-statements).
00122      *
00123      * \param key The name of the define
00124      *
00125      * \return the switch allowing to control the define
00126      */
00127     WGEShaderDefineSwitch::SPtr setDefine( std::string key );
00128 
00129     /**
00130      * Adds the specified preprocessor to this shader. The preprocessor is able to force shader reloads.
00131      *
00132      * \param preproc the preprocessor to add.
00133      */
00134     void addPreprocessor( WGEShaderPreprocessor::SPtr preproc );
00135 
00136     /**
00137      * Removes the specified preprocessor. Changes inside the preprocessor won't cause any updates anymore.
00138      *
00139      * \param preproc the preprocessor to remove. If not exists: nothing is done.
00140      */
00141     void removePreprocessor( WGEShaderPreprocessor::SPtr preproc );
00142 
00143     /**
00144      * Removes all preprocessors. Be careful with this one since it removes the WGESHaderVersionPreprocessor too, which is mandatory.
00145      */
00146     void clearPreprocessors();
00147 
00148 protected:
00149 
00150     /**
00151      * This method searches and processes all includes in the shader source. The filenames in the include statement are assumed to
00152      * be relative to this shader's path. It simply unrolls the code.
00153      *
00154      * \param filename the filename of the shader to process.
00155      * \param optional denotes whether a "file not found" is critical or not
00156      * \param level the inclusion level. This is used to avoid cycles.
00157      *
00158      * \return the processed source.
00159      */
00160     std::string processShaderRecursive( const std::string filename, bool optional = false, int level = 0 );
00161 
00162     /**
00163      * This method searches and processes all includes in the shader source. The filenames in the include statement are assumed to
00164      * be relative to this shader's path. It additionally applies preprocessors.
00165      *
00166      * \see processShaderRecursive
00167      *
00168      * \param filename the filename of the shader to process.
00169      * \param optional denotes whether a "file not found" is critical or not
00170      *
00171      * \return the processed source.
00172      */
00173     std::string processShader( const std::string filename, bool optional = false );
00174 
00175     /**
00176      * This completely reloads the shader file and processes it. It also resets m_reload to false.
00177      */
00178     void reloadShader();
00179 
00180     /**
00181      * Handles all state changes in m_reload and m_deactivated. It ensure that the shader programs are bound properly or deactivated.
00182      */
00183     void updatePrograms();
00184 
00185     /**
00186      * String that stores the location of all shader files
00187      */
00188     boost::filesystem::path m_shaderPath;
00189 
00190     /**
00191      * The name of the shader. It is used to construct the actual filename to load.
00192      */
00193     std::string m_name;
00194 
00195     /**
00196      * Flag denoting whether a shader should be reloaded.
00197      */
00198     bool m_reload;
00199 
00200     /**
00201      * True if the shaders have been loaded successfully previously.
00202      */
00203     bool m_shaderLoaded;
00204 
00205     /**
00206      * Flag denoting whether a shader should be deactivated.
00207      */
00208     bool m_deactivated;
00209 
00210     /**
00211      * Connection object to the reload signal from WGraphbicsEngine.
00212      */
00213     boost::signals2::connection m_reloadSignalConnection;
00214 
00215     /**
00216      * The list of preprocessors - Type
00217      */
00218     typedef WSharedAssociativeContainer< std::map< WGEShaderPreprocessor::SPtr, boost::signals2::connection > > PreprocessorsList;
00219 
00220     /**
00221      * List of all pre-processing that need to be applied to this shader instance
00222      */
00223     PreprocessorsList m_preprocessors;
00224 
00225     /**
00226      * This preprocessor needs to be run LAST. It handles version-statements in GLSL.
00227      */
00228     WGEShaderPreprocessor::SPtr m_versionPreprocessor;
00229 
00230     /**
00231      * the vertex shader object
00232      */
00233     osg::ref_ptr< osg::Shader > m_vertexShader;
00234 
00235     /**
00236      * the fragment shader object
00237      */
00238     osg::ref_ptr< osg::Shader > m_fragmentShader;
00239 
00240     /**
00241      * the geometry shader object
00242      */
00243     osg::ref_ptr< osg::Shader > m_geometryShader;
00244 
00245     /**
00246      * Update callback which handles the shader reloading.
00247      * This ensures thread safe modification of the osg node.
00248      */
00249     class SafeUpdaterCallback : public osg::NodeCallback
00250     {
00251     public:
00252         /**
00253          * Constructor. Creates a new callback.
00254          *
00255          * \param shader the shader which needs to be updated.
00256          */
00257         explicit SafeUpdaterCallback( WGEShader* shader );
00258 
00259         /**
00260          * Callback method called by the NodeVisitor when visiting a node.
00261          * This inserts and removes enqueued nodes from this group node instance.
00262          *
00263          * \param node the node calling this update
00264          * \param nv The node visitor which performs the traversal. Should be an
00265          * update visitor.
00266          */
00267         virtual void operator()( osg::Node* node, osg::NodeVisitor* nv );
00268 
00269     protected:
00270 
00271         /**
00272          * The shader belonging to the node currently getting updated.
00273          */
00274         WGEShader* m_shader;
00275     };
00276 
00277 private:
00278 };
00279 
00280 template < typename T >
00281 typename WGEShaderDefine< T >::SPtr WGEShader::setDefine( std::string key, T value )
00282 {
00283     typename WGEShaderDefine< T >::SPtr def;
00284 
00285     // try to find the define. If it exists, set it. If not, add it.
00286     PreprocessorsList::ReadTicket r = m_preprocessors.getReadTicket();
00287     for( PreprocessorsList::ConstIterator pp = r->get().begin(); pp != r->get().end(); ++pp )
00288     {
00289         typename WGEShaderDefine< T >::SPtr define = boost::shared_dynamic_cast< WGEShaderDefine< T > >( ( *pp ).first );
00290         if( define && ( define->getName() == key ) )
00291         {
00292             define->setValue( value );
00293             def = define;
00294             break;
00295         }
00296     }
00297     r.reset();
00298 
00299     // did not find it. Add.
00300     if( !def )
00301     {
00302         def = typename WGEShaderDefine< T >::SPtr( new WGEShaderDefine< T >( key, value ) );
00303         addPreprocessor( def );
00304     }
00305     return def;
00306 }
00307 
00308 #endif  // WGESHADER_H
00309 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends