1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 -----------------------------------------------------------------------------
26 */
27 #include "OgreShaderGenerator.h"
28 #include "OgreShaderProgram.h"
29 #include "OgreShaderProgramManager.h"
30 #include "OgreShaderFFPRenderStateBuilder.h"
31 #include "OgreShaderRenderState.h"
32 #include "OgreMaterialManager.h"
33 #include "OgreTechnique.h"
34 #include "OgreSceneManager.h"
35 #include "OgreViewport.h"
36 #include "OgreShaderExPerPixelLighting.h"
37 #include "OgreShaderExNormalMapLighting.h"
38 #include "OgreShaderExIntegratedPSSM3.h"
39 #include "OgreShaderExLayeredBlending.h"
40 #include "OgreShaderExHardwareSkinning.h"
41 #include "OgreShaderMaterialSerializerListener.h"
42 #include "OgreShaderProgramWriterManager.h"
43 #include "OgreGpuProgramManager.h"
44 #include "OgreHighLevelGpuProgramManager.h"
45 #include "OgreShaderExTextureAtlasSampler.h"
46 #include "OgreShaderExTriplanarTexturing.h"
47
48 namespace Ogre {
49
50 const String cBlankString;
51
52 //-----------------------------------------------------------------------
53 template<>
54 RTShader::ShaderGenerator* Singleton<RTShader::ShaderGenerator>::msSingleton = 0;
55
56 namespace RTShader {
57
58 String ShaderGenerator::DEFAULT_SCHEME_NAME = "ShaderGeneratorDefaultScheme";
59 String GENERATED_SHADERS_GROUP_NAME = "ShaderGeneratorResourceGroup";
60 String ShaderGenerator::SGPass::UserKey = "SGPass";
61 String ShaderGenerator::SGTechnique::UserKey = "SGTechnique";
62
63 //-----------------------------------------------------------------------
getSingletonPtr()64 ShaderGenerator* ShaderGenerator::getSingletonPtr()
65 {
66 return msSingleton;
67 }
68
69 //-----------------------------------------------------------------------
getSingleton()70 ShaderGenerator& ShaderGenerator::getSingleton()
71 {
72 assert( msSingleton );
73 return ( *msSingleton );
74 }
75
76 //-----------------------------------------------------------------------------
ShaderGenerator()77 ShaderGenerator::ShaderGenerator()
78 {
79 mProgramWriterManager = NULL;
80 mProgramManager = NULL;
81 mFFPRenderStateBuilder = NULL;
82 mActiveSceneMgr = NULL;
83 mRenderObjectListener = NULL;
84 mSceneManagerListener = NULL;
85 mScriptTranslatorManager = NULL;
86 mMaterialSerializerListener = NULL;
87 mActiveViewportValid = false;
88 mLightCount[0] = 0;
89 mLightCount[1] = 0;
90 mLightCount[2] = 0;
91 mVSOutputCompactPolicy = VSOCP_LOW;
92 mCreateShaderOverProgrammablePass = false;
93 mIsFinalizing = false;
94 mFSLayer = 0;
95 mShaderLanguage = "";
96
97 HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton();
98
99 if (hmgr.isLanguageSupported("glsles"))
100 {
101 mShaderLanguage = "glsles";
102 }
103 else if (hmgr.isLanguageSupported("cg"))
104 {
105 mShaderLanguage = "cg";
106 }
107 else if (hmgr.isLanguageSupported("glsl"))
108 {
109 mShaderLanguage = "glsl";
110 }
111 else if (hmgr.isLanguageSupported("hlsl"))
112 {
113 mShaderLanguage = "hlsl";
114 }
115 else
116 {
117 // ASSAF: This is disabled for now - to stop an exception on the iOS
118 // when running with the OpenGL ES 1.x that doesn't support shaders...
119 /*
120 OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
121 "ShaderGenerator creation error: None of the profiles is supported.",
122 "ShaderGenerator::ShaderGenerator" );
123
124 */
125 mShaderLanguage = "cg"; // HACK for now
126 }
127
128 setVertexShaderProfiles("gpu_vp gp4vp vp40 vp30 arbvp1 vs_4_0 vs_4_0_level_9_3 vs_4_0_level_9_1 vs_3_0 vs_2_x vs_2_a vs_2_0 vs_1_1");
129 setFragmentShaderProfiles("ps_4_0 ps_4_0_level_9_3 ps_4_0_level_9_1 ps_3_x ps_3_0 fp40 fp30 fp20 arbfp1 ps_2_x ps_2_a ps_2_b ps_2_0 ps_1_4 ps_1_3 ps_1_2 ps_1_1");
130 }
131
132 //-----------------------------------------------------------------------------
~ShaderGenerator()133 ShaderGenerator::~ShaderGenerator()
134 {
135
136 }
137
138 //-----------------------------------------------------------------------------
initialize()139 bool ShaderGenerator::initialize()
140 {
141 if (msSingleton == NULL)
142 {
143 msSingleton = OGRE_NEW ShaderGenerator;
144 if (false == msSingleton->_initialize())
145 {
146 OGRE_DELETE msSingleton;
147 msSingleton = NULL;
148 return false;
149 }
150 }
151
152 return true;
153 }
154
155 //-----------------------------------------------------------------------------
_initialize()156 bool ShaderGenerator::_initialize()
157 {
158 OGRE_LOCK_AUTO_MUTEX;
159
160 // Allocate program writer manager.
161 mProgramWriterManager = OGRE_NEW ProgramWriterManager;
162
163 // Allocate program manager.
164 mProgramManager = OGRE_NEW ProgramManager;
165
166 // Allocate and initialize FFP render state builder.
167 #ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
168 mFFPRenderStateBuilder = OGRE_NEW FFPRenderStateBuilder;
169 if (false == mFFPRenderStateBuilder->initialize())
170 return false;
171 #endif
172
173 // Create extensions factories.
174 createSubRenderStateExFactories();
175
176 // Allocate script translator manager.
177 mScriptTranslatorManager = OGRE_NEW SGScriptTranslatorManager(this);
178 ScriptCompilerManager::getSingleton().addTranslatorManager(mScriptTranslatorManager);
179
180 addCustomScriptTranslator("rtshader_system", &mCoreScriptTranslator);
181
182 // Create the default scheme.
183 createScheme(DEFAULT_SCHEME_NAME);
184
185 return true;
186 }
187
188
189
190 //-----------------------------------------------------------------------------
createSubRenderStateExFactories()191 void ShaderGenerator::createSubRenderStateExFactories()
192 {
193 #ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
194 OGRE_LOCK_AUTO_MUTEX;
195
196 SubRenderStateFactory* curFactory;
197
198 // check if we are running an old shader level in d3d11
199 bool d3d11AndLowProfile = ( (GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0_level_9_1") ||
200 GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0_level_9_3"))
201 && !GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0"));
202 if(!d3d11AndLowProfile)
203 {
204 curFactory = OGRE_NEW PerPixelLightingFactory;
205 addSubRenderStateFactory(curFactory);
206 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
207
208 curFactory = OGRE_NEW NormalMapLightingFactory;
209 addSubRenderStateFactory(curFactory);
210 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
211
212 curFactory = OGRE_NEW IntegratedPSSM3Factory;
213 addSubRenderStateFactory(curFactory);
214 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
215
216 curFactory = OGRE_NEW LayeredBlendingFactory;
217 addSubRenderStateFactory(curFactory);
218 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
219
220 curFactory = OGRE_NEW HardwareSkinningFactory;
221 addSubRenderStateFactory(curFactory);
222 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
223 }
224
225 curFactory = OGRE_NEW TextureAtlasSamplerFactory;
226 addSubRenderStateFactory(curFactory);
227 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
228
229 curFactory = OGRE_NEW TriplanarTexturingFactory;
230 addSubRenderStateFactory(curFactory);
231 mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
232 #endif
233 }
234
235 //-----------------------------------------------------------------------------
destroy()236 void ShaderGenerator::destroy()
237 {
238 if (msSingleton != NULL)
239 {
240 msSingleton->_destroy();
241
242 OGRE_DELETE msSingleton;
243 msSingleton = NULL;
244 }
245 }
246
247 //-----------------------------------------------------------------------------
_destroy()248 void ShaderGenerator::_destroy()
249 {
250 OGRE_LOCK_AUTO_MUTEX;
251
252 mIsFinalizing = true;
253
254 // Delete technique entries.
255 for (SGTechniqueMapIterator itTech = mTechniqueEntriesMap.begin(); itTech != mTechniqueEntriesMap.end(); ++itTech)
256 {
257 OGRE_DELETE (itTech->second);
258 }
259 mTechniqueEntriesMap.clear();
260
261 // Delete material entries.
262 for (SGMaterialIterator itMat = mMaterialEntriesMap.begin(); itMat != mMaterialEntriesMap.end(); ++itMat)
263 {
264 OGRE_DELETE (itMat->second);
265 }
266 mMaterialEntriesMap.clear();
267
268 // Delete scheme entries.
269 for (SGSchemeIterator itScheme = mSchemeEntriesMap.begin(); itScheme != mSchemeEntriesMap.end(); ++itScheme)
270 {
271 OGRE_DELETE (itScheme->second);
272 }
273 mSchemeEntriesMap.clear();
274
275 // Destroy extensions factories.
276 destroySubRenderStateExFactories();
277
278 #ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
279 // Delete FFP Emulator.
280 if (mFFPRenderStateBuilder != NULL)
281 {
282 mFFPRenderStateBuilder->destroy();
283 OGRE_DELETE mFFPRenderStateBuilder;
284 mFFPRenderStateBuilder = NULL;
285 }
286 #endif
287
288 // Delete Program manager.
289 if (mProgramManager != NULL)
290 {
291 OGRE_DELETE mProgramManager;
292 mProgramManager = NULL;
293 }
294
295 // Delete Program writer manager.
296 if(mProgramWriterManager != NULL)
297 {
298 OGRE_DELETE mProgramWriterManager;
299 mProgramWriterManager = NULL;
300 }
301
302 removeCustomScriptTranslator("rtshader_system");
303
304 // Delete script translator manager.
305 if (mScriptTranslatorManager != NULL)
306 {
307 ScriptCompilerManager::getSingleton().removeTranslatorManager(mScriptTranslatorManager);
308 OGRE_DELETE mScriptTranslatorManager;
309 mScriptTranslatorManager = NULL;
310 }
311
312 // Delete material Serializer listener.
313 if (mMaterialSerializerListener != NULL)
314 {
315 OGRE_DELETE mMaterialSerializerListener;
316 mMaterialSerializerListener = NULL;
317 }
318
319 // Remove all scene managers.
320 while (mSceneManagerMap.empty() == false)
321 {
322 SceneManagerIterator itSceneMgr = mSceneManagerMap.begin();
323
324 removeSceneManager(itSceneMgr->second);
325 }
326
327 // Delete render object listener.
328 if (mRenderObjectListener != NULL)
329 {
330 OGRE_DELETE mRenderObjectListener;
331 mRenderObjectListener = NULL;
332 }
333
334 // Delete scene manager listener.
335 if (mSceneManagerListener != NULL)
336 {
337 OGRE_DELETE mSceneManagerListener;
338 mSceneManagerListener = NULL;
339 }
340 }
341
342 //-----------------------------------------------------------------------------
destroySubRenderStateExFactories()343 void ShaderGenerator::destroySubRenderStateExFactories()
344 {
345 OGRE_LOCK_AUTO_MUTEX;
346
347 SubRenderStateFactoryIterator it;
348
349 for (it = mSubRenderStateExFactories.begin(); it != mSubRenderStateExFactories.end(); ++it)
350 {
351 removeSubRenderStateFactory(it->second);
352 OGRE_DELETE it->second;
353 }
354 mSubRenderStateExFactories.clear();
355 }
356
357 //-----------------------------------------------------------------------------
addSubRenderStateFactory(SubRenderStateFactory * factory)358 void ShaderGenerator::addSubRenderStateFactory(SubRenderStateFactory* factory)
359 {
360 OGRE_LOCK_AUTO_MUTEX;
361
362 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.find(factory->getType());
363
364 if (itFind != mSubRenderStateFactories.end())
365 {
366 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
367 "A factory of type '" + factory->getType() + "' already exists.",
368 "ShaderGenerator::addSubRenderStateFactory");
369 }
370
371 mSubRenderStateFactories[factory->getType()] = factory;
372 }
373
374 //-----------------------------------------------------------------------------
getNumSubRenderStateFactories() const375 size_t ShaderGenerator::getNumSubRenderStateFactories() const
376 {
377 return mSubRenderStateFactories.size();
378 }
379
380
381 //-----------------------------------------------------------------------------
getSubRenderStateFactory(size_t index)382 SubRenderStateFactory* ShaderGenerator::getSubRenderStateFactory(size_t index)
383 {
384 {
385 OGRE_LOCK_AUTO_MUTEX;
386
387 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.begin();
388 for(; index != 0 && itFind != mSubRenderStateFactories.end(); --index , ++itFind);
389
390 if (itFind != mSubRenderStateFactories.end())
391 {
392 return itFind->second;
393 }
394 }
395
396 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
397 "A factory on index " + StringConverter::toString(index) + " does not exist.",
398 "ShaderGenerator::addSubRenderStateFactory");
399
400 return NULL;
401 }
402 //-----------------------------------------------------------------------------
getSubRenderStateFactory(const String & type)403 SubRenderStateFactory* ShaderGenerator::getSubRenderStateFactory(const String& type)
404 {
405 OGRE_LOCK_AUTO_MUTEX;
406
407 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.find(type);
408 return (itFind != mSubRenderStateFactories.end()) ? itFind->second : NULL;
409 }
410
411 //-----------------------------------------------------------------------------
removeSubRenderStateFactory(SubRenderStateFactory * factory)412 void ShaderGenerator::removeSubRenderStateFactory(SubRenderStateFactory* factory)
413 {
414 OGRE_LOCK_AUTO_MUTEX;
415
416 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.find(factory->getType());
417
418 if (itFind != mSubRenderStateFactories.end())
419 mSubRenderStateFactories.erase(itFind);
420
421 }
422
423 //-----------------------------------------------------------------------------
createSubRenderState(const String & type)424 SubRenderState* ShaderGenerator::createSubRenderState(const String& type)
425 {
426 OGRE_LOCK_AUTO_MUTEX;
427
428 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.find(type);
429
430 if (itFind != mSubRenderStateFactories.end())
431 return itFind->second->createInstance();
432
433
434 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
435 "A factory of type '" + type + "' doesn't exists.",
436 "ShaderGenerator::createSubRenderState");
437
438 return NULL;
439 }
440
441 //-----------------------------------------------------------------------------
destroySubRenderState(SubRenderState * subRenderState)442 void ShaderGenerator::destroySubRenderState(SubRenderState* subRenderState)
443 {
444 OGRE_LOCK_AUTO_MUTEX;
445
446 SubRenderStateFactoryIterator itFind = mSubRenderStateFactories.find(subRenderState->getType());
447
448 if (itFind != mSubRenderStateFactories.end())
449 {
450 itFind->second->destroyInstance(subRenderState);
451 }
452 }
453
454 //-----------------------------------------------------------------------------
createSubRenderState(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)455 SubRenderState* ShaderGenerator::createSubRenderState(ScriptCompiler* compiler,
456 PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
457 {
458 OGRE_LOCK_AUTO_MUTEX;
459
460 SubRenderStateFactoryIterator it = mSubRenderStateFactories.begin();
461 SubRenderStateFactoryIterator itEnd = mSubRenderStateFactories.end();
462 SubRenderState* subRenderState = NULL;
463
464 while (it != itEnd)
465 {
466 subRenderState = it->second->createInstance(compiler, prop, pass, translator);
467 if (subRenderState != NULL)
468 break;
469 ++it;
470 }
471
472 return subRenderState;
473 }
474
475
476 //-----------------------------------------------------------------------------
createSubRenderState(ScriptCompiler * compiler,PropertyAbstractNode * prop,TextureUnitState * texState,SGScriptTranslator * translator)477 SubRenderState* ShaderGenerator::createSubRenderState(ScriptCompiler* compiler,
478 PropertyAbstractNode* prop, TextureUnitState* texState, SGScriptTranslator* translator)
479 {
480 OGRE_LOCK_AUTO_MUTEX;
481
482 SubRenderStateFactoryIterator it = mSubRenderStateFactories.begin();
483 SubRenderStateFactoryIterator itEnd = mSubRenderStateFactories.end();
484 SubRenderState* subRenderState = NULL;
485
486 while (it != itEnd)
487 {
488 subRenderState = it->second->createInstance(compiler, prop, texState, translator);
489 if (subRenderState != NULL)
490 break;
491 ++it;
492 }
493
494 return subRenderState;
495 }
496
497 //-----------------------------------------------------------------------------
createScheme(const String & schemeName)498 void ShaderGenerator::createScheme(const String& schemeName)
499 {
500 OGRE_LOCK_AUTO_MUTEX;
501
502 SGSchemeIterator itFind = mSchemeEntriesMap.find(schemeName);
503 SGScheme* schemeEntry = NULL;
504
505 if (itFind == mSchemeEntriesMap.end())
506 {
507 schemeEntry = OGRE_NEW SGScheme(schemeName);
508 mSchemeEntriesMap[schemeName] = schemeEntry;
509 }
510 }
511
512 //-----------------------------------------------------------------------------
getRenderState(const String & schemeName)513 RenderState* ShaderGenerator::getRenderState(const String& schemeName)
514 {
515 OGRE_LOCK_AUTO_MUTEX;
516
517 SGSchemeIterator itFind = mSchemeEntriesMap.find(schemeName);
518
519 if (itFind == mSchemeEntriesMap.end())
520 {
521 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
522 "A scheme named'" + schemeName + "' doesn't exists.",
523 "ShaderGenerator::getRenderState");
524 }
525
526 return itFind->second->getRenderState();
527 }
528
529 //-----------------------------------------------------------------------------
hasRenderState(const String & schemeName) const530 bool ShaderGenerator::hasRenderState(const String& schemeName) const
531 {
532 OGRE_LOCK_AUTO_MUTEX;
533
534 SGSchemeConstIterator itFind = mSchemeEntriesMap.find(schemeName);
535 return itFind != mSchemeEntriesMap.end();
536 }
537
538 //-----------------------------------------------------------------------------
createOrRetrieveRenderState(const String & schemeName)539 ShaderGenerator::RenderStateCreateOrRetrieveResult ShaderGenerator::createOrRetrieveRenderState(const String& schemeName)
540 {
541 SchemeCreateOrRetrieveResult res = createOrRetrieveScheme(schemeName);
542 return RenderStateCreateOrRetrieveResult(res.first->getRenderState(),res.second);
543 }
544
545 //-----------------------------------------------------------------------------
createOrRetrieveScheme(const String & schemeName)546 ShaderGenerator::SchemeCreateOrRetrieveResult ShaderGenerator::createOrRetrieveScheme(const String& schemeName)
547 {
548 OGRE_LOCK_AUTO_MUTEX;
549
550 bool wasCreated = false;
551 SGSchemeIterator itScheme = mSchemeEntriesMap.find(schemeName);
552 SGScheme* schemeEntry = NULL;
553
554 if (itScheme == mSchemeEntriesMap.end())
555 {
556 schemeEntry = OGRE_NEW SGScheme(schemeName);
557 mSchemeEntriesMap.insert(SGSchemeMap::value_type(schemeName, schemeEntry));
558 wasCreated = true;
559 }
560 else
561 {
562 schemeEntry = itScheme->second;
563 }
564
565 return SchemeCreateOrRetrieveResult(schemeEntry, wasCreated);
566 }
567
568 //-----------------------------------------------------------------------------
getRenderState(const String & schemeName,const String & materialName,unsigned short passIndex)569 RenderState* ShaderGenerator::getRenderState(const String& schemeName,
570 const String& materialName,
571 unsigned short passIndex)
572 {
573 return getRenderState(schemeName, materialName,
574 ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, passIndex);
575 }
576 //-----------------------------------------------------------------------------
getRenderState(const String & schemeName,const String & materialName,const String & groupName,unsigned short passIndex)577 RenderState* ShaderGenerator::getRenderState(const String& schemeName,
578 const String& materialName,
579 const String& groupName,
580 unsigned short passIndex)
581 {
582 OGRE_LOCK_AUTO_MUTEX;
583
584 SGSchemeIterator itFind = mSchemeEntriesMap.find(schemeName);
585
586 if (itFind == mSchemeEntriesMap.end())
587 {
588 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
589 "A scheme named'" + schemeName + "' doesn't exists.",
590 "ShaderGenerator::getRenderState");
591 }
592
593 return itFind->second->getRenderState(materialName, groupName, passIndex);
594 }
595
596 //-----------------------------------------------------------------------------
addSceneManager(SceneManager * sceneMgr)597 void ShaderGenerator::addSceneManager(SceneManager* sceneMgr)
598 {
599 // Make sure this scene manager not exists in the map.
600 SceneManagerIterator itFind = mSceneManagerMap.find(sceneMgr->getName());
601
602 if (itFind != mSceneManagerMap.end())
603 return;
604
605 if (mRenderObjectListener == NULL)
606 mRenderObjectListener = OGRE_NEW SGRenderObjectListener(this);
607
608 sceneMgr->addRenderObjectListener(mRenderObjectListener);
609
610 if (mSceneManagerListener == NULL)
611 mSceneManagerListener = OGRE_NEW SGSceneManagerListener(this);
612
613 sceneMgr->addListener(mSceneManagerListener);
614
615 mSceneManagerMap[sceneMgr->getName()] = sceneMgr;
616
617 // Update the active scene manager.
618 if (mActiveSceneMgr == NULL)
619 mActiveSceneMgr = sceneMgr;
620 }
621
622 //-----------------------------------------------------------------------------
removeSceneManager(SceneManager * sceneMgr)623 void ShaderGenerator::removeSceneManager(SceneManager* sceneMgr)
624 {
625 // Make sure this scene manager exists in the map.
626 SceneManagerIterator itFind = mSceneManagerMap.find(sceneMgr->getName());
627
628 if (itFind != mSceneManagerMap.end())
629 {
630 itFind->second->removeRenderObjectListener(mRenderObjectListener);
631 itFind->second->removeListener(mSceneManagerListener);
632
633 mSceneManagerMap.erase(itFind);
634
635 // Update the active scene manager.
636 if (mActiveSceneMgr == sceneMgr)
637 mActiveSceneMgr = NULL;
638 }
639 }
640
641 //-----------------------------------------------------------------------------
getActiveSceneManager()642 SceneManager* ShaderGenerator::getActiveSceneManager()
643 {
644 return mActiveSceneMgr;
645 }
646
647 //-----------------------------------------------------------------------------
setVertexShaderProfiles(const String & vertexShaderProfiles)648 void ShaderGenerator::setVertexShaderProfiles(const String& vertexShaderProfiles)
649 {
650 mVertexShaderProfiles = vertexShaderProfiles;
651 mVertexShaderProfilesList = StringUtil::split(vertexShaderProfiles);
652 }
653 //-----------------------------------------------------------------------------
setFragmentShaderProfiles(const String & fragmentShaderProfiles)654 void ShaderGenerator::setFragmentShaderProfiles(const String& fragmentShaderProfiles)
655 {
656 mFragmentShaderProfiles = fragmentShaderProfiles;
657 mFragmentShaderProfilesList = StringUtil::split(fragmentShaderProfiles);
658 }
659
660 //-----------------------------------------------------------------------------
hasShaderBasedTechnique(const String & materialName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName) const661 bool ShaderGenerator::hasShaderBasedTechnique(const String& materialName,
662 const String& srcTechniqueSchemeName,
663 const String& dstTechniqueSchemeName) const
664 {
665 return hasShaderBasedTechnique(materialName, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
666 srcTechniqueSchemeName, dstTechniqueSchemeName);
667 }
668 //-----------------------------------------------------------------------------
hasShaderBasedTechnique(const String & materialName,const String & groupName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName) const669 bool ShaderGenerator::hasShaderBasedTechnique(const String& materialName,
670 const String& groupName,
671 const String& srcTechniqueSchemeName,
672 const String& dstTechniqueSchemeName) const
673 {
674 OGRE_LOCK_AUTO_MUTEX;
675
676 // Make sure material exists;
677 if (false == MaterialManager::getSingleton().resourceExists(materialName))
678 return false;
679
680
681 SGMaterialConstIterator itMatEntry = findMaterialEntryIt(materialName, groupName);
682
683 // Check if technique already created.
684 if (itMatEntry != mMaterialEntriesMap.end())
685 {
686 const SGTechniqueList& techniqueEntires = itMatEntry->second->getTechniqueList();
687 SGTechniqueConstIterator itTechEntry = techniqueEntires.begin();
688
689 for (; itTechEntry != techniqueEntires.end(); ++itTechEntry)
690 {
691 // Check requested mapping already exists.
692 if ((*itTechEntry)->getSourceTechnique()->getSchemeName() == srcTechniqueSchemeName &&
693 (*itTechEntry)->getDestinationTechniqueSchemeName() == dstTechniqueSchemeName)
694 {
695 return true;
696 }
697 }
698 }
699 return false;
700 }
701 //-----------------------------------------------------------------------------
createShaderBasedTechnique(const String & materialName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName,bool overProgrammable)702 bool ShaderGenerator::createShaderBasedTechnique(const String& materialName,
703 const String& srcTechniqueSchemeName,
704 const String& dstTechniqueSchemeName,
705 bool overProgrammable)
706 {
707 return createShaderBasedTechnique(materialName, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
708 srcTechniqueSchemeName, dstTechniqueSchemeName, overProgrammable);
709 }
710 //-----------------------------------------------------------------------------
createShaderBasedTechnique(const String & materialName,const String & groupName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName,bool overProgrammable)711 bool ShaderGenerator::createShaderBasedTechnique(const String& materialName,
712 const String& groupName,
713 const String& srcTechniqueSchemeName,
714 const String& dstTechniqueSchemeName,
715 bool overProgrammable)
716 {
717 OGRE_LOCK_AUTO_MUTEX;
718
719 // Make sure material exists.
720 MaterialPtr srcMat = MaterialManager::getSingleton().getByName(materialName, groupName);
721 if (srcMat.isNull() == true)
722 return false;
723
724 // Update group name in case it is AUTODETECT_RESOURCE_GROUP_NAME
725 const String& trueGroupName = srcMat->getGroup();
726
727 // Case the requested material belongs to different group and it is not AUTODETECT_RESOURCE_GROUP_NAME.
728 if (trueGroupName != groupName &&
729 groupName != ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
730 {
731 return false;
732 }
733
734 SGMaterialIterator itMatEntry = findMaterialEntryIt(materialName, trueGroupName);
735
736 // Check if technique already created.
737 if (itMatEntry != mMaterialEntriesMap.end())
738 {
739 const SGTechniqueList& techniqueEntires = itMatEntry->second->getTechniqueList();
740 SGTechniqueConstIterator itTechEntry = techniqueEntires.begin();
741
742 for (; itTechEntry != techniqueEntires.end(); ++itTechEntry)
743 {
744 // Case the requested mapping already exists.
745 if ((*itTechEntry)->getSourceTechnique()->getSchemeName() == srcTechniqueSchemeName &&
746 (*itTechEntry)->getDestinationTechniqueSchemeName() == dstTechniqueSchemeName)
747 {
748 return true;
749 }
750
751
752 // Case a shader based technique with the same scheme name already defined based
753 // on different source technique.
754 // This state might lead to conflicts during shader generation - we prevent it by returning false here.
755 else if ((*itTechEntry)->getDestinationTechniqueSchemeName() == dstTechniqueSchemeName)
756 {
757 return false;
758 }
759 }
760 }
761
762 // No technique created -> check if one can be created from the given source technique scheme.
763 Technique* srcTechnique = NULL;
764 srcTechnique = findSourceTechnique(materialName, trueGroupName, srcTechniqueSchemeName, overProgrammable);
765
766 // No appropriate source technique found.
767 if (srcTechnique == NULL)
768 {
769 return false;
770 }
771
772
773 // Create shader based technique from the given source technique.
774 SGMaterial* matEntry = NULL;
775
776 if (itMatEntry == mMaterialEntriesMap.end())
777 {
778 matEntry = OGRE_NEW SGMaterial(materialName, trueGroupName);
779 mMaterialEntriesMap.insert(SGMaterialMap::value_type(
780 MatGroupPair(materialName, trueGroupName), matEntry));
781 }
782 else
783 {
784 matEntry = itMatEntry->second;
785 }
786
787 // Create the new technique entry.
788 SGTechnique* techEntry = OGRE_NEW SGTechnique(matEntry, srcTechnique, dstTechniqueSchemeName);
789
790
791 // Add to material entry map.
792 matEntry->getTechniqueList().push_back(techEntry);
793
794 // Add to all technique map.
795 mTechniqueEntriesMap[techEntry] = techEntry;
796
797 // Add to scheme.
798 SGScheme* schemeEntry = createOrRetrieveScheme(dstTechniqueSchemeName).first;
799 schemeEntry->addTechniqueEntry(techEntry);
800
801 return true;
802 }
803
804 //-----------------------------------------------------------------------------
removeShaderBasedTechnique(const String & materialName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName)805 bool ShaderGenerator::removeShaderBasedTechnique(const String& materialName,
806 const String& srcTechniqueSchemeName,
807 const String& dstTechniqueSchemeName)
808 {
809 return removeShaderBasedTechnique(materialName,ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
810 srcTechniqueSchemeName,dstTechniqueSchemeName);
811 }
812 //-----------------------------------------------------------------------------
removeShaderBasedTechnique(const String & materialName,const String & groupName,const String & srcTechniqueSchemeName,const String & dstTechniqueSchemeName)813 bool ShaderGenerator::removeShaderBasedTechnique(const String& materialName,
814 const String& groupName,
815 const String& srcTechniqueSchemeName,
816 const String& dstTechniqueSchemeName)
817 {
818 OGRE_LOCK_AUTO_MUTEX;
819
820 // Make sure scheme exists.
821 SGSchemeIterator itScheme = mSchemeEntriesMap.find(dstTechniqueSchemeName);
822 SGScheme* schemeEntry = NULL;
823
824 if (itScheme == mSchemeEntriesMap.end())
825 return false;
826
827 schemeEntry = itScheme->second;
828
829
830
831 // Find the material entry.
832 SGMaterialIterator itMatEntry = findMaterialEntryIt(materialName,groupName);
833
834 // Case material not found.
835 if (itMatEntry == mMaterialEntriesMap.end())
836 return false;
837
838
839 SGTechniqueList& matTechniqueEntires = itMatEntry->second->getTechniqueList();
840 SGTechniqueIterator itTechEntry = matTechniqueEntires.begin();
841 SGTechnique* dstTechnique = NULL;
842
843 // Remove destination technique entry from material techniques list.
844 for (; itTechEntry != matTechniqueEntires.end(); ++itTechEntry)
845 {
846 if ((*itTechEntry)->getSourceTechnique()->getSchemeName() == srcTechniqueSchemeName &&
847 (*itTechEntry)->getDestinationTechniqueSchemeName() == dstTechniqueSchemeName)
848 {
849 dstTechnique = *itTechEntry;
850 matTechniqueEntires.erase(itTechEntry);
851 break;
852 }
853 }
854
855 // Technique not found.
856 if (dstTechnique == NULL)
857 return false;
858
859 schemeEntry->removeTechniqueEntry(dstTechnique);
860
861 SGTechniqueMapIterator itTechMap = mTechniqueEntriesMap.find(dstTechnique);
862
863 if (itTechMap != mTechniqueEntriesMap.end())
864 mTechniqueEntriesMap.erase(itTechMap);
865
866 OGRE_DELETE dstTechnique;
867
868 return true;
869 }
870
871 //-----------------------------------------------------------------------------
removeAllShaderBasedTechniques(const String & materialName,const String & groupName)872 bool ShaderGenerator::removeAllShaderBasedTechniques(const String& materialName, const String& groupName)
873 {
874 OGRE_LOCK_AUTO_MUTEX;
875
876 // Find the material entry.
877 SGMaterialIterator itMatEntry = findMaterialEntryIt(materialName, groupName);
878
879 // Case material not found.
880 if (itMatEntry == mMaterialEntriesMap.end())
881 return false;
882
883
884 SGTechniqueList& matTechniqueEntires = itMatEntry->second->getTechniqueList();
885
886 // Remove all technique entries from material techniques list.
887 while (matTechniqueEntires.empty() == false)
888 {
889 SGTechniqueIterator itTechEntry = matTechniqueEntires.begin();
890
891 removeShaderBasedTechnique(materialName, itMatEntry->first.second, (*itTechEntry)->getSourceTechnique()->getSchemeName(),
892 (*itTechEntry)->getDestinationTechniqueSchemeName());
893 }
894
895 OGRE_DELETE itMatEntry->second;
896 mMaterialEntriesMap.erase(itMatEntry);
897
898 return true;
899 }
900
901 //-----------------------------------------------------------------------------
cloneShaderBasedTechniques(const String & srcMaterialName,const String & srcGroupName,const String & dstMaterialName,const String & dstGroupName)902 bool ShaderGenerator::cloneShaderBasedTechniques(const String& srcMaterialName,
903 const String& srcGroupName,
904 const String& dstMaterialName,
905 const String& dstGroupName)
906 {
907 OGRE_LOCK_AUTO_MUTEX;
908
909 //
910 // Check that both source and destination material exist
911 //
912
913 // Make sure material exists.
914 MaterialPtr srcMat = MaterialManager::getSingleton().getByName(srcMaterialName, srcGroupName);
915 MaterialPtr dstMat = MaterialManager::getSingleton().getByName(dstMaterialName, dstGroupName);
916 if ((srcMat.isNull() == true) || (dstMat.isNull() == true) || (srcMat == dstMat))
917 return false;
918
919 // Update group name in case it is AUTODETECT_RESOURCE_GROUP_NAME
920 const String& trueSrcGroupName = srcMat->getGroup();
921 const String& trueDstGroupName = dstMat->getGroup();
922
923 // Case the requested material belongs to different group and it is not AUTODETECT_RESOURCE_GROUP_NAME.
924 if ((trueSrcGroupName != srcGroupName && srcGroupName != ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME) ||
925 (trueSrcGroupName != dstGroupName && dstGroupName != ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME))
926 {
927 return false;
928 }
929
930 SGMaterialIterator itSrcMatEntry = findMaterialEntryIt(srcMaterialName, trueSrcGroupName);
931
932 //remove any techniques in the destination material so the new techniques may be copied
933 removeAllShaderBasedTechniques(dstMaterialName, trueDstGroupName);
934
935 //
936 //remove any techniques from the destination material which have RTSS associated schemes from
937 //the source material. This code is performed in case the user performed a clone of a material
938 //which has already generated RTSS techniques in the source material.
939 //
940
941 //first gather the techniques to remove
942 set<unsigned short>::type schemesToRemove;
943 unsigned short techCount = srcMat->getNumTechniques();
944 for(unsigned short ti = 0 ; ti < techCount ; ++ti)
945 {
946 Technique* pSrcTech = srcMat->getTechnique(ti);
947 Pass* pSrcPass = pSrcTech->getNumPasses() > 0 ? pSrcTech->getPass(0) : NULL;
948 if (pSrcPass)
949 {
950 const Any& passUserData = pSrcPass->getUserObjectBindings().getUserAny(SGPass::UserKey);
951 if (!passUserData.isEmpty())
952 {
953 schemesToRemove.insert(pSrcTech->_getSchemeIndex());
954 }
955 }
956 }
957 //remove the techniques from the destination material
958 techCount = dstMat->getNumTechniques();
959 for(unsigned short ti = techCount - 1 ; ti != (unsigned short)-1 ; --ti)
960 {
961 Technique* pDstTech = dstMat->getTechnique(ti);
962 if (schemesToRemove.find(pDstTech->_getSchemeIndex()) != schemesToRemove.end())
963 {
964 dstMat->removeTechnique(ti);
965 }
966 }
967
968 //
969 // Clone the render states from source to destination
970 //
971
972 // Check if RTSS techniques exist in the source material
973 if (itSrcMatEntry != mMaterialEntriesMap.end())
974 {
975 const SGTechniqueList& techniqueEntires = itSrcMatEntry->second->getTechniqueList();
976 SGTechniqueConstIterator itTechEntry = techniqueEntires.begin();
977
978 //Go over all rtss techniques in the source material
979 for (; itTechEntry != techniqueEntires.end(); ++itTechEntry)
980 {
981 String srcFromTechniqueScheme = (*itTechEntry)->getSourceTechnique()->getSchemeName();
982 String srcToTechniqueScheme = (*itTechEntry)->getDestinationTechniqueSchemeName();
983
984 //for every technique in the source material create a shader based technique in the
985 //destination material
986 if (createShaderBasedTechnique(dstMaterialName, trueDstGroupName, srcFromTechniqueScheme, srcToTechniqueScheme))
987 {
988 //check for custom render states in the source material
989 unsigned short passCount = (*itTechEntry)->getSourceTechnique()->getNumPasses();
990 for(unsigned short pi = 0 ; pi < passCount ; ++pi)
991 {
992 if ((*itTechEntry)->hasRenderState(pi))
993 {
994 //copy the custom render state from the source material to the destination material
995 RenderState* srcRenderState = (*itTechEntry)->getRenderState(pi);
996 RenderState* dstRenderState = getRenderState(srcToTechniqueScheme, dstMaterialName, trueDstGroupName, pi);
997
998 const SubRenderStateList& srcSubRenderState =
999 srcRenderState->getTemplateSubRenderStateList();
1000
1001 SubRenderStateList::const_iterator itSubState = srcSubRenderState.begin(),
1002 itSubStateEnd = srcSubRenderState.end();
1003 for(;itSubState != itSubStateEnd ; ++itSubState)
1004 {
1005 SubRenderState* srcSubState = *itSubState;
1006 SubRenderState* dstSubState = createSubRenderState(srcSubState->getType());
1007 (*dstSubState) = (*srcSubState);
1008 dstRenderState->addTemplateSubRenderState(dstSubState);
1009 }
1010 }
1011 }
1012 }
1013 }
1014 }
1015
1016 return true;
1017 }
1018
1019 //-----------------------------------------------------------------------------
removeAllShaderBasedTechniques()1020 void ShaderGenerator::removeAllShaderBasedTechniques()
1021 {
1022 OGRE_LOCK_AUTO_MUTEX;
1023
1024 while (mMaterialEntriesMap.size() > 0)
1025 {
1026 SGMaterialIterator itMatEntry = mMaterialEntriesMap.begin();
1027
1028 removeAllShaderBasedTechniques(itMatEntry->first.first, itMatEntry->first.second);
1029 }
1030 }
1031
1032 //-----------------------------------------------------------------------------
findSourceTechnique(const String & materialName,const String & groupName,const String & srcTechniqueSchemeName,bool allowProgrammable)1033 Technique* ShaderGenerator::findSourceTechnique(const String& materialName,
1034 const String& groupName, const String& srcTechniqueSchemeName, bool allowProgrammable)
1035 {
1036 MaterialPtr mat = MaterialManager::getSingleton().getByName(materialName, groupName);
1037 Material::TechniqueIterator itMatTechniques = mat->getTechniqueIterator();
1038
1039
1040 // Find the source technique and make sure it is not programmable.
1041 while (itMatTechniques.hasMoreElements())
1042 {
1043 Technique* curTechnique = itMatTechniques.getNext();
1044
1045 if (curTechnique->getSchemeName() == srcTechniqueSchemeName && (allowProgrammable || !isProgrammable(curTechnique)))
1046 {
1047 return curTechnique;
1048 }
1049 }
1050
1051 return NULL;
1052 }
1053
1054 //-----------------------------------------------------------------------------
isProgrammable(Technique * tech) const1055 bool ShaderGenerator::isProgrammable(Technique* tech) const
1056 {
1057 if (tech != NULL)
1058 {
1059 for (unsigned short i=0; i < tech->getNumPasses(); ++i)
1060 {
1061 if (tech->getPass(i)->isProgrammable() == true)
1062 {
1063 return true;
1064 }
1065 }
1066 }
1067 return false;
1068 }
1069
1070
1071 //-----------------------------------------------------------------------------
notifyRenderSingleObject(Renderable * rend,const Pass * pass,const AutoParamDataSource * source,const LightList * pLightList,bool suppressRenderStateChanges)1072 void ShaderGenerator::notifyRenderSingleObject(Renderable* rend,
1073 const Pass* pass,
1074 const AutoParamDataSource* source,
1075 const LightList* pLightList, bool suppressRenderStateChanges)
1076 {
1077 if (mActiveViewportValid)
1078 {
1079 const Any& passUserData = pass->getUserObjectBindings().getUserAny(SGPass::UserKey);
1080
1081 if (passUserData.isEmpty())
1082 return;
1083
1084 OGRE_LOCK_AUTO_MUTEX;
1085
1086 SGPass* passEntry = any_cast<SGPass*>(passUserData);
1087
1088 passEntry->notifyRenderSingleObject(rend, source, pLightList, suppressRenderStateChanges);
1089
1090 }
1091 }
1092
1093
1094 //-----------------------------------------------------------------------------
preFindVisibleObjects(SceneManager * source,SceneManager::IlluminationRenderStage irs,Viewport * v)1095 void ShaderGenerator::preFindVisibleObjects(SceneManager* source,
1096 SceneManager::IlluminationRenderStage irs,
1097 Viewport* v)
1098 {
1099 OGRE_LOCK_AUTO_MUTEX;
1100
1101 const String& curMaterialScheme = v->getMaterialScheme();
1102
1103 mActiveSceneMgr = source;
1104 mActiveViewportValid = validateScheme(curMaterialScheme);
1105 }
1106
1107 //-----------------------------------------------------------------------------
invalidateScheme(const String & schemeName)1108 void ShaderGenerator::invalidateScheme(const String& schemeName)
1109 {
1110 OGRE_LOCK_AUTO_MUTEX;
1111
1112 SGSchemeIterator itScheme = mSchemeEntriesMap.find(schemeName);
1113
1114 if (itScheme != mSchemeEntriesMap.end())
1115 itScheme->second->invalidate();
1116
1117 }
1118
1119 //-----------------------------------------------------------------------------
validateScheme(const String & schemeName)1120 bool ShaderGenerator::validateScheme(const String& schemeName)
1121 {
1122 OGRE_LOCK_AUTO_MUTEX;
1123
1124 SGSchemeIterator itScheme = mSchemeEntriesMap.find(schemeName);
1125
1126 // No such scheme exists.
1127 if (itScheme == mSchemeEntriesMap.end())
1128 return false;
1129
1130 itScheme->second->validate();
1131
1132 return true;
1133 }
1134
1135 //-----------------------------------------------------------------------------
invalidateMaterial(const String & schemeName,const String & materialName,const String & groupName)1136 void ShaderGenerator::invalidateMaterial(const String& schemeName, const String& materialName, const String& groupName)
1137 {
1138 OGRE_LOCK_AUTO_MUTEX;
1139
1140 SGSchemeIterator itScheme = mSchemeEntriesMap.find(schemeName);
1141
1142 if (itScheme != mSchemeEntriesMap.end())
1143 itScheme->second->invalidate(materialName, groupName);
1144 }
1145
1146 //-----------------------------------------------------------------------------
validateMaterial(const String & schemeName,const String & materialName,const String & groupName)1147 bool ShaderGenerator::validateMaterial(const String& schemeName, const String& materialName, const String& groupName)
1148 {
1149 OGRE_LOCK_AUTO_MUTEX;
1150
1151 SGSchemeIterator itScheme = mSchemeEntriesMap.find(schemeName);
1152
1153 // No such scheme exists.
1154 if (itScheme == mSchemeEntriesMap.end())
1155 return false;
1156
1157 return itScheme->second->validate(materialName, groupName);
1158 }
1159
1160 //-----------------------------------------------------------------------------
getMaterialSerializerListener()1161 SGMaterialSerializerListener* ShaderGenerator::getMaterialSerializerListener()
1162 {
1163 if (mMaterialSerializerListener == NULL)
1164 mMaterialSerializerListener = OGRE_NEW SGMaterialSerializerListener;
1165
1166 return mMaterialSerializerListener;
1167 }
1168
1169 //-----------------------------------------------------------------------------
flushShaderCache()1170 void ShaderGenerator::flushShaderCache()
1171 {
1172 SGTechniqueMapIterator itTech = mTechniqueEntriesMap.begin();
1173 SGTechniqueMapIterator itTechEnd = mTechniqueEntriesMap.end();
1174
1175 // Release all programs.
1176 for (; itTech != itTechEnd; ++itTech)
1177 {
1178 itTech->second->releasePrograms();
1179 }
1180
1181 ProgramManager::getSingleton().flushGpuProgramsCache();
1182
1183 SGSchemeIterator itScheme = mSchemeEntriesMap.begin();
1184 SGSchemeIterator itSchemeEnd = mSchemeEntriesMap.end();
1185
1186 // Invalidate all schemes.
1187 for (; itScheme != itSchemeEnd; ++itScheme)
1188 {
1189 itScheme->second->invalidate();
1190 }
1191 }
1192
1193 //-----------------------------------------------------------------------------
addCustomScriptTranslator(const String & key,ScriptTranslator * translator)1194 bool ShaderGenerator::addCustomScriptTranslator(const String& key, ScriptTranslator* translator)
1195 {
1196 OGRE_LOCK_AUTO_MUTEX;
1197
1198 SGScriptTranslatorIterator itFind = mScriptTranslatorsMap.find(key);
1199
1200 if (itFind != mScriptTranslatorsMap.end())
1201 return false;
1202
1203 mScriptTranslatorsMap[key] = translator;
1204
1205 return true;
1206 }
1207
1208 //-----------------------------------------------------------------------------
removeCustomScriptTranslator(const String & key)1209 bool ShaderGenerator::removeCustomScriptTranslator(const String& key)
1210 {
1211 OGRE_LOCK_AUTO_MUTEX;
1212
1213 SGScriptTranslatorIterator itFind = mScriptTranslatorsMap.find(key);
1214
1215 if (itFind == mScriptTranslatorsMap.end())
1216 return false;
1217
1218 mScriptTranslatorsMap.erase(itFind);
1219
1220 return true;
1221 }
1222
1223 //-----------------------------------------------------------------------------
getNumTranslators() const1224 size_t ShaderGenerator::getNumTranslators() const
1225 {
1226 OGRE_LOCK_AUTO_MUTEX;
1227
1228 return mScriptTranslatorsMap.size();
1229 }
1230
1231 //-----------------------------------------------------------------------------
getTranslator(const AbstractNodePtr & node)1232 ScriptTranslator* ShaderGenerator::getTranslator(const AbstractNodePtr& node)
1233 {
1234 OGRE_LOCK_AUTO_MUTEX;
1235
1236 ScriptTranslator *translator = 0;
1237
1238 if(node->type == Ogre::ANT_OBJECT)
1239 {
1240 ObjectAbstractNode *obj = reinterpret_cast<ObjectAbstractNode*>(node.get());
1241 SGScriptTranslatorIterator itFind = mScriptTranslatorsMap.find(obj->cls);
1242
1243 if(itFind != mScriptTranslatorsMap.end())
1244 translator = itFind->second;
1245 }
1246
1247 return translator;
1248 }
1249
1250 //-----------------------------------------------------------------------------
serializePassAttributes(MaterialSerializer * ser,SGPass * passEntry)1251 void ShaderGenerator::serializePassAttributes(MaterialSerializer* ser, SGPass* passEntry)
1252 {
1253
1254 // Write section header and begin it.
1255 ser->writeAttribute(3, "rtshader_system");
1256 ser->beginSection(3);
1257
1258 // Grab the custom render state this pass uses.
1259 RenderState* customRenderState = passEntry->getCustomRenderState();
1260
1261 if (customRenderState != NULL)
1262 {
1263 // Write each of the sub-render states that composing the final render state.
1264 const SubRenderStateList& subRenderStates = customRenderState->getTemplateSubRenderStateList();
1265 SubRenderStateListConstIterator it = subRenderStates.begin();
1266 SubRenderStateListConstIterator itEnd = subRenderStates.end();
1267
1268 for (; it != itEnd; ++it)
1269 {
1270 SubRenderState* curSubRenderState = *it;
1271 SubRenderStateFactoryIterator itFactory = mSubRenderStateFactories.find(curSubRenderState->getType());
1272
1273 if (itFactory != mSubRenderStateFactories.end())
1274 {
1275 SubRenderStateFactory* curFactory = itFactory->second;
1276 curFactory->writeInstance(ser, curSubRenderState, passEntry->getSrcPass(), passEntry->getDstPass());
1277 }
1278 }
1279 }
1280
1281 // Write section end.
1282 ser->endSection(3);
1283 }
1284
1285
1286
1287 //-----------------------------------------------------------------------------
serializeTextureUnitStateAttributes(MaterialSerializer * ser,SGPass * passEntry,const TextureUnitState * srcTextureUnit)1288 void ShaderGenerator::serializeTextureUnitStateAttributes(MaterialSerializer* ser, SGPass* passEntry, const TextureUnitState* srcTextureUnit)
1289 {
1290
1291 // Write section header and begin it.
1292 ser->writeAttribute(4, "rtshader_system");
1293 ser->beginSection(4);
1294
1295 // Grab the custom render state this pass uses.
1296 RenderState* customRenderState = passEntry->getCustomRenderState();
1297
1298 if (customRenderState != NULL)
1299 {
1300 //retrive the destintion texture unit state
1301 TextureUnitState* dstTextureUnit = NULL;
1302 unsigned short texIndex = srcTextureUnit->getParent()->getTextureUnitStateIndex(srcTextureUnit);
1303 if (texIndex < passEntry->getDstPass()->getNumTextureUnitStates())
1304 {
1305 dstTextureUnit = passEntry->getDstPass()->getTextureUnitState(texIndex);
1306 }
1307
1308 // Write each of the sub-render states that composing the final render state.
1309 const SubRenderStateList& subRenderStates = customRenderState->getTemplateSubRenderStateList();
1310 SubRenderStateListConstIterator it = subRenderStates.begin();
1311 SubRenderStateListConstIterator itEnd = subRenderStates.end();
1312
1313 for (; it != itEnd; ++it)
1314 {
1315 SubRenderState* curSubRenderState = *it;
1316 SubRenderStateFactoryIterator itFactory = mSubRenderStateFactories.find(curSubRenderState->getType());
1317
1318 if (itFactory != mSubRenderStateFactories.end())
1319 {
1320 SubRenderStateFactory* curFactory = itFactory->second;
1321 curFactory->writeInstance(ser, curSubRenderState, srcTextureUnit, dstTextureUnit);
1322 }
1323 }
1324 }
1325
1326 // Write section end.
1327 ser->endSection(4);
1328 }
1329
1330 //-----------------------------------------------------------------------------
getVertexShaderCount() const1331 size_t ShaderGenerator::getVertexShaderCount() const
1332 {
1333 return mProgramManager->getVertexShaderCount();
1334 }
1335
1336 //-----------------------------------------------------------------------------
getFragmentShaderCount() const1337 size_t ShaderGenerator::getFragmentShaderCount() const
1338 {
1339 return mProgramManager->getFragmentShaderCount();
1340 }
1341
1342 //-----------------------------------------------------------------------------
setTargetLanguage(const String & shaderLanguage)1343 void ShaderGenerator::setTargetLanguage(const String& shaderLanguage)
1344 {
1345 // Make sure that the shader language is supported.
1346 if (HighLevelGpuProgramManager::getSingleton().isLanguageSupported(shaderLanguage) == false)
1347 {
1348 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
1349 "The language " + shaderLanguage + " is not supported !!",
1350 "ShaderGenerator::setShaderLanguage");
1351 }
1352
1353 // Case target language changed -> flush the shaders cache.
1354 if (mShaderLanguage != shaderLanguage)
1355 {
1356 mShaderLanguage = shaderLanguage;
1357 flushShaderCache();
1358 }
1359 }
1360
1361 //-----------------------------------------------------------------------------
setShaderCachePath(const String & cachePath)1362 void ShaderGenerator::setShaderCachePath( const String& cachePath )
1363 {
1364 String stdCachePath = cachePath;
1365
1366 // Standardise the cache path in case of none empty string.
1367 if (stdCachePath.empty() == false)
1368 stdCachePath = StringUtil::standardisePath(stdCachePath);
1369
1370 if (mShaderCachePath != stdCachePath)
1371 {
1372 // Remove previous cache path.
1373 if (mShaderCachePath.empty() == false)
1374 {
1375 ResourceGroupManager::getSingleton().removeResourceLocation(mShaderCachePath, GENERATED_SHADERS_GROUP_NAME);
1376 }
1377
1378 mShaderCachePath = stdCachePath;
1379
1380 // Case this is a valid file path -> add as resource location in order to make sure that
1381 // generated shaders could be loaded by the file system archive.
1382 if (mShaderCachePath.empty() == false)
1383 {
1384 // Make sure this is a valid writable path.
1385 String outTestFileName(mShaderCachePath + "ShaderGenerator.tst");
1386 std::ofstream outFile(outTestFileName.c_str());
1387
1388 if (!outFile)
1389 {
1390 OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE,
1391 "Could create output files in the given shader cache path '" + mShaderCachePath,
1392 "ShaderGenerator::setShaderCachePath");
1393 }
1394
1395 // Close and remove the test file.
1396 outFile.close();
1397 remove(outTestFileName.c_str());
1398
1399 ResourceGroupManager::getSingleton().addResourceLocation(mShaderCachePath, "FileSystem", GENERATED_SHADERS_GROUP_NAME);
1400 }
1401 }
1402 }
1403
1404 //-----------------------------------------------------------------------------
findMaterialEntryIt(const String & materialName,const String & groupName)1405 ShaderGenerator::SGMaterialIterator ShaderGenerator::findMaterialEntryIt(const String& materialName, const String& groupName)
1406 {
1407 SGMaterialIterator itMatEntry;
1408 //check if we have auto detect request
1409 if (groupName == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
1410 {
1411 //find the possible first entry
1412 itMatEntry = mMaterialEntriesMap.lower_bound(MatGroupPair(materialName,""));
1413 if ((itMatEntry != mMaterialEntriesMap.end()) &&
1414 (itMatEntry->first.first != materialName))
1415 {
1416 //no entry found
1417 itMatEntry = mMaterialEntriesMap.end();
1418 }
1419 }
1420 else
1421 {
1422 //find entry with group name specified
1423 itMatEntry = mMaterialEntriesMap.find(MatGroupPair(materialName,groupName));
1424 }
1425 return itMatEntry;
1426 }
1427
1428 //-----------------------------------------------------------------------------
findMaterialEntryIt(const String & materialName,const String & groupName) const1429 ShaderGenerator::SGMaterialConstIterator ShaderGenerator::findMaterialEntryIt(const String& materialName, const String& groupName) const
1430 {
1431 SGMaterialConstIterator itMatEntry;
1432 //check if we have auto detect request
1433 if (groupName == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
1434 {
1435 //find the possible first entry
1436 itMatEntry = mMaterialEntriesMap.lower_bound(MatGroupPair(materialName,""));
1437 if ((itMatEntry != mMaterialEntriesMap.end()) &&
1438 (itMatEntry->first.first != materialName))
1439 {
1440 //no entry found
1441 itMatEntry = mMaterialEntriesMap.end();
1442 }
1443 }
1444 else
1445 {
1446 //find entry with group name specified
1447 itMatEntry = mMaterialEntriesMap.find(MatGroupPair(materialName,groupName));
1448 }
1449 return itMatEntry;
1450 }
1451 //-----------------------------------------------------------------------------
getRTShaderSchemeCount() const1452 size_t ShaderGenerator::getRTShaderSchemeCount() const
1453 {
1454 OGRE_LOCK_AUTO_MUTEX;
1455 return mSchemeEntriesMap.size();
1456 }
1457 //-----------------------------------------------------------------------------
getRTShaderScheme(size_t index) const1458 const String& ShaderGenerator::getRTShaderScheme(size_t index) const
1459 {
1460 OGRE_LOCK_AUTO_MUTEX;
1461
1462 SGSchemeMap::const_iterator it = mSchemeEntriesMap.begin();
1463 while ((index != 0) && (it != mSchemeEntriesMap.end()))
1464 {
1465 --index;
1466 ++it;
1467 }
1468
1469 assert((it != mSchemeEntriesMap.end()) && "Index out of bounds");
1470 if (it != mSchemeEntriesMap.end())
1471 return it->first;
1472 else return cBlankString;
1473 }
1474
1475 //-----------------------------------------------------------------------------
1476
getIsFinalizing() const1477 bool ShaderGenerator::getIsFinalizing() const
1478 {
1479 return mIsFinalizing;
1480 }
1481
1482 //-----------------------------------------------------------------------------
SGPass(SGTechnique * parent,Pass * srcPass,Pass * dstPass)1483 ShaderGenerator::SGPass::SGPass(SGTechnique* parent, Pass* srcPass, Pass* dstPass)
1484 {
1485 mParent = parent;
1486 mSrcPass = srcPass;
1487 mDstPass = dstPass;
1488 mCustomRenderState = NULL;
1489 mTargetRenderState = NULL;
1490 mDstPass->getUserObjectBindings().setUserAny(SGPass::UserKey, Any(this));
1491 }
1492
1493 //-----------------------------------------------------------------------------
~SGPass()1494 ShaderGenerator::SGPass::~SGPass()
1495 {
1496 if (mTargetRenderState != NULL)
1497 {
1498 OGRE_DELETE mTargetRenderState;
1499 mTargetRenderState = NULL;
1500 }
1501 }
1502
1503 //-----------------------------------------------------------------------------
buildTargetRenderState()1504 void ShaderGenerator::SGPass::buildTargetRenderState()
1505 {
1506 const String& schemeName = mParent->getDestinationTechniqueSchemeName();
1507 const RenderState* renderStateGlobal = ShaderGenerator::getSingleton().getRenderState(schemeName);
1508
1509
1510 mTargetRenderState = OGRE_NEW TargetRenderState;
1511
1512 // Set light properties.
1513 int lightCount[3] = {0};
1514
1515 // Use light count definitions of the custom render state if exists.
1516 if (mCustomRenderState != NULL && mCustomRenderState->getLightCountAutoUpdate() == false)
1517 {
1518 mCustomRenderState->getLightCount(lightCount);
1519 }
1520
1521 // Use light count definitions of the global render state if exists.
1522 else if (renderStateGlobal != NULL)
1523 {
1524 renderStateGlobal->getLightCount(lightCount);
1525 }
1526
1527
1528 mTargetRenderState->setLightCount(lightCount);
1529
1530 #ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
1531 // Build the FFP state.
1532 FFPRenderStateBuilder::getSingleton().buildRenderState(this, mTargetRenderState);
1533 #endif
1534
1535
1536 // Link the target render state with the custom render state of this pass if exists.
1537 if (mCustomRenderState != NULL)
1538 {
1539 mTargetRenderState->link(*mCustomRenderState, mSrcPass, mDstPass);
1540 }
1541
1542 // Link the target render state with the scheme render state of the shader generator.
1543 if (renderStateGlobal != NULL)
1544 {
1545 mTargetRenderState->link(*renderStateGlobal, mSrcPass, mDstPass);
1546 }
1547 }
1548
1549 //-----------------------------------------------------------------------------
acquirePrograms()1550 void ShaderGenerator::SGPass::acquirePrograms()
1551 {
1552 ProgramManager::getSingleton().acquirePrograms(mDstPass, mTargetRenderState);
1553 }
1554
1555 //-----------------------------------------------------------------------------
releasePrograms()1556 void ShaderGenerator::SGPass::releasePrograms()
1557 {
1558 ProgramManager::getSingleton().releasePrograms(mDstPass, mTargetRenderState);
1559 }
1560
1561 //-----------------------------------------------------------------------------
notifyRenderSingleObject(Renderable * rend,const AutoParamDataSource * source,const LightList * pLightList,bool suppressRenderStateChanges)1562 void ShaderGenerator::SGPass::notifyRenderSingleObject(Renderable* rend, const AutoParamDataSource* source,
1563 const LightList* pLightList, bool suppressRenderStateChanges)
1564 {
1565 if (mTargetRenderState != NULL && suppressRenderStateChanges == false)
1566 mTargetRenderState->updateGpuProgramsParams(rend, mDstPass, source, pLightList);
1567 }
1568 //-----------------------------------------------------------------------------
getCustomFFPSubState(int subStateOrder)1569 SubRenderState* ShaderGenerator::SGPass::getCustomFFPSubState(int subStateOrder)
1570 {
1571 SubRenderState* customSubState = NULL;
1572
1573 // Try to override with custom render state of this pass.
1574 customSubState = getCustomFFPSubState(subStateOrder, mCustomRenderState);
1575
1576 // Case no custom sub state of this pass found, try to override with global scheme state.
1577 if (customSubState == NULL)
1578 {
1579 const String& schemeName = mParent->getDestinationTechniqueSchemeName();
1580 const RenderState* renderStateGlobal = ShaderGenerator::getSingleton().getRenderState(schemeName);
1581
1582 customSubState = getCustomFFPSubState(subStateOrder, renderStateGlobal);
1583 }
1584
1585 return customSubState;
1586 }
1587
1588 //-----------------------------------------------------------------------------
getCustomFFPSubState(int subStateOrder,const RenderState * renderState)1589 SubRenderState* ShaderGenerator::SGPass::getCustomFFPSubState(int subStateOrder, const RenderState* renderState)
1590 {
1591 if (renderState != NULL)
1592 {
1593 const SubRenderStateList& subRenderStateList = renderState->getTemplateSubRenderStateList();
1594
1595 for (SubRenderStateListConstIterator it=subRenderStateList.begin(); it != subRenderStateList.end(); ++it)
1596 {
1597 SubRenderState* curSubRenderState = *it;
1598
1599 if (curSubRenderState->getExecutionOrder() == subStateOrder)
1600 {
1601 SubRenderState* clone;
1602
1603 clone = ShaderGenerator::getSingleton().createSubRenderState(curSubRenderState->getType());
1604 *clone = *curSubRenderState;
1605
1606 return clone;
1607 }
1608 }
1609 }
1610
1611 return NULL;
1612 }
1613
1614 //-----------------------------------------------------------------------------
SGTechnique(SGMaterial * parent,Technique * srcTechnique,const String & dstTechniqueSchemeName)1615 ShaderGenerator::SGTechnique::SGTechnique(SGMaterial* parent, Technique* srcTechnique, const String& dstTechniqueSchemeName)
1616 {
1617 mParent = parent;
1618 mSrcTechnique = srcTechnique;
1619 mDstTechniqueSchemeName = dstTechniqueSchemeName;
1620 mDstTechnique = NULL;
1621 mBuildDstTechnique = true;
1622 }
1623
1624 //-----------------------------------------------------------------------------
createSGPasses()1625 void ShaderGenerator::SGTechnique::createSGPasses()
1626 {
1627 // Create pass entry for each pass.
1628 for (unsigned short i=0; i < mSrcTechnique->getNumPasses(); ++i)
1629 {
1630 Pass* srcPass = mSrcTechnique->getPass(i);
1631 Pass* dstPass = mDstTechnique->getPass(i);
1632
1633 SGPass* passEntry = OGRE_NEW SGPass(this, srcPass, dstPass);
1634
1635 if (i < mCustomRenderStates.size())
1636 passEntry->setCustomRenderState(mCustomRenderStates[i]);
1637 mPassEntries.push_back(passEntry);
1638 }
1639 }
1640
1641 //-----------------------------------------------------------------------------
~SGTechnique()1642 ShaderGenerator::SGTechnique::~SGTechnique()
1643 {
1644 const String& materialName = mParent->getMaterialName();
1645 const String& groupName = mParent->getGroupName();
1646
1647 if (MaterialManager::getSingleton().resourceExists(materialName))
1648 {
1649 MaterialPtr mat = MaterialManager::getSingleton().getByName(materialName, groupName);
1650
1651 // Remove the destination technique from parent material.
1652 for (unsigned int i=0; i < mat->getNumTechniques(); ++i)
1653 {
1654 if (mDstTechnique == mat->getTechnique(i))
1655 {
1656 // Unload the generated technique in order tor free referenced resources.
1657 mDstTechnique->_unload();
1658
1659 // Remove the generated technique in order to restore the material to its original state.
1660 mat->removeTechnique(i);
1661
1662 // touch when finalizing - will reload the textures - so no touch if finalizing
1663 if (ShaderGenerator::getSingleton().getIsFinalizing() == false)
1664 {
1665 // Make sure the material goes back to its original state.
1666 mat->touch();
1667 }
1668 break;
1669 }
1670 }
1671 }
1672
1673 // Release CPU/GPU programs that associated with this technique passes.
1674 for (SGPassIterator itPass = mPassEntries.begin(); itPass != mPassEntries.end(); ++itPass)
1675 {
1676 (*itPass)->releasePrograms();
1677 }
1678
1679 // Destroy the passes.
1680 destroySGPasses();
1681
1682 // Delete the custom render states of each pass if exist.
1683 for (unsigned int i=0; i < mCustomRenderStates.size(); ++i)
1684 {
1685 if (mCustomRenderStates[i] != NULL)
1686 {
1687 OGRE_DELETE mCustomRenderStates[i];
1688 mCustomRenderStates[i] = NULL;
1689 }
1690 }
1691 mCustomRenderStates.clear();
1692
1693 }
1694
1695 //-----------------------------------------------------------------------------
destroySGPasses()1696 void ShaderGenerator::SGTechnique::destroySGPasses()
1697 {
1698 for (SGPassIterator itPass = mPassEntries.begin(); itPass != mPassEntries.end(); ++itPass)
1699 {
1700 OGRE_DELETE (*itPass);
1701 }
1702 mPassEntries.clear();
1703 }
1704
1705 //-----------------------------------------------------------------------------
buildTargetRenderState()1706 void ShaderGenerator::SGTechnique::buildTargetRenderState()
1707 {
1708 // Remove existing destination technique and passes
1709 // in order to build it again from scratch.
1710 if (mDstTechnique != NULL)
1711 {
1712 Material* mat = mSrcTechnique->getParent();
1713
1714 for (unsigned short i=0; i < mat->getNumTechniques(); ++i)
1715 {
1716 if (mat->getTechnique(i) == mDstTechnique)
1717 {
1718 mat->removeTechnique(i);
1719 break;
1720 }
1721 }
1722 destroySGPasses();
1723 }
1724
1725 // Create the destination technique and passes.
1726 mDstTechnique = mSrcTechnique->getParent()->createTechnique();
1727 mDstTechnique->getUserObjectBindings().setUserAny(SGTechnique::UserKey, Any(this));
1728 *mDstTechnique = *mSrcTechnique;
1729 mDstTechnique->setSchemeName(mDstTechniqueSchemeName);
1730 createSGPasses();
1731
1732
1733 // Build render state for each pass.
1734 for (SGPassIterator itPass = mPassEntries.begin(); itPass != mPassEntries.end(); ++itPass)
1735 {
1736 (*itPass)->buildTargetRenderState();
1737 }
1738 }
1739
1740 //-----------------------------------------------------------------------------
acquirePrograms()1741 void ShaderGenerator::SGTechnique::acquirePrograms()
1742 {
1743 for (SGPassIterator itPass = mPassEntries.begin(); itPass != mPassEntries.end(); ++itPass)
1744 {
1745 (*itPass)->acquirePrograms();
1746 }
1747 }
1748
1749 //-----------------------------------------------------------------------------
releasePrograms()1750 void ShaderGenerator::SGTechnique::releasePrograms()
1751 {
1752 // Remove destination technique.
1753 if (mDstTechnique != NULL)
1754 {
1755 Material* mat = mSrcTechnique->getParent();
1756
1757 for (unsigned short i=0; i < mat->getNumTechniques(); ++i)
1758 {
1759 if (mat->getTechnique(i) == mDstTechnique)
1760 {
1761 mat->removeTechnique(i);
1762 break;
1763 }
1764 }
1765 mDstTechnique = NULL;
1766 }
1767
1768 // Release CPU/GPU programs that associated with this technique passes.
1769 for (SGPassIterator itPass = mPassEntries.begin(); itPass != mPassEntries.end(); ++itPass)
1770 {
1771 (*itPass)->releasePrograms();
1772 }
1773
1774 // Destroy the passes.
1775 destroySGPasses();
1776 }
1777
1778 //-----------------------------------------------------------------------------
getRenderState(unsigned short passIndex)1779 RenderState* ShaderGenerator::SGTechnique::getRenderState(unsigned short passIndex)
1780 {
1781 RenderState* renderState = NULL;
1782
1783 if (passIndex >= mCustomRenderStates.size())
1784 mCustomRenderStates.resize(passIndex + 1, NULL);
1785
1786 renderState = mCustomRenderStates[passIndex];
1787 if (renderState == NULL)
1788 {
1789 renderState = OGRE_NEW RenderState;
1790 mCustomRenderStates[passIndex] = renderState;
1791 }
1792
1793 return renderState;
1794 }
1795 //-----------------------------------------------------------------------------
hasRenderState(unsigned short passIndex)1796 bool ShaderGenerator::SGTechnique::hasRenderState(unsigned short passIndex)
1797 {
1798 return (passIndex < mCustomRenderStates.size()) && (mCustomRenderStates[passIndex] != NULL);
1799 }
1800
1801
1802 //-----------------------------------------------------------------------------
SGScheme(const String & schemeName)1803 ShaderGenerator::SGScheme::SGScheme(const String& schemeName)
1804 {
1805 mOutOfDate = true;
1806 mRenderState = NULL;
1807 mName = schemeName;
1808 mFogMode = FOG_NONE;
1809 }
1810
1811 //-----------------------------------------------------------------------------
~SGScheme()1812 ShaderGenerator::SGScheme::~SGScheme()
1813 {
1814 if (mRenderState != NULL)
1815 {
1816 OGRE_DELETE mRenderState;
1817 mRenderState = NULL;
1818 }
1819 }
1820
1821 //-----------------------------------------------------------------------------
getRenderState()1822 RenderState* ShaderGenerator::SGScheme::getRenderState()
1823 {
1824 if (mRenderState == NULL)
1825 mRenderState = OGRE_NEW RenderState;
1826
1827 return mRenderState;
1828 }
1829
1830 //-----------------------------------------------------------------------------
getRenderState(const String & materialName,const String & groupName,unsigned short passIndex)1831 RenderState* ShaderGenerator::SGScheme::getRenderState(const String& materialName, const String& groupName, unsigned short passIndex)
1832 {
1833 SGTechniqueIterator itTech;
1834
1835 // Find the desired technique.
1836 bool doAutoDetect = groupName == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
1837 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1838 {
1839 SGTechnique* curTechEntry = *itTech;
1840 Material* curMat = curTechEntry->getSourceTechnique()->getParent();
1841 if ((curMat->getName() == materialName) &&
1842 ((doAutoDetect == true) || (curMat->getGroup() == groupName)))
1843 {
1844 return curTechEntry->getRenderState(passIndex);
1845 }
1846 }
1847
1848 return NULL;
1849 }
1850
1851
1852 //-----------------------------------------------------------------------------
addTechniqueEntry(SGTechnique * techEntry)1853 void ShaderGenerator::SGScheme::addTechniqueEntry(SGTechnique* techEntry)
1854 {
1855 mTechniqueEntries.push_back(techEntry);
1856
1857 // Mark as out of data.
1858 mOutOfDate = true;
1859 }
1860
1861 //-----------------------------------------------------------------------------
removeTechniqueEntry(SGTechnique * techEntry)1862 void ShaderGenerator::SGScheme::removeTechniqueEntry(SGTechnique* techEntry)
1863 {
1864 SGTechniqueIterator itTech;
1865
1866 // Build render state for each technique.
1867 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1868 {
1869 SGTechnique* curTechEntry = *itTech;
1870
1871 if (curTechEntry == techEntry)
1872 {
1873 mTechniqueEntries.erase(itTech);
1874 break;
1875 }
1876 }
1877 }
1878
1879 //-----------------------------------------------------------------------------
validate()1880 void ShaderGenerator::SGScheme::validate()
1881 {
1882 // Synchronize with light settings.
1883 synchronizeWithLightSettings();
1884
1885 // Synchronize with fog settings.
1886 synchronizeWithFogSettings();
1887
1888 // The target scheme is up to date.
1889 if (mOutOfDate == false)
1890 return;
1891
1892 SGTechniqueIterator itTech;
1893
1894 // Build render state for each technique.
1895 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1896 {
1897 SGTechnique* curTechEntry = *itTech;
1898
1899 if (curTechEntry->getBuildDestinationTechnique())
1900 curTechEntry->buildTargetRenderState();
1901 }
1902
1903 // Acquire GPU programs for each technique.
1904 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1905 {
1906 SGTechnique* curTechEntry = *itTech;
1907
1908 if (curTechEntry->getBuildDestinationTechnique())
1909 curTechEntry->acquirePrograms();
1910 }
1911
1912 // Turn off the build destination technique flag.
1913 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1914 {
1915 SGTechnique* curTechEntry = *itTech;
1916
1917 curTechEntry->setBuildDestinationTechnique(false);
1918 }
1919
1920 // Mark this scheme as up to date.
1921 mOutOfDate = false;
1922 }
1923
1924 //-----------------------------------------------------------------------------
synchronizeWithLightSettings()1925 void ShaderGenerator::SGScheme::synchronizeWithLightSettings()
1926 {
1927 SceneManager* sceneManager = ShaderGenerator::getSingleton().getActiveSceneManager();
1928 RenderState* curRenderState = getRenderState();
1929
1930 if (sceneManager != NULL && curRenderState->getLightCountAutoUpdate())
1931 {
1932 const LightList& lightList = sceneManager->_getLightsAffectingFrustum();
1933
1934 int sceneLightCount[3] = {0};
1935 int currLightCount[3] = {0};
1936
1937 for (unsigned int i=0; i < lightList.size(); ++i)
1938 {
1939 sceneLightCount[lightList[i]->getType()]++;
1940 }
1941
1942 mRenderState->getLightCount(currLightCount);
1943
1944 // Case light state has been changed -> invalidate this scheme.
1945 if (currLightCount[0] != sceneLightCount[0] ||
1946 currLightCount[1] != sceneLightCount[1] ||
1947 currLightCount[2] != sceneLightCount[2])
1948 {
1949 curRenderState->setLightCount(sceneLightCount);
1950 invalidate();
1951 }
1952 }
1953 }
1954
1955 //-----------------------------------------------------------------------------
synchronizeWithFogSettings()1956 void ShaderGenerator::SGScheme::synchronizeWithFogSettings()
1957 {
1958 SceneManager* sceneManager = ShaderGenerator::getSingleton().getActiveSceneManager();
1959
1960 if (sceneManager != NULL && sceneManager->getFogMode() != mFogMode)
1961 {
1962 mFogMode = sceneManager->getFogMode();
1963 invalidate();
1964 }
1965 }
1966
1967 //-----------------------------------------------------------------------------
validate(const String & materialName,const String & groupName)1968 bool ShaderGenerator::SGScheme::validate(const String& materialName, const String& groupName)
1969 {
1970 // Synchronize with light settings.
1971 synchronizeWithLightSettings();
1972
1973 // Synchronize with fog settings.
1974 synchronizeWithFogSettings();
1975
1976
1977 SGTechniqueIterator itTech;
1978
1979 // Find the desired technique.
1980 bool doAutoDetect = groupName == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
1981 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
1982 {
1983 SGTechnique* curTechEntry = *itTech;
1984 const SGMaterial* curMat = curTechEntry->getParent();
1985 if ((curMat->getMaterialName() == materialName) &&
1986 ((doAutoDetect == true) || (curMat->getGroupName() == groupName)) &&
1987 (curTechEntry->getBuildDestinationTechnique()))
1988 {
1989 // Build render state for each technique.
1990 curTechEntry->buildTargetRenderState();
1991
1992 // Acquire the CPU/GPU programs.
1993 curTechEntry->acquirePrograms();
1994
1995 // Turn off the build destination technique flag.
1996 curTechEntry->setBuildDestinationTechnique(false);
1997
1998 return true;
1999 }
2000 }
2001
2002 return false;
2003 }
2004 //-----------------------------------------------------------------------------
invalidate(const String & materialName,const String & groupName)2005 void ShaderGenerator::SGScheme::invalidate(const String& materialName, const String& groupName)
2006 {
2007 SGTechniqueIterator itTech;
2008
2009 // Find the desired technique.
2010 bool doAutoDetect = groupName == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
2011 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
2012 {
2013 SGTechnique* curTechEntry = *itTech;
2014 const SGMaterial* curMaterial = curTechEntry->getParent();
2015 if ((curMaterial->getMaterialName() == materialName) &&
2016 ((doAutoDetect == true) || (curMaterial->getGroupName() == groupName)))
2017 {
2018 // Turn on the build destination technique flag.
2019 curTechEntry->setBuildDestinationTechnique(true);
2020 break;
2021 }
2022 }
2023
2024 mOutOfDate = true;
2025 }
2026
2027 //-----------------------------------------------------------------------------
invalidate()2028 void ShaderGenerator::SGScheme::invalidate()
2029 {
2030 SGTechniqueIterator itTech;
2031
2032 // Turn on the build destination technique flag of all techniques.
2033 for (itTech = mTechniqueEntries.begin(); itTech != mTechniqueEntries.end(); ++itTech)
2034 {
2035 SGTechnique* curTechEntry = *itTech;
2036
2037 curTechEntry->setBuildDestinationTechnique(true);
2038 }
2039
2040 mOutOfDate = true;
2041 }
2042
2043 }
2044 }
2045