1 #ifndef SH_FACTORY_H 2 #define SH_FACTORY_H 3 4 #include <map> 5 #include <string> 6 #include <sstream> 7 8 #include "MaterialInstance.hpp" 9 #include "ShaderSet.hpp" 10 #include "Language.hpp" 11 12 namespace sh 13 { 14 class Platform; 15 16 class Configuration : public PropertySetGet 17 { 18 public: setSourceFile(const std::string & file)19 void setSourceFile (const std::string& file) { mSourceFile = file ; } getSourceFile()20 std::string getSourceFile () { return mSourceFile; } 21 22 void save(const std::string& name, std::ofstream &stream); 23 24 private: 25 std::string mSourceFile; 26 }; 27 28 typedef std::map<std::string, MaterialInstance> MaterialMap; 29 typedef std::map<std::string, ShaderSet> ShaderSetMap; 30 typedef std::map<std::string, Configuration> ConfigurationMap; 31 typedef std::map<int, PropertySetGet> LodConfigurationMap; 32 typedef std::map<std::string, int> LastModifiedMap; 33 34 typedef std::map<std::string, std::string> TextureAliasMap; 35 36 /** 37 * @brief 38 * Allows you to be notified when a certain material was just created. Useful for changing material properties that you can't 39 * do in a .mat script (for example a series of animated textures) \n 40 * When receiving the event, you can get the platform material by calling m->getMaterial() 41 * and casting that to the platform specific material (e.g. for Ogre, sh::OgreMaterial) 42 */ 43 class MaterialListener 44 { 45 public: 46 virtual void materialCreated (MaterialInstance* m, const std::string& configuration, unsigned short lodIndex) = 0; 47 }; 48 49 /** 50 * @brief 51 * The main interface class 52 */ 53 class Factory 54 { 55 public: 56 Factory(Platform* platform); 57 ///< @note Ownership of \a platform is transferred to this class, so you don't have to delete it. 58 59 ~Factory(); 60 61 /** 62 * Create a MaterialInstance, optionally copying all properties from \a parentInstance 63 * @param name name of the new instance 64 * @param name of the parent (optional) 65 * @return newly created instance 66 */ 67 MaterialInstance* createMaterialInstance (const std::string& name, const std::string& parentInstance = ""); 68 69 /// @note It is safe to call this if the instance does not exist 70 void destroyMaterialInstance (const std::string& name); 71 72 /// Use this to enable or disable shaders on-the-fly 73 void setShadersEnabled (bool enabled); 74 75 /// write generated shaders to current directory, useful for debugging 76 void setShaderDebugOutputEnabled (bool enabled); 77 78 /// Use this to manage user settings. \n 79 /// Global settings can be retrieved in shaders through a macro. \n 80 /// When a global setting is changed, the shaders that depend on them are recompiled automatically. 81 void setGlobalSetting (const std::string& name, const std::string& value); 82 83 /// Adjusts the given shared parameter. \n 84 /// Internally, this will change all uniform parameters of this name marked with the macro \@shSharedParameter \n 85 /// @param name of the shared parameter 86 /// @param value of the parameter, use sh::makeProperty to construct this value 87 void setSharedParameter (const std::string& name, PropertyValuePtr value); 88 89 Language getCurrentLanguage (); 90 91 /// Switch between different shader languages (cg, glsl, hlsl) 92 void setCurrentLanguage (Language lang); 93 94 /// Get a MaterialInstance by name 95 MaterialInstance* getMaterialInstance (const std::string& name); 96 97 /// Create a configuration, which can then be altered by using Factory::getConfiguration 98 void createConfiguration (const std::string& name); 99 100 /// Register a lod configuration, which can then be used by setting up lod distance values for the material \n 101 /// 0 refers to highest lod, so use 1 or higher as index parameter 102 void registerLodConfiguration (int index, PropertySetGet configuration); 103 104 /// Set an alias name for a texture, the real name can then be retrieved with the "texture_alias" 105 /// property in a texture unit - this is useful if you don't know the name of your texture beforehand. \n 106 /// Example: \n 107 /// - In the material definition: texture_alias ReflectionMap \n 108 /// - At runtime: factory->setTextureAlias("ReflectionMap", "rtt_654654"); \n 109 /// You can call factory->setTextureAlias as many times as you want, and if the material was already created, its texture will be updated! 110 void setTextureAlias (const std::string& alias, const std::string& realName); 111 112 /// Retrieve the real texture name for a texture alias (the real name is set by the user) 113 std::string retrieveTextureAlias (const std::string& name); 114 115 /// Attach a listener for material created events 116 void setMaterialListener (MaterialListener* listener); 117 118 /// Call this after you have set up basic stuff, like the shader language. 119 void loadAllFiles (); 120 121 /// Controls writing of generated shader source code to the cache folder, so that the 122 /// (rather expensive) preprocessing step can be skipped on the next run. See Factory::setReadSourceCache \n 123 /// \note The default is off (no cache writing) setWriteSourceCache(bool write)124 void setWriteSourceCache(bool write) { mWriteSourceCache = write; } 125 126 /// Controls reading of generated shader sources from the cache folder 127 /// \note The default is off (no cache reading) 128 /// \note Even if microcode caching is enabled, generating (or caching) the source is still required due to the macros. setReadSourceCache(bool read)129 void setReadSourceCache(bool read) { mReadSourceCache = read; } 130 131 /// Controls writing the microcode of the generated shaders to the cache folder. Microcode is machine independent 132 /// and loads very fast compared to regular compilation. Note that the availability of this feature depends on the \a Platform. 133 /// \note The default is off (no cache writing) setWriteMicrocodeCache(bool write)134 void setWriteMicrocodeCache(bool write) { mWriteMicrocodeCache = write; } 135 136 /// Controls reading of shader microcode from the cache folder. Microcode is machine independent 137 /// and loads very fast compared to regular compilation. Note that the availability of this feature depends on the \a Platform. 138 /// \note The default is off (no cache reading) setReadMicrocodeCache(bool read)139 void setReadMicrocodeCache(bool read) { mReadMicrocodeCache = read; } 140 141 /// Lists all materials currently registered with the factory. Whether they are 142 /// loaded or not does not matter. 143 void listMaterials (std::vector<std::string>& out); 144 145 /// Lists current name & value of all global settings. 146 void listGlobalSettings (std::map<std::string, std::string>& out); 147 148 /// Lists configuration names. 149 void listConfigurationNames (std::vector<std::string>& out); 150 151 /// Lists current name & value of settings for a given configuration. 152 void listConfigurationSettings (const std::string& name, std::map<std::string, std::string>& out); 153 154 /// Lists shader sets. 155 void listShaderSets (std::vector<std::string>& out); 156 157 /// \note This only works if microcode caching is disabled, as there is currently no way to remove the cache 158 /// through the Ogre API. Luckily, this is already fixed in Ogre 1.9. 159 bool reloadShaders(); 160 161 /// Calls reloadShaders() if shader files have been modified since the last reload. 162 /// \note This only works if microcode caching is disabled, as there is currently no way to remove the cache 163 /// through the Ogre API. Luckily, this is already fixed in Ogre 1.9. 164 void doMonitorShaderFiles(); 165 166 /// Unloads all materials that are currently not referenced. This will not unload the textures themselves, 167 /// but it will let go of the SharedPtr's to the textures, so that you may unload them if you so desire. \n 168 /// A good time to call this would be after a new level has been loaded, but just calling it occasionally after a period 169 /// of time should work just fine too. 170 void unloadUnreferencedMaterials(); 171 172 void destroyConfiguration (const std::string& name); 173 174 void notifyConfigurationChanged(); 175 176 /// Saves all materials and configurations, by default to the file they were loaded from. 177 /// If you wish to save them elsewhere, use setSourceFile first. 178 void saveAll (); 179 180 /// Returns the error log as a string, then clears it. 181 /// Note: Errors are also written to the standard error output, or thrown if they are fatal. 182 std::string getErrorLog (); 183 184 static Factory& getInstance(); 185 ///< Return instance of this class. 186 187 static Factory* getInstancePtr(); 188 189 /// Make sure a material technique is loaded.\n 190 /// You will probably never have to use this. 191 void _ensureMaterial(const std::string& name, const std::string& configuration); 192 193 194 Configuration* getConfiguration (const std::string& name); 195 196 private: 197 198 MaterialInstance* requestMaterial (const std::string& name, const std::string& configuration, unsigned short lodIndex); 199 ShaderSet* getShaderSet (const std::string& name); 200 Platform* getPlatform (); 201 202 PropertySetGet* getCurrentGlobalSettings(); 203 204 void addTextureAliasInstance (const std::string& name, TextureUnitState* t); 205 void removeTextureAliasInstances (TextureUnitState* t); 206 getCacheFolder()207 std::string getCacheFolder () { return mPlatform->getCacheFolder (); } getReadSourceCache()208 bool getReadSourceCache() { return mReadSourceCache; } getWriteSourceCache()209 bool getWriteSourceCache() { return mWriteSourceCache; } 210 public: getWriteMicrocodeCache()211 bool getWriteMicrocodeCache() { return mWriteMicrocodeCache; } // Fixme 212 213 private: 214 void setActiveConfiguration (const std::string& configuration); 215 void setActiveLodLevel (int level); 216 getShaderDebugOutputEnabled()217 bool getShaderDebugOutputEnabled() { return mShaderDebugOutputEnabled; } 218 219 std::map<TextureUnitState*, std::string> mTextureAliasInstances; 220 221 void logError (const std::string& msg); 222 223 friend class Platform; 224 friend class MaterialInstance; 225 friend class ShaderInstance; 226 friend class ShaderSet; 227 friend class TextureUnitState; 228 229 private: 230 static Factory* sThis; 231 232 bool mShadersEnabled; 233 bool mShaderDebugOutputEnabled; 234 235 bool mReadMicrocodeCache; 236 bool mWriteMicrocodeCache; 237 bool mReadSourceCache; 238 bool mWriteSourceCache; 239 std::stringstream mErrorLog; 240 241 MaterialMap mMaterials; 242 ShaderSetMap mShaderSets; 243 ConfigurationMap mConfigurations; 244 LodConfigurationMap mLodConfigurations; 245 LastModifiedMap mShadersLastModified; 246 LastModifiedMap mShadersLastModifiedNew; 247 248 PropertySetGet mGlobalSettings; 249 250 PropertySetGet* mCurrentConfiguration; 251 PropertySetGet* mCurrentLodConfiguration; 252 253 TextureAliasMap mTextureAliases; 254 255 Language mCurrentLanguage; 256 257 MaterialListener* mListener; 258 259 Platform* mPlatform; 260 261 MaterialInstance* findInstance (const std::string& name); 262 MaterialInstance* searchInstance (const std::string& name); 263 264 /// @return was anything removed? 265 bool removeCache (const std::string& pattern); 266 267 static const std::string mBinaryCacheName; 268 }; 269 } 270 271 #endif 272