SO3Engine
SO3MaterialGenerator.h
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#ifndef __SO3_DEFERRED_SHADING_MATERIAL_GENERATOR_H__
26#define __SO3_DEFERRED_SHADING_MATERIAL_GENERATOR_H__
27
29#include "SO3GBuffer.h"
30#include "OgreMaterial.h"
31
32namespace SO3
33{
34
45template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> class SMaterialGenerator
46{
47public:
48 typedef PERMUTATION_TYPE Perm;
49protected:
50 const Ogre::String materialBaseName;
51private:
52 typedef typename Ogre::map<PERMUTATION_TYPE, Ogre::GpuProgramPtr>::type ProgramPermMap;
53 typedef typename Ogre::map<SGBuffer*, typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap*>::type ProgramMap;
54 typedef typename Ogre::map<PERMUTATION_TYPE, Ogre::MaterialPtr>::type MaterialPermMap;
55 typedef typename Ogre::map<SGBuffer*, typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap*>::type MaterialMap;
56 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramMap mVs;
57 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramMap mFs;
58 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialMap templateMaterials;
59 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialMap materials;
60
61public:
65
69 const Ogre::MaterialPtr& GetMaterial(SGBuffer* gbuffer, PERMUTATION_CLASS permutation);
70
71 /*
72 Function to get statistic on how many materials (instances) resources where created by this deferred material generator.
73 */
74 unsigned int GetDeferredMaterialNumber(SGBuffer* gbuffer);
75
76 /*
77 Function to get statistic on how many materials (templates) resources where created by this deferred material generator.
78 */
80
85
89 unsigned int GetDeferredPixelShaderNumber(SGBuffer* gbuffer);
90
95 void ResetResources(SGBuffer* gbuffer);
96protected:
102 SMaterialGenerator(const Ogre::String& typeName);
103
106 const Ogre::GpuProgramPtr& GetVertexShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue);
107
108 /*
109 */
110 const Ogre::GpuProgramPtr& GetFragmentShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue);
111
114 const Ogre::MaterialPtr& GetTemplateMaterial(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue);
115
118 virtual Ogre::GpuProgramPtr GenerateVertexShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue) = 0;
119
122 virtual Ogre::GpuProgramPtr GenerateFragmentShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue) = 0;
123
126 virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue) = 0;
127private:
132};
133
134template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::SMaterialGenerator(const Ogre::String& typeName) : materialBaseName(Ogre::String("SO3/Deferred/") + typeName)
135{
136}
137
138template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::SMaterialGenerator() : materialBaseName("")
139{
140 // Forbiden ctor
141}
142
143template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::~SMaterialGenerator()
144{
145 // Build gbuffer list
146 std::vector<SGBuffer*> gbufferList;
147 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialMap::iterator iTemplateMaterials = templateMaterials.begin();
148 while(iTemplateMaterials != templateMaterials.end())
149 {
150 gbufferList.push_back(iTemplateMaterials->first);
151 iTemplateMaterials++;
152 }
153
154 // Clean all gbuffers
155 std::vector<SGBuffer*>::iterator iGBuffer = gbufferList.begin();
156 while(iGBuffer != gbufferList.end())
157 {
158 // Clean MaterialPermMap etc... instance
160 iGBuffer++;
161 }
162}
163
164template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> unsigned int SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetDeferredMaterialNumber(SGBuffer* gbuffer)
165{
167 if(i != materials.end())
168 return i->second.size();
169 else
170 return 0;
171}
172
173template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> unsigned int SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetDeferredMaterialTemplateNumber(SGBuffer* gbuffer)
174{
176 if(i != templateMaterials.end())
177 return i->second.size();
178 else
179 return 0;
180}
181
182template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> unsigned int SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetDeferredVertexShaderNumber(SGBuffer* gbuffer)
183{
185 if(i != mVs.end())
186 return i->second.size();
187 else
188 return 0;
189}
190
191template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> unsigned int SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetDeferredPixelShaderNumber(SGBuffer* gbuffer)
192{
194 if(i != mFs.end())
195 return i->second.size();
196 else
197 return 0;
198}
199
200template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> void SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ResetResources(SGBuffer* gbuffer)
201{
202 // Ogre's references
203 Ogre::MaterialManager* materialManager = Ogre::MaterialManager::getSingletonPtr();
204 Ogre::HighLevelGpuProgramManager* programManager = Ogre::HighLevelGpuProgramManager::getSingletonPtr();
205
206 // Reset templates materials
207 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialMap::iterator iTemplateMaterials = templateMaterials.find(gbuffer);
208 if(iTemplateMaterials != templateMaterials.end())
209 {
210 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap* materialPermMap = iTemplateMaterials->second;
211 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap::iterator iTemplatePermutations = materialPermMap->begin();
212 while(iTemplatePermutations != materialPermMap->end())
213 {
214 materialManager->remove(iTemplatePermutations->second->getHandle());
215 iTemplatePermutations++;
216 }
217
218 // Erase from our list, this will erase the last reference to MaterialPtr, and will effectively destroy it.
219 SO3_SAFE_DELETE(iTemplateMaterials->second);
220 templateMaterials.erase(iTemplateMaterials);
221 }
222
223 // Reset materials
224 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialMap::iterator iMaterials = materials.find(gbuffer);
225 if(iMaterials != materials.end())
226 {
227 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap* materialPermMap = iMaterials->second;
228 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap::iterator iPermutations = materialPermMap->begin();
229 while(iPermutations != materialPermMap->end())
230 {
231 materialManager->remove(iPermutations->second->getHandle());
232 iPermutations++;
233 }
234
235 // Erase from our list, this will erase the last reference to MaterialPtr, and will effectively destroy it.
236 SO3_SAFE_DELETE(iMaterials->second);
237 materials.erase(iMaterials);
238 }
239
240 // Reset vertex shaders
242 if(iVertex != mVs.end())
243 {
244 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap* vertexPermMap = iVertex->second;
245 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap::iterator iPermutations = vertexPermMap->begin();
246 while(iPermutations != vertexPermMap->end())
247 {
248 programManager->remove(iPermutations->second->getHandle());
249 iPermutations++;
250 }
251
252 // Erase from our list, this will erase the last reference to MaterialPtr, and will effectively destroy it.
253 SO3_SAFE_DELETE(iVertex->second);
254 mVs.erase(iVertex);
255 }
256
257 // Reset fragments shaders
259 if(iFragment != mFs.end())
260 {
261 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap* fragmentPermMap = iFragment->second;
262 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap::iterator iPermutations = fragmentPermMap->begin();
263 while(iPermutations != fragmentPermMap->end())
264 {
265 programManager->remove(iPermutations->second->getHandle());
266 iPermutations++;
267 }
268
269 // Erase from our list, this will erase the last reference to MaterialPtr, and will effectively destroy it.
270 SO3_SAFE_DELETE(iFragment->second);
271 mFs.erase(iFragment);
272 }
273}
274
275template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> const Ogre::MaterialPtr& SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetMaterial(SGBuffer* gbuffer, PERMUTATION_CLASS permutation)
276{
277 // Check if the GBuffer instance was already used
278 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap* materialPermMap = 0;
280 if(i == materials.end())
281 {
282 // Not found create a new material permutation map
283 materialPermMap = new SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap();
284 materials[gbuffer] = materialPermMap;
285 }
286 else
287 {
288 materialPermMap = i->second;
289 }
290
291 // Check if material/shader permutation was already generated
292 PERMUTATION_TYPE permutationValue = permutation.GetPermutations();
293 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap::iterator j = materialPermMap->find(permutationValue);
294 if(j != materialPermMap->end())
295 {
296 return j->second;
297 }
298 else
299 {
300 // Create it
301 Ogre::MaterialPtr templ = GetTemplateMaterial(gbuffer, permutation.GetMaterialPermutations());
302 Ogre::GpuProgramPtr vs = GetVertexShader(gbuffer, permutation.GetVertexPermutations());
303 Ogre::GpuProgramPtr fs = GetFragmentShader(gbuffer, permutation.GetFragmentPermutations());
304
305 // Create material name
306 Ogre::String name = materialBaseName + permutation.ToString();
307 std::cerr << name << " " << vs->getName() << " " << fs->getName() << std::endl;
308
309 // Create material from template, and set shaders
310 Ogre::MaterialPtr mat = templ->clone(name);
311 Ogre::Technique* tech = mat->getTechnique(0);
312 Ogre::Pass* pass = tech->getPass(0);
313 pass->setFragmentProgram(fs->getName());
314 pass->setVertexProgram(vs->getName());
315
316 // Store it and return it
318 materialPermMap->insert(materialPermMap->begin(), val);
319 return mat;
320 }
321}
322
323template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> const Ogre::GpuProgramPtr& SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetVertexShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue)
324{
325 // Check if the GBuffer instance was already used
326 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap* programPermMap = 0;
328 if(i == mVs.end())
329 {
330 // Not found create a new material permutation map
331 programPermMap = new SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap();
332 mVs[gbuffer] = programPermMap;
333 }
334 else
335 {
336 programPermMap = i->second;
337 }
338
339 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap::iterator j = programPermMap->find(permutationValue);
340 if(j != programPermMap->end())
341 {
342 return j->second;
343 }
344 else
345 {
346 // Create it, store it and return it
347 Ogre::GpuProgramPtr progptr = GenerateVertexShader(gbuffer, permutationValue);
349 programPermMap->insert(programPermMap->begin(), val);
350 return progptr;
351 }
352}
353
354template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> const Ogre::GpuProgramPtr& SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetFragmentShader(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue)
355{
356 // Check if the GBuffer instance was already used
357 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap* programPermMap = 0;
359 if(i == mFs.end())
360 {
361 // Not found create a new material permutation map
362 programPermMap = new SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap();
363 mFs[gbuffer] = programPermMap;
364 }
365 else
366 {
367 programPermMap = i->second;
368 }
369
370 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::ProgramPermMap::iterator j = programPermMap->find(permutationValue);
371 if(j != programPermMap->end())
372 {
373 return j->second;
374 }
375 else
376 {
377 // Create it, store it and return it
378 Ogre::GpuProgramPtr progptr = GenerateFragmentShader(gbuffer, permutationValue);
380 programPermMap->insert(programPermMap->begin(), val);
381 return progptr;
382 }
383}
384
385template <class PERMUTATION_CLASS, typename PERMUTATION_TYPE> const Ogre::MaterialPtr& SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::GetTemplateMaterial(SGBuffer* gbuffer, PERMUTATION_TYPE permutationValue)
386{
387 // Check if the GBuffer instance was already used
388 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap* materialPermMap = 0;
390 if(i == templateMaterials.end())
391 {
392 // Not found create a new material permutation map
393 materialPermMap = new SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap();
394 templateMaterials[gbuffer] = materialPermMap;
395 }
396 else
397 {
398 materialPermMap = i->second;
399 }
400
401 typename SMaterialGenerator<PERMUTATION_CLASS, PERMUTATION_TYPE>::MaterialPermMap::iterator j = materialPermMap->find(permutationValue);
402 if(j != materialPermMap->end())
403 {
404 return j->second;
405 }
406 else
407 {
408 // Create it
409 Ogre::MaterialPtr matptr = GenerateTemplateMaterial(gbuffer, permutationValue);
411 materialPermMap->insert(materialPermMap->begin(), val);
412 return matptr;
413 }
414}
415
416}
417
418#endif
librairies include
SMaterialGenerator(const Ogre::String &typeName)
const Ogre::MaterialPtr & GetTemplateMaterial(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)
unsigned int GetDeferredMaterialNumber(SGBuffer *gbuffer)
virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)=0
unsigned int GetDeferredMaterialTemplateNumber(SGBuffer *gbuffer)
const Ogre::GpuProgramPtr & GetFragmentShader(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)
const Ogre::MaterialPtr & GetMaterial(SGBuffer *gbuffer, PERMUTATION_CLASS permutation)
void ResetResources(SGBuffer *gbuffer)
const Ogre::String materialBaseName
Base name of materials generated by this.
virtual Ogre::GpuProgramPtr GenerateVertexShader(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)=0
unsigned int GetDeferredVertexShaderNumber(SGBuffer *gbuffer)
PERMUTATION_TYPE Perm
Bitfield used to signify a material permutations.
virtual Ogre::GpuProgramPtr GenerateFragmentShader(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)=0
const Ogre::GpuProgramPtr & GetVertexShader(SGBuffer *gbuffer, PERMUTATION_TYPE permutationValue)
unsigned int GetDeferredPixelShaderNumber(SGBuffer *gbuffer)