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 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "OgreStableHeaders.h"
29 
30 #include "OgreTechnique.h"
31 #include "OgreMaterial.h"
32 #include "OgrePass.h"
33 #include "OgreRoot.h"
34 #include "OgreRenderSystem.h"
35 #include "OgreGpuProgramManager.h"
36 #include "OgreMaterialManager.h"
37 
38 
39 namespace Ogre {
40     //-----------------------------------------------------------------------------
Technique(Material * parent)41     Technique::Technique(Material* parent)
42         : mParent(parent), mIsSupported(false), mIlluminationPassesCompilationPhase(IPS_NOT_COMPILED), mLodIndex(0), mSchemeIndex(0)
43     {
44         // See above, defaults to unsupported until examined
45     }
46     //-----------------------------------------------------------------------------
Technique(Material * parent,const Technique & oth)47     Technique::Technique(Material* parent, const Technique& oth)
48         : mParent(parent), mLodIndex(0), mSchemeIndex(0)
49     {
50         // Copy using operator=
51         *this = oth;
52     }
53     //-----------------------------------------------------------------------------
~Technique()54     Technique::~Technique()
55     {
56         removeAllPasses();
57         clearIlluminationPasses();
58     }
59     //-----------------------------------------------------------------------------
isSupported(void) const60     bool Technique::isSupported(void) const
61     {
62         return mIsSupported;
63     }
64     //-----------------------------------------------------------------------------
calculateSize(void) const65     size_t Technique::calculateSize(void) const
66     {
67         size_t memSize = 0;
68 
69         // Tally up passes
70         Passes::const_iterator i, iend;
71         iend = mPasses.end();
72         for (i = mPasses.begin(); i != iend; ++i)
73         {
74             memSize += (*i)->calculateSize();
75         }
76         return memSize;
77     }
78     //-----------------------------------------------------------------------------
_compile(bool autoManageTextureUnits)79     String Technique::_compile(bool autoManageTextureUnits)
80     {
81 		StringUtil::StrStreamType errors;
82 
83 		mIsSupported = checkGPURules(errors);
84 		if (mIsSupported)
85 		{
86 			mIsSupported = checkHardwareSupport(autoManageTextureUnits, errors);
87 		}
88 
89         // Compile for categorised illumination on demand
90         clearIlluminationPasses();
91         mIlluminationPassesCompilationPhase = IPS_NOT_COMPILED;
92 
93 		return errors.str();
94 
95     }
96 	//---------------------------------------------------------------------
checkHardwareSupport(bool autoManageTextureUnits,StringUtil::StrStreamType & compileErrors)97 	bool Technique::checkHardwareSupport(bool autoManageTextureUnits, StringUtil::StrStreamType& compileErrors)
98 	{
99 		// Go through each pass, checking requirements
100 		Passes::iterator i;
101 		unsigned short passNum = 0;
102 		const RenderSystemCapabilities* caps =
103 			Root::getSingleton().getRenderSystem()->getCapabilities();
104 		unsigned short numTexUnits = caps->getNumTextureUnits();
105 		for (i = mPasses.begin(); i != mPasses.end(); ++i, ++passNum)
106 		{
107 			Pass* currPass = *i;
108 			// Adjust pass index
109 			currPass->_notifyIndex(passNum);
110 			// Check for advanced blending operation support
111 			if((currPass->getSceneBlendingOperation() != SBO_ADD || currPass->getSceneBlendingOperationAlpha() != SBO_ADD) &&
112 				!caps->hasCapability(RSC_ADVANCED_BLEND_OPERATIONS))
113 			{
114 				return false;
115 			}
116 			// Check texture unit requirements
117 			size_t numTexUnitsRequested = currPass->getNumTextureUnitStates();
118 			// Don't trust getNumTextureUnits for programmable
119 			if(!currPass->hasFragmentProgram())
120 			{
121 #if defined(OGRE_PRETEND_TEXTURE_UNITS) && OGRE_PRETEND_TEXTURE_UNITS > 0
122 				if (numTexUnits > OGRE_PRETEND_TEXTURE_UNITS)
123 					numTexUnits = OGRE_PRETEND_TEXTURE_UNITS;
124 #endif
125 				if (numTexUnitsRequested > numTexUnits)
126 				{
127 					if (!autoManageTextureUnits)
128 					{
129 						// The user disabled auto pass split
130 						compileErrors << "Pass " << passNum <<
131 							": Too many texture units for the current hardware and no splitting allowed."
132 							<< std::endl;
133 						return false;
134 					}
135 					else if (currPass->hasVertexProgram())
136 					{
137 						// Can't do this one, and can't split a programmable pass
138 						compileErrors << "Pass " << passNum <<
139 							": Too many texture units for the current hardware and "
140 							"cannot split programmable passes."
141 							<< std::endl;
142 						return false;
143 					}
144 				}
145 			}
146 			if (currPass->hasComputeProgram())
147 			{
148 				// Check fragment program version
149 				if (!currPass->getComputeProgram()->isSupported())
150 				{
151 					// Can't do this one
152 					compileErrors << "Pass " << passNum <<
153 						": Compute program " << currPass->getComputeProgram()->getName()
154 						<< " cannot be used - ";
155 					if (currPass->getComputeProgram()->hasCompileError())
156 						compileErrors << "compile error.";
157 					else
158 						compileErrors << "not supported.";
159 
160 					compileErrors << std::endl;
161 					return false;
162 				}
163 			}
164 			if (currPass->hasVertexProgram())
165 			{
166 				// Check vertex program version
167 				if (!currPass->getVertexProgram()->isSupported() )
168 				{
169 					// Can't do this one
170 					compileErrors << "Pass " << passNum <<
171 						": Vertex program " << currPass->getVertexProgram()->getName()
172 						<< " cannot be used - ";
173 					if (currPass->getVertexProgram()->hasCompileError())
174 						compileErrors << "compile error.";
175 					else
176 						compileErrors << "not supported.";
177 
178 					compileErrors << std::endl;
179 					return false;
180 				}
181 			}
182 			if (currPass->hasTesselationHullProgram())
183 			{
184 				// Check tesselation control program version
185 				if (!currPass->getTesselationHullProgram()->isSupported() )
186 				{
187 					// Can't do this one
188 					compileErrors << "Pass " << passNum <<
189 						": Tesselation Hull program " << currPass->getTesselationHullProgram()->getName()
190 						<< " cannot be used - ";
191 					if (currPass->getTesselationHullProgram()->hasCompileError())
192 						compileErrors << "compile error.";
193 					else
194 						compileErrors << "not supported.";
195 
196 					compileErrors << std::endl;
197 					return false;
198 				}
199 			}
200 			if (currPass->hasTesselationDomainProgram())
201 			{
202 				// Check tesselation control program version
203 				if (!currPass->getTesselationDomainProgram()->isSupported() )
204 				{
205 					// Can't do this one
206 					compileErrors << "Pass " << passNum <<
207 						": Tesselation Domain program " << currPass->getTesselationDomainProgram()->getName()
208 						<< " cannot be used - ";
209 					if (currPass->getTesselationDomainProgram()->hasCompileError())
210 						compileErrors << "compile error.";
211 					else
212 						compileErrors << "not supported.";
213 
214 					compileErrors << std::endl;
215 					return false;
216 				}
217 			}
218 			if (currPass->hasGeometryProgram())
219 			{
220 				// Check geometry program version
221 				if (!currPass->getGeometryProgram()->isSupported() )
222 				{
223 					// Can't do this one
224 					compileErrors << "Pass " << passNum <<
225 						": Geometry program " << currPass->getGeometryProgram()->getName()
226 						<< " cannot be used - ";
227 					if (currPass->getGeometryProgram()->hasCompileError())
228 						compileErrors << "compile error.";
229 					else
230 						compileErrors << "not supported.";
231 
232 					compileErrors << std::endl;
233 					return false;
234 				}
235 			}
236 			if (currPass->hasFragmentProgram())
237 			{
238 				// Check fragment program version
239 				if (!currPass->getFragmentProgram()->isSupported())
240 				{
241 					// Can't do this one
242 					compileErrors << "Pass " << passNum <<
243 						": Fragment program " << currPass->getFragmentProgram()->getName()
244 						<< " cannot be used - ";
245 					if (currPass->getFragmentProgram()->hasCompileError())
246 						compileErrors << "compile error.";
247 					else
248 						compileErrors << "not supported.";
249 
250 					compileErrors << std::endl;
251 					return false;
252 				}
253 			}
254 			else
255 			{
256 				// Check a few fixed-function options in texture layers
257 				Pass::TextureUnitStateIterator texi = currPass->getTextureUnitStateIterator();
258 				size_t texUnit = 0;
259 				while (texi.hasMoreElements())
260 				{
261 					TextureUnitState* tex = texi.getNext();
262 					// Any Cube textures? NB we make the assumption that any
263 					// card capable of running fragment programs can support
264 					// cubic textures, which has to be true, surely?
265 					if (tex->is3D() && !caps->hasCapability(RSC_CUBEMAPPING))
266 					{
267 						// Fail
268 						compileErrors << "Pass " << passNum <<
269 							" Tex " << texUnit <<
270 							": Cube maps not supported by current environment."
271 							<< std::endl;
272 						return false;
273 					}
274 					// Any 3D textures? NB we make the assumption that any
275 					// card capable of running fragment programs can support
276 					// 3D textures, which has to be true, surely?
277 					if (((tex->getTextureType() == TEX_TYPE_3D) || (tex->getTextureType() == TEX_TYPE_2D_ARRAY)) &&
278                          !caps->hasCapability(RSC_TEXTURE_3D))
279 					{
280 						// Fail
281 						compileErrors << "Pass " << passNum <<
282 							" Tex " << texUnit <<
283 							": Volume textures not supported by current environment."
284 							<< std::endl;
285 						return false;
286 					}
287 					// Any Dot3 blending?
288 					if (tex->getColourBlendMode().operation == LBX_DOTPRODUCT &&
289 						!caps->hasCapability(RSC_DOT3))
290 					{
291 						// Fail
292 						compileErrors << "Pass " << passNum <<
293 							" Tex " << texUnit <<
294 							": DOT3 blending not supported by current environment."
295 							<< std::endl;
296 						return false;
297 					}
298 					++texUnit;
299 				}
300 
301 				// We're ok on operations, now we need to check # texture units
302 				if (!currPass->hasFragmentProgram())
303 				{
304 					// Keep splitting this pass so long as units requested > gpu units
305 					while (numTexUnitsRequested > numTexUnits)
306 					{
307 						// chop this pass into many passes
308 						currPass = currPass->_split(numTexUnits);
309 						numTexUnitsRequested = currPass->getNumTextureUnitStates();
310 						// Advance pass number
311 						++passNum;
312 						// Reset iterator
313 						i = mPasses.begin() + passNum;
314 						// Move the new pass to the right place (will have been created
315 						// at the end, may be other passes in between)
316 						assert(mPasses.back() == currPass);
317 						std::copy_backward(i, (mPasses.end()-1), mPasses.end());
318 						*i = currPass;
319 						// Adjust pass index
320 						currPass->_notifyIndex(passNum);
321 					}
322 				}
323 			}
324 
325 		}
326 		// If we got this far, we're ok
327 		return true;
328 	}
329 	//---------------------------------------------------------------------
checkGPURules(StringUtil::StrStreamType & errors)330 	bool Technique::checkGPURules(StringUtil::StrStreamType& errors)
331 	{
332 		const RenderSystemCapabilities* caps =
333 			Root::getSingleton().getRenderSystem()->getCapabilities();
334 
335 		StringUtil::StrStreamType includeRules;
336 		bool includeRulesPresent = false;
337 		bool includeRuleMatched = false;
338 
339 		// Check vendors first
340 		for (GPUVendorRuleList::const_iterator i = mGPUVendorRules.begin();
341 			i != mGPUVendorRules.end(); ++i)
342 		{
343 			if (i->includeOrExclude == INCLUDE)
344 			{
345 				includeRulesPresent = true;
346 				includeRules << caps->vendorToString(i->vendor) << " ";
347 				if (i->vendor == caps->getVendor())
348 					includeRuleMatched = true;
349 			}
350 			else // EXCLUDE
351 			{
352 				if (i->vendor == caps->getVendor())
353 				{
354 					errors << "Excluded GPU vendor: " << caps->vendorToString(i->vendor)
355 						<< std::endl;
356 					return false;
357 				}
358 
359 			}
360 		}
361 
362 		if (includeRulesPresent && !includeRuleMatched)
363 		{
364 			errors << "Failed to match GPU vendor: " << includeRules.str( )
365 				<< std::endl;
366 			return false;
367 		}
368 
369 		// now check device names
370 		includeRules.str(StringUtil::BLANK);
371 		includeRulesPresent = false;
372 		includeRuleMatched = false;
373 
374 		for (GPUDeviceNameRuleList::const_iterator i = mGPUDeviceNameRules.begin();
375 			i != mGPUDeviceNameRules.end(); ++i)
376 		{
377 			if (i->includeOrExclude == INCLUDE)
378 			{
379 				includeRulesPresent = true;
380 				includeRules << i->devicePattern << " ";
381 				if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive))
382 					includeRuleMatched = true;
383 			}
384 			else // EXCLUDE
385 			{
386 				if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive))
387 				{
388 					errors << "Excluded GPU device: " << i->devicePattern
389 						<< std::endl;
390 					return false;
391 				}
392 
393 			}
394 		}
395 
396 		if (includeRulesPresent && !includeRuleMatched)
397 		{
398 			errors << "Failed to match GPU device: " << includeRules.str( )
399 				<< std::endl;
400 			return false;
401 		}
402 
403 		// passed
404 		return true;
405 	}
406     //-----------------------------------------------------------------------------
createPass(void)407     Pass* Technique::createPass(void)
408     {
409 		Pass* newPass = OGRE_NEW Pass(this, static_cast<unsigned short>(mPasses.size()));
410 		mPasses.push_back(newPass);
411 		return newPass;
412     }
413     //-----------------------------------------------------------------------------
getPass(unsigned short index)414     Pass* Technique::getPass(unsigned short index)
415     {
416 		assert(index < mPasses.size() && "Index out of bounds");
417 		return mPasses[index];
418     }
419     //-----------------------------------------------------------------------------
getPass(const String & name)420     Pass* Technique::getPass(const String& name)
421     {
422         Passes::iterator i    = mPasses.begin();
423         Passes::iterator iend = mPasses.end();
424         Pass* foundPass = 0;
425 
426         // iterate through techniques to find a match
427         while (i != iend)
428         {
429             if ( (*i)->getName() == name )
430             {
431                 foundPass = (*i);
432                 break;
433             }
434             ++i;
435         }
436 
437         return foundPass;
438     }
439     //-----------------------------------------------------------------------------
getNumPasses(void) const440     unsigned short Technique::getNumPasses(void) const
441     {
442 		return static_cast<unsigned short>(mPasses.size());
443     }
444     //-----------------------------------------------------------------------------
removePass(unsigned short index)445     void Technique::removePass(unsigned short index)
446     {
447 		assert(index < mPasses.size() && "Index out of bounds");
448 		Passes::iterator i = mPasses.begin() + index;
449 		(*i)->queueForDeletion();
450 		i = mPasses.erase(i);
451 		// Adjust passes index
452 		for (; i != mPasses.end(); ++i, ++index)
453 		{
454 			(*i)->_notifyIndex(index);
455 		}
456     }
457     //-----------------------------------------------------------------------------
removeAllPasses(void)458     void Technique::removeAllPasses(void)
459     {
460         Passes::iterator i, iend;
461         iend = mPasses.end();
462         for (i = mPasses.begin(); i != iend; ++i)
463         {
464             (*i)->queueForDeletion();
465         }
466         mPasses.clear();
467     }
468 
469     //-----------------------------------------------------------------------------
movePass(const unsigned short sourceIndex,const unsigned short destinationIndex)470     bool Technique::movePass(const unsigned short sourceIndex, const unsigned short destinationIndex)
471     {
472         bool moveSuccessful = false;
473 
474         // don't move the pass if source == destination
475         if (sourceIndex == destinationIndex) return true;
476 
477         if( (sourceIndex < mPasses.size()) && (destinationIndex < mPasses.size()))
478         {
479             Passes::iterator i = mPasses.begin() + sourceIndex;
480             //Passes::iterator DestinationIterator = mPasses.begin() + destinationIndex;
481 
482             Pass* pass = (*i);
483             mPasses.erase(i);
484 
485             i = mPasses.begin() + destinationIndex;
486 
487             mPasses.insert(i, pass);
488 
489 			// Adjust passes index
490 			unsigned short beginIndex, endIndex;
491 			if (destinationIndex > sourceIndex)
492 			{
493 				beginIndex = sourceIndex;
494 				endIndex = destinationIndex;
495 			}
496 			else
497 			{
498 				beginIndex = destinationIndex;
499 				endIndex = sourceIndex;
500 			}
501 			for (unsigned short index = beginIndex; index <= endIndex; ++index)
502 			{
503 				mPasses[index]->_notifyIndex(index);
504 			}
505             moveSuccessful = true;
506         }
507 
508         return moveSuccessful;
509     }
510 
511     //-----------------------------------------------------------------------------
getPassIterator(void)512     const Technique::PassIterator Technique::getPassIterator(void)
513     {
514 		return PassIterator(mPasses.begin(), mPasses.end());
515     }
516     //-----------------------------------------------------------------------------
operator =(const Technique & rhs)517     Technique& Technique::operator=(const Technique& rhs)
518     {
519         mName = rhs.mName;
520 		this->mIsSupported = rhs.mIsSupported;
521         this->mLodIndex = rhs.mLodIndex;
522 		this->mSchemeIndex = rhs.mSchemeIndex;
523 		this->mShadowCasterMaterial = rhs.mShadowCasterMaterial;
524 		this->mShadowCasterMaterialName = rhs.mShadowCasterMaterialName;
525 		this->mShadowReceiverMaterial = rhs.mShadowReceiverMaterial;
526 		this->mShadowReceiverMaterialName = rhs.mShadowReceiverMaterialName;
527 		this->mGPUVendorRules = rhs.mGPUVendorRules;
528 		this->mGPUDeviceNameRules = rhs.mGPUDeviceNameRules;
529 
530 		// copy passes
531 		removeAllPasses();
532 		Passes::const_iterator i, iend;
533 		iend = rhs.mPasses.end();
534 		for (i = rhs.mPasses.begin(); i != iend; ++i)
535 		{
536 			Pass* p = OGRE_NEW Pass(this, (*i)->getIndex(), *(*i));
537 			mPasses.push_back(p);
538 		}
539         // Compile for categorised illumination on demand
540         clearIlluminationPasses();
541         mIlluminationPassesCompilationPhase = IPS_NOT_COMPILED;
542 		return *this;
543     }
544     //-----------------------------------------------------------------------------
isTransparent(void) const545     bool Technique::isTransparent(void) const
546     {
547         if (mPasses.empty())
548         {
549             return false;
550         }
551         else
552         {
553             // Base decision on the transparency of the first pass
554             return mPasses[0]->isTransparent();
555         }
556     }
557     //-----------------------------------------------------------------------------
isTransparentSortingEnabled(void) const558     bool Technique::isTransparentSortingEnabled(void) const
559     {
560         if (mPasses.empty())
561         {
562             return true;
563         }
564         else
565         {
566             // Base decision on the transparency of the first pass
567             return mPasses[0]->getTransparentSortingEnabled();
568         }
569     }
570     //-----------------------------------------------------------------------------
isTransparentSortingForced(void) const571     bool Technique::isTransparentSortingForced(void) const
572     {
573         if (mPasses.empty())
574         {
575             return false;
576         }
577         else
578         {
579             // Base decision on the first pass
580             return mPasses[0]->getTransparentSortingForced();
581         }
582     }
583     //-----------------------------------------------------------------------------
isDepthWriteEnabled(void) const584     bool Technique::isDepthWriteEnabled(void) const
585     {
586         if (mPasses.empty())
587         {
588             return false;
589         }
590         else
591         {
592             // Base decision on the depth settings of the first pass
593             return mPasses[0]->getDepthWriteEnabled();
594         }
595     }
596     //-----------------------------------------------------------------------------
isDepthCheckEnabled(void) const597     bool Technique::isDepthCheckEnabled(void) const
598     {
599         if (mPasses.empty())
600         {
601             return false;
602         }
603         else
604         {
605             // Base decision on the depth settings of the first pass
606             return mPasses[0]->getDepthCheckEnabled();
607         }
608     }
609     //-----------------------------------------------------------------------------
hasColourWriteDisabled(void) const610     bool Technique::hasColourWriteDisabled(void) const
611     {
612         if (mPasses.empty())
613         {
614             return true;
615         }
616         else
617         {
618             // Base decision on the colour write settings of the first pass
619             return !mPasses[0]->getColourWriteEnabled();
620         }
621     }
622     //-----------------------------------------------------------------------------
_prepare(void)623     void Technique::_prepare(void)
624     {
625 		assert (mIsSupported && "This technique is not supported");
626 		// Load each pass
627 		Passes::iterator i, iend;
628 		iend = mPasses.end();
629 		for (i = mPasses.begin(); i != iend; ++i)
630 		{
631 			(*i)->_prepare();
632 		}
633 
634 		IlluminationPassList::iterator il, ilend;
635 		ilend = mIlluminationPasses.end();
636 		for (il = mIlluminationPasses.begin(); il != ilend; ++il)
637 		{
638 			if((*il)->pass != (*il)->originalPass)
639 			    (*il)->pass->_prepare();
640 		}
641     }
642     //-----------------------------------------------------------------------------
_unprepare(void)643     void Technique::_unprepare(void)
644     {
645 		// Unload each pass
646 		Passes::iterator i, iend;
647 		iend = mPasses.end();
648 		for (i = mPasses.begin(); i != iend; ++i)
649 		{
650 			(*i)->_unprepare();
651 		}
652     }
653     //-----------------------------------------------------------------------------
_load(void)654     void Technique::_load(void)
655     {
656 		assert (mIsSupported && "This technique is not supported");
657 		// Load each pass
658 		Passes::iterator i, iend;
659 		iend = mPasses.end();
660 		for (i = mPasses.begin(); i != iend; ++i)
661 		{
662 			(*i)->_load();
663 		}
664 
665 		IlluminationPassList::iterator il, ilend;
666 		ilend = mIlluminationPasses.end();
667 		for (il = mIlluminationPasses.begin(); il != ilend; ++il)
668 		{
669 			if((*il)->pass != (*il)->originalPass)
670 			    (*il)->pass->_load();
671 		}
672 
673 		if (!mShadowCasterMaterial.isNull())
674 		{
675 			mShadowCasterMaterial->load();
676 		}
677 		else if (!mShadowCasterMaterialName.empty())
678 		{
679 			// in case we could not get material as it wasn't yet parsed/existent at that time.
680 			mShadowCasterMaterial = MaterialManager::getSingleton().getByName(mShadowCasterMaterialName);
681             if (!mShadowCasterMaterial.isNull())
682 			    mShadowCasterMaterial->load();
683 		}
684 		if (!mShadowReceiverMaterial.isNull())
685 		{
686 			mShadowReceiverMaterial->load();
687 		}
688 		else if (!mShadowReceiverMaterialName.empty())
689 		{
690 			// in case we could not get material as it wasn't yet parsed/existent at that time.
691 			mShadowReceiverMaterial = MaterialManager::getSingleton().getByName(mShadowReceiverMaterialName);
692             if (!mShadowReceiverMaterial.isNull())
693 			    mShadowReceiverMaterial->load();
694 		}
695     }
696     //-----------------------------------------------------------------------------
_unload(void)697     void Technique::_unload(void)
698     {
699 		// Unload each pass
700 		Passes::iterator i, iend;
701 		iend = mPasses.end();
702 		for (i = mPasses.begin(); i != iend; ++i)
703 		{
704 			(*i)->_unload();
705 		}
706     }
707     //-----------------------------------------------------------------------------
isLoaded(void) const708     bool Technique::isLoaded(void) const
709     {
710         // Only supported technique will be loaded
711         return mParent->isLoaded() && mIsSupported;
712     }
713     //-----------------------------------------------------------------------
setPointSize(Real ps)714     void Technique::setPointSize(Real ps)
715     {
716         Passes::iterator i, iend;
717         iend = mPasses.end();
718         for (i = mPasses.begin(); i != iend; ++i)
719         {
720             (*i)->setPointSize(ps);
721         }
722 
723     }
724     //-----------------------------------------------------------------------
setAmbient(Real red,Real green,Real blue)725     void Technique::setAmbient(Real red, Real green, Real blue)
726     {
727 		setAmbient(ColourValue(red, green, blue));
728 
729 
730     }
731     //-----------------------------------------------------------------------
setAmbient(const ColourValue & ambient)732     void Technique::setAmbient(const ColourValue& ambient)
733     {
734 		Passes::iterator i, iend;
735 		iend = mPasses.end();
736 		for (i = mPasses.begin(); i != iend; ++i)
737 		{
738 			(*i)->setAmbient(ambient);
739 		}
740     }
741     //-----------------------------------------------------------------------
setDiffuse(Real red,Real green,Real blue,Real alpha)742     void Technique::setDiffuse(Real red, Real green, Real blue, Real alpha)
743     {
744         Passes::iterator i, iend;
745         iend = mPasses.end();
746         for (i = mPasses.begin(); i != iend; ++i)
747         {
748             (*i)->setDiffuse(red, green, blue, alpha);
749         }
750     }
751     //-----------------------------------------------------------------------
setDiffuse(const ColourValue & diffuse)752     void Technique::setDiffuse(const ColourValue& diffuse)
753     {
754         setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
755     }
756     //-----------------------------------------------------------------------
setSpecular(Real red,Real green,Real blue,Real alpha)757     void Technique::setSpecular(Real red, Real green, Real blue, Real alpha)
758     {
759         Passes::iterator i, iend;
760         iend = mPasses.end();
761         for (i = mPasses.begin(); i != iend; ++i)
762         {
763             (*i)->setSpecular(red, green, blue, alpha);
764         }
765     }
766     //-----------------------------------------------------------------------
setSpecular(const ColourValue & specular)767     void Technique::setSpecular(const ColourValue& specular)
768     {
769         setSpecular(specular.r, specular.g, specular.b, specular.a);
770     }
771     //-----------------------------------------------------------------------
setShininess(Real val)772     void Technique::setShininess(Real val)
773     {
774         Passes::iterator i, iend;
775         iend = mPasses.end();
776         for (i = mPasses.begin(); i != iend; ++i)
777         {
778             (*i)->setShininess(val);
779         }
780     }
781     //-----------------------------------------------------------------------
setSelfIllumination(Real red,Real green,Real blue)782     void Technique::setSelfIllumination(Real red, Real green, Real blue)
783     {
784         setSelfIllumination(ColourValue(red, green, blue));
785     }
786     //-----------------------------------------------------------------------
setSelfIllumination(const ColourValue & selfIllum)787     void Technique::setSelfIllumination(const ColourValue& selfIllum)
788     {
789 		Passes::iterator i, iend;
790 		iend = mPasses.end();
791 		for (i = mPasses.begin(); i != iend; ++i)
792 		{
793 			(*i)->setSelfIllumination(selfIllum);
794 		}
795     }
796     //-----------------------------------------------------------------------
setDepthCheckEnabled(bool enabled)797     void Technique::setDepthCheckEnabled(bool enabled)
798     {
799         Passes::iterator i, iend;
800         iend = mPasses.end();
801         for (i = mPasses.begin(); i != iend; ++i)
802         {
803             (*i)->setDepthCheckEnabled(enabled);
804         }
805     }
806     //-----------------------------------------------------------------------
setDepthWriteEnabled(bool enabled)807     void Technique::setDepthWriteEnabled(bool enabled)
808     {
809         Passes::iterator i, iend;
810         iend = mPasses.end();
811         for (i = mPasses.begin(); i != iend; ++i)
812         {
813             (*i)->setDepthWriteEnabled(enabled);
814         }
815     }
816     //-----------------------------------------------------------------------
setDepthFunction(CompareFunction func)817     void Technique::setDepthFunction( CompareFunction func )
818     {
819         Passes::iterator i, iend;
820         iend = mPasses.end();
821         for (i = mPasses.begin(); i != iend; ++i)
822         {
823             (*i)->setDepthFunction(func);
824         }
825     }
826     //-----------------------------------------------------------------------
setColourWriteEnabled(bool enabled)827 	void Technique::setColourWriteEnabled(bool enabled)
828     {
829         Passes::iterator i, iend;
830         iend = mPasses.end();
831         for (i = mPasses.begin(); i != iend; ++i)
832         {
833             (*i)->setColourWriteEnabled(enabled);
834         }
835     }
836     //-----------------------------------------------------------------------
setCullingMode(CullingMode mode)837     void Technique::setCullingMode( CullingMode mode )
838     {
839         Passes::iterator i, iend;
840         iend = mPasses.end();
841         for (i = mPasses.begin(); i != iend; ++i)
842         {
843             (*i)->setCullingMode(mode);
844         }
845     }
846     //-----------------------------------------------------------------------
setManualCullingMode(ManualCullingMode mode)847     void Technique::setManualCullingMode( ManualCullingMode mode )
848     {
849         Passes::iterator i, iend;
850         iend = mPasses.end();
851         for (i = mPasses.begin(); i != iend; ++i)
852         {
853             (*i)->setManualCullingMode(mode);
854         }
855     }
856     //-----------------------------------------------------------------------
setLightingEnabled(bool enabled)857     void Technique::setLightingEnabled(bool enabled)
858     {
859         Passes::iterator i, iend;
860         iend = mPasses.end();
861         for (i = mPasses.begin(); i != iend; ++i)
862         {
863             (*i)->setLightingEnabled(enabled);
864         }
865     }
866     //-----------------------------------------------------------------------
setShadingMode(ShadeOptions mode)867     void Technique::setShadingMode( ShadeOptions mode )
868     {
869         Passes::iterator i, iend;
870         iend = mPasses.end();
871         for (i = mPasses.begin(); i != iend; ++i)
872         {
873             (*i)->setShadingMode(mode);
874         }
875     }
876     //-----------------------------------------------------------------------
setFog(bool overrideScene,FogMode mode,const ColourValue & colour,Real expDensity,Real linearStart,Real linearEnd)877     void Technique::setFog(bool overrideScene, FogMode mode, const ColourValue& colour,
878         Real expDensity, Real linearStart, Real linearEnd)
879     {
880         Passes::iterator i, iend;
881         iend = mPasses.end();
882         for (i = mPasses.begin(); i != iend; ++i)
883         {
884             (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd);
885         }
886     }
887     //-----------------------------------------------------------------------
setDepthBias(float constantBias,float slopeScaleBias)888     void Technique::setDepthBias(float constantBias, float slopeScaleBias)
889     {
890         Passes::iterator i, iend;
891         iend = mPasses.end();
892         for (i = mPasses.begin(); i != iend; ++i)
893         {
894             (*i)->setDepthBias(constantBias, slopeScaleBias);
895         }
896     }
897     //-----------------------------------------------------------------------
setTextureFiltering(TextureFilterOptions filterType)898     void Technique::setTextureFiltering(TextureFilterOptions filterType)
899     {
900         Passes::iterator i, iend;
901         iend = mPasses.end();
902         for (i = mPasses.begin(); i != iend; ++i)
903         {
904             (*i)->setTextureFiltering(filterType);
905         }
906     }
907     // --------------------------------------------------------------------
setTextureAnisotropy(unsigned int maxAniso)908     void Technique::setTextureAnisotropy(unsigned int maxAniso)
909     {
910         Passes::iterator i, iend;
911         iend = mPasses.end();
912         for (i = mPasses.begin(); i != iend; ++i)
913         {
914             (*i)->setTextureAnisotropy(maxAniso);
915         }
916     }
917     // --------------------------------------------------------------------
setSceneBlending(const SceneBlendType sbt)918     void Technique::setSceneBlending( const SceneBlendType sbt )
919     {
920         Passes::iterator i, iend;
921         iend = mPasses.end();
922         for (i = mPasses.begin(); i != iend; ++i)
923         {
924             (*i)->setSceneBlending(sbt);
925         }
926     }
927     // --------------------------------------------------------------------
setSeparateSceneBlending(const SceneBlendType sbt,const SceneBlendType sbta)928     void Technique::setSeparateSceneBlending( const SceneBlendType sbt, const SceneBlendType sbta )
929 	{
930         Passes::iterator i, iend;
931         iend = mPasses.end();
932         for (i = mPasses.begin(); i != iend; ++i)
933         {
934             (*i)->setSeparateSceneBlending(sbt, sbta);
935         }
936 	}
937     // --------------------------------------------------------------------
setSceneBlending(const SceneBlendFactor sourceFactor,const SceneBlendFactor destFactor)938     void Technique::setSceneBlending( const SceneBlendFactor sourceFactor,
939         const SceneBlendFactor destFactor)
940     {
941         Passes::iterator i, iend;
942         iend = mPasses.end();
943         for (i = mPasses.begin(); i != iend; ++i)
944         {
945             (*i)->setSceneBlending(sourceFactor, destFactor);
946         }
947     }
948     // --------------------------------------------------------------------
setSeparateSceneBlending(const SceneBlendFactor sourceFactor,const SceneBlendFactor destFactor,const SceneBlendFactor sourceFactorAlpha,const SceneBlendFactor destFactorAlpha)949     void Technique::setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha)
950 	{
951         Passes::iterator i, iend;
952         iend = mPasses.end();
953         for (i = mPasses.begin(); i != iend; ++i)
954         {
955             (*i)->setSeparateSceneBlending(sourceFactor, destFactor, sourceFactorAlpha, destFactorAlpha);
956         }
957 	}
958 
959     // --------------------------------------------------------------------
setName(const String & name)960     void Technique::setName(const String& name)
961     {
962         mName = name;
963     }
964 
965 
966     //-----------------------------------------------------------------------
_notifyNeedsRecompile(void)967     void Technique::_notifyNeedsRecompile(void)
968     {
969         // Disable require to recompile when splitting illumination passes
970         if (mIlluminationPassesCompilationPhase != IPS_COMPILE_DISABLED)
971         {
972             mParent->_notifyNeedsRecompile();
973         }
974     }
975     //-----------------------------------------------------------------------
setLodIndex(unsigned short index)976     void Technique::setLodIndex(unsigned short index)
977     {
978         mLodIndex = index;
979         _notifyNeedsRecompile();
980     }
981     //-----------------------------------------------------------------------
setSchemeName(const String & schemeName)982 	void Technique::setSchemeName(const String& schemeName)
983 	{
984 		mSchemeIndex = MaterialManager::getSingleton()._getSchemeIndex(schemeName);
985         _notifyNeedsRecompile();
986 	}
987     //-----------------------------------------------------------------------
getSchemeName(void) const988 	const String& Technique::getSchemeName(void) const
989 	{
990 		return MaterialManager::getSingleton()._getSchemeName(mSchemeIndex);
991 	}
992     //-----------------------------------------------------------------------
_getSchemeIndex(void) const993 	unsigned short Technique::_getSchemeIndex(void) const
994 	{
995 		return mSchemeIndex;
996 	}
997 	//---------------------------------------------------------------------
checkManuallyOrganisedIlluminationPasses()998 	bool Technique::checkManuallyOrganisedIlluminationPasses()
999 	{
1000 		// first check whether all passes have manually assigned illumination
1001 		Passes::iterator i, ibegin, iend;
1002 		ibegin = mPasses.begin();
1003 		iend = mPasses.end();
1004 
1005 		for (i = ibegin; i != iend; ++i)
1006 		{
1007 			if ((*i)->getIlluminationStage() == IS_UNKNOWN)
1008 				return false;
1009 		}
1010 
1011 		// ok, all manually controlled, so just use that
1012 		for (i = ibegin; i != iend; ++i)
1013 		{
1014 			IlluminationPass* iPass = OGRE_NEW IlluminationPass();
1015 			iPass->destroyOnShutdown = false;
1016 			iPass->originalPass = iPass->pass = *i;
1017 			iPass->stage = (*i)->getIlluminationStage();
1018 			mIlluminationPasses.push_back(iPass);
1019 		}
1020 
1021 		return true;
1022 	}
1023     //-----------------------------------------------------------------------
_compileIlluminationPasses(void)1024     void Technique::_compileIlluminationPasses(void)
1025     {
1026         clearIlluminationPasses();
1027 
1028 		if (!checkManuallyOrganisedIlluminationPasses())
1029 		{
1030 			// Build based on our own heuristics
1031 
1032 			Passes::iterator i, iend;
1033 			iend = mPasses.end();
1034 			i = mPasses.begin();
1035 
1036 			IlluminationStage iStage = IS_AMBIENT;
1037 
1038 			bool haveAmbient = false;
1039 			while (i != iend)
1040 			{
1041 				IlluminationPass* iPass;
1042 				Pass* p = *i;
1043 				switch(iStage)
1044 				{
1045 				case IS_AMBIENT:
1046 					// Keep looking for ambient only
1047 					if (p->isAmbientOnly())
1048 					{
1049 						// Add this pass wholesale
1050 						iPass = OGRE_NEW IlluminationPass();
1051 						iPass->destroyOnShutdown = false;
1052 						iPass->originalPass = iPass->pass = p;
1053 						iPass->stage = iStage;
1054 						mIlluminationPasses.push_back(iPass);
1055 						haveAmbient = true;
1056 						// progress to next pass
1057 						++i;
1058 					}
1059 					else
1060 					{
1061 						// Split off any ambient part
1062 						if (p->getAmbient() != ColourValue::Black ||
1063 							p->getSelfIllumination() != ColourValue::Black ||
1064 							p->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
1065 						{
1066 							// Copy existing pass
1067 							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
1068 							if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
1069 							{
1070 								// Alpha rejection passes must retain their transparency, so
1071 								// we allow the texture units, but override the colour functions
1072 								Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator();
1073 								while (tusi.hasMoreElements())
1074 								{
1075 									TextureUnitState* tus = tusi.getNext();
1076 									tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT);
1077 								}
1078 							}
1079 							else
1080 							{
1081 								// Remove any texture units
1082 								newPass->removeAllTextureUnitStates();
1083 							}
1084 							// Remove any fragment program
1085 							if (newPass->hasFragmentProgram())
1086 								newPass->setFragmentProgram("");
1087 							// We have to leave vertex program alone (if any) and
1088 							// just trust that the author is using light bindings, which
1089 							// we will ensure there are none in the ambient pass
1090 							newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a);  // Preserving alpha
1091 							newPass->setSpecular(ColourValue::Black);
1092 
1093 							// Calculate hash value for new pass, because we are compiling
1094 							// illumination passes on demand, which will loss hash calculate
1095 							// before it add to render queue first time.
1096 							newPass->_recalculateHash();
1097 
1098 							iPass = OGRE_NEW IlluminationPass();
1099 							iPass->destroyOnShutdown = true;
1100 							iPass->originalPass = p;
1101 							iPass->pass = newPass;
1102 							iPass->stage = iStage;
1103 
1104 							mIlluminationPasses.push_back(iPass);
1105 							haveAmbient = true;
1106 
1107 						}
1108 
1109 						if (!haveAmbient)
1110 						{
1111 							// Make up a new basic pass
1112 							Pass* newPass = OGRE_NEW Pass(this, p->getIndex());
1113 							newPass->setAmbient(ColourValue::Black);
1114 							newPass->setDiffuse(ColourValue::Black);
1115 
1116 							// Calculate hash value for new pass, because we are compiling
1117 							// illumination passes on demand, which will loss hash calculate
1118 							// before it add to render queue first time.
1119 							newPass->_recalculateHash();
1120 
1121 							iPass = OGRE_NEW IlluminationPass();
1122 							iPass->destroyOnShutdown = true;
1123 							iPass->originalPass = p;
1124 							iPass->pass = newPass;
1125 							iPass->stage = iStage;
1126 							mIlluminationPasses.push_back(iPass);
1127 							haveAmbient = true;
1128 						}
1129 						// This means we're done with ambients, progress to per-light
1130 						iStage = IS_PER_LIGHT;
1131 					}
1132 					break;
1133 				case IS_PER_LIGHT:
1134 					if (p->getIteratePerLight())
1135 					{
1136 						// If this is per-light already, use it directly
1137 						iPass = OGRE_NEW IlluminationPass();
1138 						iPass->destroyOnShutdown = false;
1139 						iPass->originalPass = iPass->pass = p;
1140 						iPass->stage = iStage;
1141 						mIlluminationPasses.push_back(iPass);
1142 						// progress to next pass
1143 						++i;
1144 					}
1145 					else
1146 					{
1147 						// Split off per-light details (can only be done for one)
1148 						if (p->getLightingEnabled() &&
1149 							(p->getDiffuse() != ColourValue::Black ||
1150 							p->getSpecular() != ColourValue::Black))
1151 						{
1152 							// Copy existing pass
1153 							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
1154 							if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
1155 							{
1156 								// Alpha rejection passes must retain their transparency, so
1157 								// we allow the texture units, but override the colour functions
1158 								Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator();
1159 								while (tusi.hasMoreElements())
1160 								{
1161 									TextureUnitState* tus = tusi.getNext();
1162 									tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT);
1163 								}
1164 							}
1165 							else
1166 							{
1167 								// remove texture units
1168 								newPass->removeAllTextureUnitStates();
1169 							}
1170 							// remove fragment programs
1171 							if (newPass->hasFragmentProgram())
1172 								newPass->setFragmentProgram("");
1173 							// Cannot remove vertex program, have to assume that
1174 							// it will process diffuse lights, ambient will be turned off
1175 							newPass->setAmbient(ColourValue::Black);
1176 							newPass->setSelfIllumination(ColourValue::Black);
1177 							// must be additive
1178 							newPass->setSceneBlending(SBF_ONE, SBF_ONE);
1179 
1180 							// Calculate hash value for new pass, because we are compiling
1181 							// illumination passes on demand, which will loss hash calculate
1182 							// before it add to render queue first time.
1183 							newPass->_recalculateHash();
1184 
1185 							iPass = OGRE_NEW IlluminationPass();
1186 							iPass->destroyOnShutdown = true;
1187 							iPass->originalPass = p;
1188 							iPass->pass = newPass;
1189 							iPass->stage = iStage;
1190 
1191 							mIlluminationPasses.push_back(iPass);
1192 
1193 						}
1194 						// This means the end of per-light passes
1195 						iStage = IS_DECAL;
1196 					}
1197 					break;
1198 				case IS_DECAL:
1199 					// We just want a 'lighting off' pass to finish off
1200 					// and only if there are texture units
1201 					if (p->getNumTextureUnitStates() > 0)
1202 					{
1203 						if (!p->getLightingEnabled())
1204 						{
1205 							// we assume this pass already combines as required with the scene
1206 							iPass = OGRE_NEW IlluminationPass();
1207 							iPass->destroyOnShutdown = false;
1208 							iPass->originalPass = iPass->pass = p;
1209 							iPass->stage = iStage;
1210 							mIlluminationPasses.push_back(iPass);
1211 						}
1212 						else
1213 						{
1214 							// Copy the pass and tweak away the lighting parts
1215 							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
1216 							newPass->setAmbient(ColourValue::Black);
1217 							newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a);  // Preserving alpha
1218 							newPass->setSpecular(ColourValue::Black);
1219 							newPass->setSelfIllumination(ColourValue::Black);
1220 							newPass->setLightingEnabled(false);
1221 							newPass->setIteratePerLight(false, false);
1222 							// modulate
1223 							newPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
1224 
1225 							// Calculate hash value for new pass, because we are compiling
1226 							// illumination passes on demand, which will loss hash calculate
1227 							// before it add to render queue first time.
1228 							newPass->_recalculateHash();
1229 
1230 							// NB there is nothing we can do about vertex & fragment
1231 							// programs here, so people will just have to make their
1232 							// programs friendly-like if they want to use this technique
1233 							iPass = OGRE_NEW IlluminationPass();
1234 							iPass->destroyOnShutdown = true;
1235 							iPass->originalPass = p;
1236 							iPass->pass = newPass;
1237 							iPass->stage = iStage;
1238 							mIlluminationPasses.push_back(iPass);
1239 
1240 						}
1241 					}
1242 					++i; // always increment on decal, since nothing more to do with this pass
1243 
1244 					break;
1245                 case IS_UNKNOWN:
1246                     break;
1247 				}
1248 			}
1249 		}
1250 
1251     }
1252     //-----------------------------------------------------------------------
clearIlluminationPasses(void)1253     void Technique::clearIlluminationPasses(void)
1254     {
1255         IlluminationPassList::iterator i, iend;
1256         iend = mIlluminationPasses.end();
1257         for (i = mIlluminationPasses.begin(); i != iend; ++i)
1258         {
1259             if ((*i)->destroyOnShutdown)
1260             {
1261                 (*i)->pass->queueForDeletion();
1262             }
1263             OGRE_DELETE *i;
1264         }
1265         mIlluminationPasses.clear();
1266     }
1267     //-----------------------------------------------------------------------
1268     const Technique::IlluminationPassIterator
getIlluminationPassIterator(void)1269     Technique::getIlluminationPassIterator(void)
1270     {
1271         IlluminationPassesState targetState = IPS_COMPILED;
1272         if (mIlluminationPassesCompilationPhase != targetState)
1273         {
1274             // prevents parent->_notifyNeedsRecompile() call during compile
1275             mIlluminationPassesCompilationPhase = IPS_COMPILE_DISABLED;
1276             // Splitting the passes into illumination passes
1277             _compileIlluminationPasses();
1278             // Mark that illumination passes compilation finished
1279             mIlluminationPassesCompilationPhase = targetState;
1280         }
1281 
1282         return IlluminationPassIterator(mIlluminationPasses.begin(),
1283             mIlluminationPasses.end());
1284     }
1285     //-----------------------------------------------------------------------
getResourceGroup(void) const1286 	const String& Technique::getResourceGroup(void) const
1287 	{
1288 		return mParent->getGroup();
1289 	}
1290 
1291     //-----------------------------------------------------------------------
applyTextureAliases(const AliasTextureNamePairList & aliasList,const bool apply) const1292     bool Technique::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const
1293     {
1294         // iterate through passes and apply texture alias
1295         Passes::const_iterator i, iend;
1296         iend = mPasses.end();
1297         bool testResult = false;
1298 
1299         for(i = mPasses.begin(); i != iend; ++i)
1300         {
1301             if ((*i)->applyTextureAliases(aliasList, apply))
1302                 testResult = true;
1303         }
1304 
1305         return testResult;
1306     }
1307 	//-----------------------------------------------------------------------
getShadowCasterMaterial() const1308 	Ogre::MaterialPtr  Technique::getShadowCasterMaterial() const
1309 	{
1310 		return mShadowCasterMaterial;
1311 	}
1312 	//-----------------------------------------------------------------------
setShadowCasterMaterial(Ogre::MaterialPtr val)1313 	void  Technique::setShadowCasterMaterial(Ogre::MaterialPtr val)
1314 	{
1315 		if (val.isNull())
1316 		{
1317 			mShadowCasterMaterial.setNull();
1318 			mShadowCasterMaterialName.clear();
1319 		}
1320 		else
1321 		{
1322 			mShadowCasterMaterial = val;
1323 			mShadowCasterMaterialName = val->getName();
1324 		}
1325 	}
1326 	//-----------------------------------------------------------------------
setShadowCasterMaterial(const Ogre::String & name)1327 	void  Technique::setShadowCasterMaterial(const Ogre::String &name)
1328 	{
1329 		mShadowCasterMaterialName = name;
1330 		mShadowCasterMaterial = MaterialManager::getSingleton().getByName(name);
1331 	}
1332 	//-----------------------------------------------------------------------
getShadowReceiverMaterial() const1333 	Ogre::MaterialPtr  Technique::getShadowReceiverMaterial() const
1334 	{
1335 		return mShadowReceiverMaterial;
1336 	}
1337 	//-----------------------------------------------------------------------
setShadowReceiverMaterial(Ogre::MaterialPtr val)1338 	void  Technique::setShadowReceiverMaterial(Ogre::MaterialPtr val)
1339 	{
1340 		if (val.isNull())
1341 		{
1342 			mShadowReceiverMaterial.setNull();
1343 			mShadowReceiverMaterialName.clear();
1344 		}
1345 		else
1346 		{
1347 			mShadowReceiverMaterial = val;
1348 			mShadowReceiverMaterialName = val->getName();
1349 		}
1350 	}
1351 	//-----------------------------------------------------------------------
setShadowReceiverMaterial(const Ogre::String & name)1352 	void  Technique::setShadowReceiverMaterial(const Ogre::String &name)
1353 	{
1354 		mShadowReceiverMaterialName = name;
1355 		mShadowReceiverMaterial = MaterialManager::getSingleton().getByName(name);
1356 	}
1357 	//---------------------------------------------------------------------
addGPUVendorRule(GPUVendor vendor,Technique::IncludeOrExclude includeOrExclude)1358 	void Technique::addGPUVendorRule(GPUVendor vendor, Technique::IncludeOrExclude includeOrExclude)
1359 	{
1360 		addGPUVendorRule(GPUVendorRule(vendor, includeOrExclude));
1361 	}
1362 	//---------------------------------------------------------------------
addGPUVendorRule(const Technique::GPUVendorRule & rule)1363 	void Technique::addGPUVendorRule(const Technique::GPUVendorRule& rule)
1364 	{
1365 		// remove duplicates
1366 		removeGPUVendorRule(rule.vendor);
1367 		mGPUVendorRules.push_back(rule);
1368 	}
1369 	//---------------------------------------------------------------------
removeGPUVendorRule(GPUVendor vendor)1370 	void Technique::removeGPUVendorRule(GPUVendor vendor)
1371 	{
1372 		for (GPUVendorRuleList::iterator i = mGPUVendorRules.begin(); i != mGPUVendorRules.end(); )
1373 		{
1374 			if (i->vendor == vendor)
1375 				i = mGPUVendorRules.erase(i);
1376 			else
1377 				++i;
1378 		}
1379 	}
1380 	//---------------------------------------------------------------------
getGPUVendorRuleIterator() const1381 	Technique::GPUVendorRuleIterator Technique::getGPUVendorRuleIterator() const
1382 	{
1383 		return GPUVendorRuleIterator(mGPUVendorRules.begin(), mGPUVendorRules.end());
1384 	}
1385 	//---------------------------------------------------------------------
addGPUDeviceNameRule(const String & devicePattern,Technique::IncludeOrExclude includeOrExclude,bool caseSensitive)1386 	void Technique::addGPUDeviceNameRule(const String& devicePattern,
1387 		Technique::IncludeOrExclude includeOrExclude, bool caseSensitive)
1388 	{
1389 		addGPUDeviceNameRule(GPUDeviceNameRule(devicePattern, includeOrExclude, caseSensitive));
1390 	}
1391 	//---------------------------------------------------------------------
addGPUDeviceNameRule(const Technique::GPUDeviceNameRule & rule)1392 	void Technique::addGPUDeviceNameRule(const Technique::GPUDeviceNameRule& rule)
1393 	{
1394 		// remove duplicates
1395 		removeGPUDeviceNameRule(rule.devicePattern);
1396 		mGPUDeviceNameRules.push_back(rule);
1397 	}
1398 	//---------------------------------------------------------------------
removeGPUDeviceNameRule(const String & devicePattern)1399 	void Technique::removeGPUDeviceNameRule(const String& devicePattern)
1400 	{
1401 		for (GPUDeviceNameRuleList::iterator i = mGPUDeviceNameRules.begin(); i != mGPUDeviceNameRules.end(); )
1402 		{
1403 			if (i->devicePattern == devicePattern)
1404 				i = mGPUDeviceNameRules.erase(i);
1405 			else
1406 				++i;
1407 		}
1408 	}
1409 	//---------------------------------------------------------------------
getGPUDeviceNameRuleIterator() const1410 	Technique::GPUDeviceNameRuleIterator Technique::getGPUDeviceNameRuleIterator() const
1411 	{
1412 		return GPUDeviceNameRuleIterator(mGPUDeviceNameRules.begin(), mGPUDeviceNameRules.end());
1413 	}
1414 	//---------------------------------------------------------------------
1415 
1416 
1417 }
1418