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-2014 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 "OgreGpuProgramUsage.h"
31 #include "OgreTextureUnitState.h"
32 
33 namespace Ogre {
34 
35     /** Default pass hash function.
36     @remarks
37         Tries to minimise the number of texture changes.
38     */
39     struct MinTextureStateChangeHashFunc : public Pass::HashFunc
40     {
operator ()Ogre::MinTextureStateChangeHashFunc41         uint32 operator()(const Pass* p) const
42         {
43             OGRE_LOCK_MUTEX(p->mTexUnitChangeMutex);
44             uint32 hash = 0;
45             ushort c = p->getNumTextureUnitStates();
46 
47             for (ushort i = 0; i < c; ++i)
48             {
49                 const TextureUnitState* tus = 0;
50                 tus = p->getTextureUnitState(i);
51                 hash = FastHash(tus->getTextureName().c_str(), tus->getTextureName().size(), hash);
52             }
53 
54             return hash;
55         }
56     };
57     MinTextureStateChangeHashFunc sMinTextureStateChangeHashFunc;
58     /** Alternate pass hash function.
59     @remarks
60         Tries to minimise the number of GPU program changes.
61     */
62     struct MinGpuProgramChangeHashFunc : public Pass::HashFunc
63     {
operator ()Ogre::MinGpuProgramChangeHashFunc64         uint32 operator()(const Pass* p) const
65         {
66             OGRE_LOCK_MUTEX(p->mGpuProgramChangeMutex);
67             uint32 hash = 0;
68 
69             for(int i = 0; i < GPT_COUNT; i++)
70             {
71                 const String& name = p->getGpuProgramName(GpuProgramType(i));
72                 if(!name.empty()) {
73                     hash = FastHash(name.c_str(), name.size(), hash);
74                 }
75             }
76 
77             return hash;
78         }
79     };
80     MinGpuProgramChangeHashFunc sMinGpuProgramChangeHashFunc;
81     //-----------------------------------------------------------------------------
82     Pass::PassSet Pass::msDirtyHashList;
83     Pass::PassSet Pass::msPassGraveyard;
84     OGRE_STATIC_MUTEX_INSTANCE(Pass::msDirtyHashListMutex);
85     OGRE_STATIC_MUTEX_INSTANCE(Pass::msPassGraveyardMutex);
86 
87     Pass::HashFunc* Pass::msHashFunc = &sMinGpuProgramChangeHashFunc;
88     //-----------------------------------------------------------------------------
getBuiltinHashFunction(BuiltinHashFunction builtin)89     Pass::HashFunc* Pass::getBuiltinHashFunction(BuiltinHashFunction builtin)
90     {
91         Pass::HashFunc* hashFunc = NULL;
92 
93         switch(builtin)
94         {
95         case MIN_TEXTURE_CHANGE:
96             hashFunc = &sMinTextureStateChangeHashFunc;
97             break;
98         case MIN_GPU_PROGRAM_CHANGE:
99             hashFunc = &sMinGpuProgramChangeHashFunc;
100             break;
101         }
102 
103         return hashFunc;
104     }
105     //-----------------------------------------------------------------------------
setHashFunction(BuiltinHashFunction builtin)106     void Pass::setHashFunction(BuiltinHashFunction builtin)
107     {
108         switch(builtin)
109         {
110         case MIN_TEXTURE_CHANGE:
111             msHashFunc = &sMinTextureStateChangeHashFunc;
112             break;
113         case MIN_GPU_PROGRAM_CHANGE:
114             msHashFunc = &sMinGpuProgramChangeHashFunc;
115             break;
116         }
117     }
118     //-----------------------------------------------------------------------------
Pass(Technique * parent,unsigned short index)119     Pass::Pass(Technique* parent, unsigned short index)
120         : mParent(parent)
121         , mHash(0)
122         , mIndex(index)
123         , mAmbient(ColourValue::White)
124         , mDiffuse(ColourValue::White)
125         , mSpecular(ColourValue::Black)
126         , mEmissive(ColourValue::Black)
127         , mShininess(0)
128         , mTracking(TVC_NONE)
129         , mHashDirtyQueued(false)
130         , mDepthCheck(true)
131         , mDepthWrite(true)
132         , mAlphaToCoverageEnabled(false)
133         , mTransparentSorting(true)
134         , mTransparentSortingForced(false)
135         , mLightingEnabled(true)
136         , mIteratePerLight(false)
137         , mRunOnlyForOneLightType(false)
138         , mNormaliseNormals(false)
139         , mPolygonModeOverrideable(true)
140         , mFogOverride(false)
141         , mQueuedForDeletion(false)
142         , mLightScissoring(false)
143         , mLightClipPlanes(false)
144         , mPointSpritesEnabled(false)
145         , mPointAttenuationEnabled(false)
146         , mContentTypeLookupBuilt(false)
147         , mAlphaRejectVal(0)
148         , mDepthFunc(CMPF_LESS_EQUAL)
149         , mDepthBiasConstant(0.0f)
150         , mDepthBiasSlopeScale(0.0f)
151         , mDepthBiasPerIteration(0.0f)
152         , mAlphaRejectFunc(CMPF_ALWAYS_PASS)
153         , mCullMode(CULL_CLOCKWISE)
154         , mManualCullMode(MANUAL_CULL_BACK)
155         , mMaxSimultaneousLights(OGRE_MAX_SIMULTANEOUS_LIGHTS)
156         , mStartLight(0)
157         , mLightsPerIteration(1)
158         , mOnlyLightType(Light::LT_POINT)
159         , mLightMask(0xFFFFFFFF)
160         , mShadeOptions(SO_GOURAUD)
161         , mPolygonMode(PM_SOLID)
162         , mFogMode(FOG_NONE)
163         , mFogColour(ColourValue::White)
164         , mFogStart(0.0)
165         , mFogEnd(1.0)
166         , mFogDensity(0.001)
167         , mPassIterationCount(1)
168         , mLineWidth(1.0f)
169         , mPointSize(1.0f)
170         , mPointMinSize(0.0f)
171         , mPointMaxSize(0.0f)
172         , mIlluminationStage(IS_UNKNOWN)
173     {
174         mPointAttenuationCoeffs[0] = 1.0f;
175         mPointAttenuationCoeffs[1] = mPointAttenuationCoeffs[2] = 0.0f;
176 
177         // init the hash inline
178         _recalculateHash();
179    }
180 
181     //-----------------------------------------------------------------------------
Pass(Technique * parent,unsigned short index,const Pass & oth)182     Pass::Pass(Technique *parent, unsigned short index, const Pass& oth)
183         : mParent(parent), mIndex(index), mQueuedForDeletion(false), mPassIterationCount(1)
184     {
185         *this = oth;
186         mParent = parent;
187         mIndex = index;
188         mQueuedForDeletion = false;
189 
190         // init the hash inline
191         _recalculateHash();
192     }
193     Pass::~Pass() = default; // ensure unique_ptr destructors are in cpp
194     //-----------------------------------------------------------------------------
operator =(const Pass & oth)195     Pass& Pass::operator=(const Pass& oth)
196     {
197         mName = oth.mName;
198         mHash = oth.mHash;
199         mAmbient = oth.mAmbient;
200         mDiffuse = oth.mDiffuse;
201         mSpecular = oth.mSpecular;
202         mEmissive = oth.mEmissive;
203         mShininess = oth.mShininess;
204         mTracking = oth.mTracking;
205 
206         // Copy fog parameters
207         mFogOverride = oth.mFogOverride;
208         mFogMode = oth.mFogMode;
209         mFogColour = oth.mFogColour;
210         mFogStart = oth.mFogStart;
211         mFogEnd = oth.mFogEnd;
212         mFogDensity = oth.mFogDensity;
213 
214         // Default blending (overwrite)
215         mBlendState = oth.mBlendState;
216 
217         mDepthCheck = oth.mDepthCheck;
218         mDepthWrite = oth.mDepthWrite;
219         mAlphaRejectFunc = oth.mAlphaRejectFunc;
220         mAlphaRejectVal = oth.mAlphaRejectVal;
221         mAlphaToCoverageEnabled = oth.mAlphaToCoverageEnabled;
222         mTransparentSorting = oth.mTransparentSorting;
223         mTransparentSortingForced = oth.mTransparentSortingForced;
224         mDepthFunc = oth.mDepthFunc;
225         mDepthBiasConstant = oth.mDepthBiasConstant;
226         mDepthBiasSlopeScale = oth.mDepthBiasSlopeScale;
227         mDepthBiasPerIteration = oth.mDepthBiasPerIteration;
228         mCullMode = oth.mCullMode;
229         mManualCullMode = oth.mManualCullMode;
230         mLightingEnabled = oth.mLightingEnabled;
231         mMaxSimultaneousLights = oth.mMaxSimultaneousLights;
232         mStartLight = oth.mStartLight;
233         mIteratePerLight = oth.mIteratePerLight;
234         mLightsPerIteration = oth.mLightsPerIteration;
235         mRunOnlyForOneLightType = oth.mRunOnlyForOneLightType;
236         mNormaliseNormals = oth.mNormaliseNormals;
237         mOnlyLightType = oth.mOnlyLightType;
238         mShadeOptions = oth.mShadeOptions;
239         mPolygonMode = oth.mPolygonMode;
240         mPolygonModeOverrideable = oth.mPolygonModeOverrideable;
241         mPassIterationCount = oth.mPassIterationCount;
242         mLineWidth = oth.mLineWidth;
243         mPointSize = oth.mPointSize;
244         mPointMinSize = oth.mPointMinSize;
245         mPointMaxSize = oth.mPointMaxSize;
246         mPointSpritesEnabled = oth.mPointSpritesEnabled;
247         mPointAttenuationEnabled = oth.mPointAttenuationEnabled;
248         memcpy(mPointAttenuationCoeffs, oth.mPointAttenuationCoeffs, sizeof(Real)*3);
249         mShadowContentTypeLookup = oth.mShadowContentTypeLookup;
250         mContentTypeLookupBuilt = oth.mContentTypeLookupBuilt;
251         mLightScissoring = oth.mLightScissoring;
252         mLightClipPlanes = oth.mLightClipPlanes;
253         mIlluminationStage = oth.mIlluminationStage;
254         mLightMask = oth.mLightMask;
255 
256         for(int i = 0; i < GPT_COUNT; i++)
257         {
258             auto& programUsage = mProgramUsage[i];
259             auto& othUsage = oth.mProgramUsage[i];
260             othUsage ? programUsage.reset(new GpuProgramUsage(*othUsage, this)) : programUsage.reset();
261         }
262 
263         mShadowCasterVertexProgramUsage.reset();
264         if (oth.mShadowCasterVertexProgramUsage)
265         {
266             mShadowCasterVertexProgramUsage.reset(new GpuProgramUsage(*(oth.mShadowCasterVertexProgramUsage), this));
267         }
268 
269         mShadowCasterFragmentProgramUsage.reset();
270         if (oth.mShadowCasterFragmentProgramUsage)
271         {
272             mShadowCasterFragmentProgramUsage.reset(new GpuProgramUsage(*(oth.mShadowCasterFragmentProgramUsage), this));
273         }
274 
275         mShadowReceiverVertexProgramUsage.reset();
276         if (oth.mShadowReceiverVertexProgramUsage)
277         {
278             mShadowReceiverVertexProgramUsage.reset(new GpuProgramUsage(*(oth.mShadowReceiverVertexProgramUsage), this));
279         }
280 
281         mShadowReceiverFragmentProgramUsage.reset();
282         if (oth.mShadowReceiverFragmentProgramUsage)
283         {
284             mShadowReceiverFragmentProgramUsage.reset(new GpuProgramUsage(*(oth.mShadowReceiverFragmentProgramUsage), this));
285         }
286 
287         TextureUnitStates::const_iterator i, iend;
288 
289         // Clear texture units but doesn't notify need recompilation in the case
290         // we are cloning, The parent material will take care of this.
291         iend = mTextureUnitStates.end();
292         for (i = mTextureUnitStates.begin(); i != iend; ++i)
293         {
294             OGRE_DELETE *i;
295         }
296 
297         mTextureUnitStates.clear();
298 
299         // Copy texture units
300         iend = oth.mTextureUnitStates.end();
301         for (i = oth.mTextureUnitStates.begin(); i != iend; ++i)
302         {
303             TextureUnitState* t = OGRE_NEW TextureUnitState(this, *(*i));
304             mTextureUnitStates.push_back(t);
305         }
306 
307         _dirtyHash();
308 
309         return *this;
310     }
311     //-----------------------------------------------------------------------------
calculateSize(void) const312     size_t Pass::calculateSize(void) const
313     {
314         size_t memSize = 0;
315 
316         // Tally up TU states
317         TextureUnitStates::const_iterator i, iend;
318         iend = mTextureUnitStates.end();
319         for (i = mTextureUnitStates.begin(); i != iend; ++i)
320         {
321             memSize += (*i)->calculateSize();
322         }
323         for(const auto& u : mProgramUsage)
324             memSize += u ? u->calculateSize() : 0;
325 
326         if(mShadowCasterVertexProgramUsage)
327             memSize += mShadowCasterVertexProgramUsage->calculateSize();
328         if(mShadowCasterFragmentProgramUsage)
329             memSize += mShadowCasterFragmentProgramUsage->calculateSize();
330         if(mShadowReceiverVertexProgramUsage)
331             memSize += mShadowReceiverVertexProgramUsage->calculateSize();
332         if(mShadowReceiverFragmentProgramUsage)
333             memSize += mShadowReceiverFragmentProgramUsage->calculateSize();
334         return memSize;
335     }
336     //-----------------------------------------------------------------------
setName(const String & name)337     void Pass::setName(const String& name)
338     {
339         mName = name;
340     }
341     //-----------------------------------------------------------------------
setPointSize(Real ps)342     void Pass::setPointSize(Real ps)
343     {
344         mPointSize = ps;
345     }
346     //-----------------------------------------------------------------------
setPointSpritesEnabled(bool enabled)347     void Pass::setPointSpritesEnabled(bool enabled)
348     {
349         mPointSpritesEnabled = enabled;
350     }
351     //-----------------------------------------------------------------------
getPointSpritesEnabled(void) const352     bool Pass::getPointSpritesEnabled(void) const
353     {
354         return mPointSpritesEnabled;
355     }
356     //-----------------------------------------------------------------------
setPointAttenuation(bool enabled,Real constant,Real linear,Real quadratic)357     void Pass::setPointAttenuation(bool enabled,
358         Real constant, Real linear, Real quadratic)
359     {
360         mPointAttenuationEnabled = enabled;
361         mPointAttenuationCoeffs[0] = constant;
362         mPointAttenuationCoeffs[1] = linear;
363         mPointAttenuationCoeffs[2] = quadratic;
364     }
365     //-----------------------------------------------------------------------
isPointAttenuationEnabled(void) const366     bool Pass::isPointAttenuationEnabled(void) const
367     {
368         return mPointAttenuationEnabled;
369     }
370     //-----------------------------------------------------------------------
getPointAttenuationConstant(void) const371     Real Pass::getPointAttenuationConstant(void) const
372     {
373         return mPointAttenuationCoeffs[0];
374     }
375     //-----------------------------------------------------------------------
getPointAttenuationLinear(void) const376     Real Pass::getPointAttenuationLinear(void) const
377     {
378         return mPointAttenuationCoeffs[1];
379     }
380     //-----------------------------------------------------------------------
getPointAttenuationQuadratic(void) const381     Real Pass::getPointAttenuationQuadratic(void) const
382     {
383         return mPointAttenuationCoeffs[2];
384     }
385     //-----------------------------------------------------------------------
setPointMinSize(Real min)386     void Pass::setPointMinSize(Real min)
387     {
388         mPointMinSize = min;
389     }
390     //-----------------------------------------------------------------------
getPointMinSize(void) const391     Real Pass::getPointMinSize(void) const
392     {
393         return mPointMinSize;
394     }
395     //-----------------------------------------------------------------------
setPointMaxSize(Real max)396     void Pass::setPointMaxSize(Real max)
397     {
398         mPointMaxSize = max;
399     }
400     //-----------------------------------------------------------------------
getPointMaxSize(void) const401     Real Pass::getPointMaxSize(void) const
402     {
403         return mPointMaxSize;
404     }
405     //-----------------------------------------------------------------------
setAmbient(float red,float green,float blue)406     void Pass::setAmbient(float red, float green, float blue)
407     {
408         mAmbient.r = red;
409         mAmbient.g = green;
410         mAmbient.b = blue;
411 
412     }
413     //-----------------------------------------------------------------------
setAmbient(const ColourValue & ambient)414     void Pass::setAmbient(const ColourValue& ambient)
415     {
416         mAmbient = ambient;
417     }
418     //-----------------------------------------------------------------------
setDiffuse(float red,float green,float blue,float alpha)419     void Pass::setDiffuse(float red, float green, float blue, float alpha)
420     {
421         mDiffuse.r = red;
422         mDiffuse.g = green;
423         mDiffuse.b = blue;
424         mDiffuse.a = alpha;
425     }
426     //-----------------------------------------------------------------------
setDiffuse(const ColourValue & diffuse)427     void Pass::setDiffuse(const ColourValue& diffuse)
428     {
429         mDiffuse = diffuse;
430     }
431     //-----------------------------------------------------------------------
setSpecular(float red,float green,float blue,float alpha)432     void Pass::setSpecular(float red, float green, float blue, float alpha)
433     {
434         mSpecular.r = red;
435         mSpecular.g = green;
436         mSpecular.b = blue;
437         mSpecular.a = alpha;
438     }
439     //-----------------------------------------------------------------------
setSpecular(const ColourValue & specular)440     void Pass::setSpecular(const ColourValue& specular)
441     {
442         mSpecular = specular;
443     }
444     //-----------------------------------------------------------------------
setShininess(Real val)445     void Pass::setShininess(Real val)
446     {
447         mShininess = val;
448     }
449     //-----------------------------------------------------------------------
setSelfIllumination(float red,float green,float blue)450     void Pass::setSelfIllumination(float red, float green, float blue)
451     {
452         mEmissive.r = red;
453         mEmissive.g = green;
454         mEmissive.b = blue;
455 
456     }
457     //-----------------------------------------------------------------------
setSelfIllumination(const ColourValue & selfIllum)458     void Pass::setSelfIllumination(const ColourValue& selfIllum)
459     {
460         mEmissive = selfIllum;
461     }
462     //-----------------------------------------------------------------------
setVertexColourTracking(TrackVertexColourType tracking)463     void Pass::setVertexColourTracking(TrackVertexColourType tracking)
464     {
465         mTracking = tracking;
466     }
467     //-----------------------------------------------------------------------
getPointSize(void) const468     Real Pass::getPointSize(void) const
469     {
470         return mPointSize;
471     }
472     //-----------------------------------------------------------------------
getAmbient(void) const473     const ColourValue& Pass::getAmbient(void) const
474     {
475         return mAmbient;
476     }
477     //-----------------------------------------------------------------------
getDiffuse(void) const478     const ColourValue& Pass::getDiffuse(void) const
479     {
480         return mDiffuse;
481     }
482     //-----------------------------------------------------------------------
getSpecular(void) const483     const ColourValue& Pass::getSpecular(void) const
484     {
485         return mSpecular;
486     }
487     //-----------------------------------------------------------------------
getSelfIllumination(void) const488     const ColourValue& Pass::getSelfIllumination(void) const
489     {
490         return mEmissive;
491     }
492     //-----------------------------------------------------------------------
getShininess(void) const493     Real Pass::getShininess(void) const
494     {
495         return mShininess;
496     }
497     //-----------------------------------------------------------------------
getVertexColourTracking(void) const498     TrackVertexColourType Pass::getVertexColourTracking(void) const
499     {
500         return mTracking;
501     }
502     //-----------------------------------------------------------------------
createTextureUnitState(void)503     TextureUnitState* Pass::createTextureUnitState(void)
504     {
505         TextureUnitState *t = OGRE_NEW TextureUnitState(this);
506         addTextureUnitState(t);
507         mContentTypeLookupBuilt = false;
508         return t;
509     }
510     //-----------------------------------------------------------------------
createTextureUnitState(const String & textureName,unsigned short texCoordSet)511     TextureUnitState* Pass::createTextureUnitState(
512         const String& textureName, unsigned short texCoordSet)
513     {
514         TextureUnitState *t = OGRE_NEW TextureUnitState(this);
515         t->setTextureName(textureName);
516         t->setTextureCoordSet(texCoordSet);
517         addTextureUnitState(t);
518         mContentTypeLookupBuilt = false;
519         return t;
520     }
521     //-----------------------------------------------------------------------
addTextureUnitState(TextureUnitState * state)522     void Pass::addTextureUnitState(TextureUnitState* state)
523     {
524             OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
525 
526         assert(state && "state is 0 in Pass::addTextureUnitState()");
527         if (state)
528         {
529             // only attach TUS to pass if TUS does not belong to another pass
530             if ((state->getParent() == 0) || (state->getParent() == this))
531             {
532                 mTextureUnitStates.push_back(state);
533                 // Notify state
534                 state->_notifyParent(this);
535                 // if texture unit state name is empty then give it a default name based on its index
536                 if (state->getName().empty())
537                 {
538                     // its the last entry in the container so its index is size - 1
539                     size_t idx = mTextureUnitStates.size() - 1;
540 
541                     // allow 8 digit hex number. there should never be that many texture units.
542                     // This sprintf replaced a call to StringConverter::toString for performance reasons
543                     state->setName( StringUtil::format("%lx", static_cast<long>(idx)));
544 
545                     /** since the name was never set and a default one has been made, clear the alias name
546                      so that when the texture unit name is set by the user, the alias name will be set to
547                      that name
548                     */
549                     state->setTextureNameAlias(BLANKSTRING);
550                 }
551                 // Needs recompilation
552                 mParent->_notifyNeedsRecompile();
553                 _dirtyHash();
554             }
555             else
556             {
557                 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState already attached to another pass",
558                     "Pass:addTextureUnitState");
559 
560             }
561             mContentTypeLookupBuilt = false;
562         }
563     }
564     //-----------------------------------------------------------------------
getTextureUnitState(unsigned short index) const565     TextureUnitState* Pass::getTextureUnitState(unsigned short index) const
566     {
567             OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
568         assert (index < mTextureUnitStates.size() && "Index out of bounds");
569         return mTextureUnitStates[index];
570     }
571     //-----------------------------------------------------------------------------
getTextureUnitState(const String & name) const572     TextureUnitState* Pass::getTextureUnitState(const String& name) const
573     {
574             OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
575         TextureUnitStates::const_iterator i    = mTextureUnitStates.begin();
576         TextureUnitStates::const_iterator iend = mTextureUnitStates.end();
577         TextureUnitState* foundTUS = 0;
578 
579         // iterate through TUS Container to find a match
580         while (i != iend)
581         {
582             if ( (*i)->getName() == name )
583             {
584                 foundTUS = (*i);
585                 break;
586             }
587 
588             ++i;
589         }
590 
591         return foundTUS;
592     }
593 
594     //-----------------------------------------------------------------------
getTextureUnitStateIndex(const TextureUnitState * state) const595     unsigned short Pass::getTextureUnitStateIndex(const TextureUnitState* state) const
596     {
597         OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
598         assert(state && "state is 0 in Pass::getTextureUnitStateIndex()");
599 
600         // only find index for state attached to this pass
601         if (state->getParent() == this)
602         {
603             TextureUnitStates::const_iterator i =
604                 std::find(mTextureUnitStates.begin(), mTextureUnitStates.end(), state);
605             assert(i != mTextureUnitStates.end() && "state is supposed to attached to this pass");
606             return static_cast<unsigned short>(std::distance(mTextureUnitStates.begin(), i));
607         }
608         else
609         {
610             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState is not attached to this pass",
611                 "Pass:getTextureUnitStateIndex");
612         }
613     }
614 
615     //-----------------------------------------------------------------------
616     Pass::TextureUnitStateIterator
getTextureUnitStateIterator(void)617         Pass::getTextureUnitStateIterator(void)
618     {
619         return TextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
620     }
621     //-----------------------------------------------------------------------
622     Pass::ConstTextureUnitStateIterator
getTextureUnitStateIterator(void) const623         Pass::getTextureUnitStateIterator(void) const
624     {
625         return ConstTextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
626     }
627     //-----------------------------------------------------------------------
removeTextureUnitState(unsigned short index)628     void Pass::removeTextureUnitState(unsigned short index)
629     {
630         OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
631         assert (index < mTextureUnitStates.size() && "Index out of bounds");
632 
633         TextureUnitStates::iterator i = mTextureUnitStates.begin() + index;
634         OGRE_DELETE *i;
635         mTextureUnitStates.erase(i);
636         if (!mQueuedForDeletion)
637         {
638             // Needs recompilation
639             mParent->_notifyNeedsRecompile();
640         }
641         _dirtyHash();
642         mContentTypeLookupBuilt = false;
643     }
644     //-----------------------------------------------------------------------
removeAllTextureUnitStates(void)645     void Pass::removeAllTextureUnitStates(void)
646     {
647         OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
648         TextureUnitStates::iterator i, iend;
649         iend = mTextureUnitStates.end();
650         for (i = mTextureUnitStates.begin(); i != iend; ++i)
651         {
652             OGRE_DELETE *i;
653         }
654         mTextureUnitStates.clear();
655         if (!mQueuedForDeletion)
656         {
657             // Needs recompilation
658             mParent->_notifyNeedsRecompile();
659         }
660         _dirtyHash();
661         mContentTypeLookupBuilt = false;
662     }
663     //-----------------------------------------------------------------------
_getBlendFlags(SceneBlendType type,SceneBlendFactor & source,SceneBlendFactor & dest)664     void Pass::_getBlendFlags(SceneBlendType type, SceneBlendFactor& source, SceneBlendFactor& dest)
665     {
666         switch ( type )
667         {
668         case SBT_TRANSPARENT_ALPHA:
669             source = SBF_SOURCE_ALPHA;
670             dest = SBF_ONE_MINUS_SOURCE_ALPHA;
671             return;
672         case SBT_TRANSPARENT_COLOUR:
673             source = SBF_SOURCE_COLOUR;
674             dest = SBF_ONE_MINUS_SOURCE_COLOUR;
675             return;
676         case SBT_MODULATE:
677             source = SBF_DEST_COLOUR;
678             dest = SBF_ZERO;
679             return;
680         case SBT_ADD:
681             source = SBF_ONE;
682             dest = SBF_ONE;
683             return;
684         case SBT_REPLACE:
685             source = SBF_ONE;
686             dest = SBF_ZERO;
687             return;
688         }
689 
690         // Default to SBT_REPLACE
691 
692         source = SBF_ONE;
693         dest = SBF_ZERO;
694     }
695     //-----------------------------------------------------------------------
setSceneBlending(SceneBlendType sbt)696     void Pass::setSceneBlending(SceneBlendType sbt)
697     {
698         // Convert type into blend factors
699 
700         SceneBlendFactor source;
701         SceneBlendFactor dest;
702         _getBlendFlags(sbt, source, dest);
703 
704         // Set blend factors
705 
706         setSceneBlending(source, dest);
707     }
708     //-----------------------------------------------------------------------
setSeparateSceneBlending(const SceneBlendType sbt,const SceneBlendType sbta)709     void Pass::setSeparateSceneBlending( const SceneBlendType sbt, const SceneBlendType sbta )
710     {
711         // Convert types into blend factors
712 
713         SceneBlendFactor source;
714         SceneBlendFactor dest;
715         _getBlendFlags(sbt, source, dest);
716 
717         SceneBlendFactor sourceAlpha;
718         SceneBlendFactor destAlpha;
719         _getBlendFlags(sbta, sourceAlpha, destAlpha);
720 
721         // Set blend factors
722 
723         setSeparateSceneBlending(source, dest, sourceAlpha, destAlpha);
724     }
725 
726     //-----------------------------------------------------------------------
setSceneBlending(SceneBlendFactor sourceFactor,SceneBlendFactor destFactor)727     void Pass::setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
728     {
729         mBlendState.sourceFactor = sourceFactor;
730         mBlendState.sourceFactorAlpha = sourceFactor;
731         mBlendState.destFactor = destFactor;
732         mBlendState.destFactorAlpha = destFactor;
733     }
734     //-----------------------------------------------------------------------
setSeparateSceneBlending(const SceneBlendFactor sourceFactor,const SceneBlendFactor destFactor,const SceneBlendFactor sourceFactorAlpha,const SceneBlendFactor destFactorAlpha)735     void Pass::setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha )
736     {
737         mBlendState.sourceFactor = sourceFactor;
738         mBlendState.destFactor = destFactor;
739         mBlendState.sourceFactorAlpha = sourceFactorAlpha;
740         mBlendState.destFactorAlpha = destFactorAlpha;
741     }
742     //-----------------------------------------------------------------------
getSourceBlendFactor(void) const743     SceneBlendFactor Pass::getSourceBlendFactor(void) const
744     {
745         return mBlendState.sourceFactor;
746     }
747     //-----------------------------------------------------------------------
getDestBlendFactor(void) const748     SceneBlendFactor Pass::getDestBlendFactor(void) const
749     {
750         return mBlendState.destFactor;
751     }
752     //-----------------------------------------------------------------------
getSourceBlendFactorAlpha(void) const753     SceneBlendFactor Pass::getSourceBlendFactorAlpha(void) const
754     {
755         return mBlendState.sourceFactorAlpha ;
756     }
757     //-----------------------------------------------------------------------
getDestBlendFactorAlpha(void) const758     SceneBlendFactor Pass::getDestBlendFactorAlpha(void) const
759     {
760         return mBlendState.destFactorAlpha;
761     }
762     //-----------------------------------------------------------------------
hasSeparateSceneBlending() const763     bool Pass::hasSeparateSceneBlending() const
764     {
765         return true;
766     }
767     //-----------------------------------------------------------------------
setSceneBlendingOperation(SceneBlendOperation op)768     void Pass::setSceneBlendingOperation(SceneBlendOperation op)
769     {
770         mBlendState.operation = op;
771         mBlendState.alphaOperation = op;
772     }
773     //-----------------------------------------------------------------------
setSeparateSceneBlendingOperation(SceneBlendOperation op,SceneBlendOperation alphaOp)774     void Pass::setSeparateSceneBlendingOperation(SceneBlendOperation op, SceneBlendOperation alphaOp)
775     {
776         mBlendState.operation = op;
777         mBlendState.alphaOperation = alphaOp;
778     }
779     //-----------------------------------------------------------------------
getSceneBlendingOperation() const780     SceneBlendOperation Pass::getSceneBlendingOperation() const
781     {
782         return mBlendState.operation;
783     }
784     //-----------------------------------------------------------------------
getSceneBlendingOperationAlpha() const785     SceneBlendOperation Pass::getSceneBlendingOperationAlpha() const
786     {
787         return mBlendState.alphaOperation;
788     }
789     //-----------------------------------------------------------------------
hasSeparateSceneBlendingOperations() const790     bool Pass::hasSeparateSceneBlendingOperations() const
791     {
792         return true;
793     }
794     //-----------------------------------------------------------------------
isTransparent(void) const795     bool Pass::isTransparent(void) const
796     {
797         // Transparent if any of the destination colour is taken into account
798         if (mBlendState.destFactor == SBF_ZERO &&
799             mBlendState.sourceFactor != SBF_DEST_COLOUR &&
800             mBlendState.sourceFactor != SBF_ONE_MINUS_DEST_COLOUR &&
801             mBlendState.sourceFactor != SBF_DEST_ALPHA &&
802             mBlendState.sourceFactor != SBF_ONE_MINUS_DEST_ALPHA)
803         {
804             return false;
805         }
806         else
807         {
808             return true;
809         }
810     }
811     //-----------------------------------------------------------------------
setDepthCheckEnabled(bool enabled)812     void Pass::setDepthCheckEnabled(bool enabled)
813     {
814         mDepthCheck = enabled;
815     }
816     //-----------------------------------------------------------------------
getDepthCheckEnabled(void) const817     bool Pass::getDepthCheckEnabled(void) const
818     {
819         return mDepthCheck;
820     }
821     //-----------------------------------------------------------------------
setDepthWriteEnabled(bool enabled)822     void Pass::setDepthWriteEnabled(bool enabled)
823     {
824         mDepthWrite = enabled;
825     }
826     //-----------------------------------------------------------------------
getDepthWriteEnabled(void) const827     bool Pass::getDepthWriteEnabled(void) const
828     {
829         return mDepthWrite;
830     }
831     //-----------------------------------------------------------------------
setDepthFunction(CompareFunction func)832     void Pass::setDepthFunction( CompareFunction func)
833     {
834         mDepthFunc = func;
835     }
836     //-----------------------------------------------------------------------
getDepthFunction(void) const837     CompareFunction Pass::getDepthFunction(void) const
838     {
839         return mDepthFunc;
840     }
841     //-----------------------------------------------------------------------
setAlphaRejectSettings(CompareFunction func,unsigned char value,bool alphaToCoverage)842     void Pass::setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverage)
843     {
844         mAlphaRejectFunc = func;
845         mAlphaRejectVal = value;
846         mAlphaToCoverageEnabled = alphaToCoverage;
847     }
848     //-----------------------------------------------------------------------
setAlphaRejectFunction(CompareFunction func)849     void Pass::setAlphaRejectFunction(CompareFunction func)
850     {
851         mAlphaRejectFunc = func;
852     }
853     //-----------------------------------------------------------------------
setAlphaRejectValue(unsigned char val)854     void Pass::setAlphaRejectValue(unsigned char val)
855     {
856         mAlphaRejectVal = val;
857     }
858     //---------------------------------------------------------------------
setAlphaToCoverageEnabled(bool enabled)859     void Pass::setAlphaToCoverageEnabled(bool enabled)
860     {
861         mAlphaToCoverageEnabled = enabled;
862     }
863     //-----------------------------------------------------------------------
setTransparentSortingEnabled(bool enabled)864     void Pass::setTransparentSortingEnabled(bool enabled)
865     {
866         mTransparentSorting = enabled;
867     }
868     //-----------------------------------------------------------------------
getTransparentSortingEnabled(void) const869     bool Pass::getTransparentSortingEnabled(void) const
870     {
871         return mTransparentSorting;
872     }
873     //-----------------------------------------------------------------------
setTransparentSortingForced(bool enabled)874     void Pass::setTransparentSortingForced(bool enabled)
875     {
876         mTransparentSortingForced = enabled;
877     }
878     //-----------------------------------------------------------------------
getTransparentSortingForced(void) const879     bool Pass::getTransparentSortingForced(void) const
880     {
881         return mTransparentSortingForced;
882     }
883     //-----------------------------------------------------------------------
setColourWriteEnabled(bool enabled)884     void Pass::setColourWriteEnabled(bool enabled)
885     {
886         mBlendState.writeR = enabled;
887         mBlendState.writeG = enabled;
888         mBlendState.writeB = enabled;
889         mBlendState.writeA = enabled;
890     }
891     //-----------------------------------------------------------------------
getColourWriteEnabled() const892     bool Pass::getColourWriteEnabled() const
893     {
894         return mBlendState.writeR || mBlendState.writeG || mBlendState.writeB ||
895                mBlendState.writeA;
896     }
897     //-----------------------------------------------------------------------
898 
setColourWriteEnabled(bool red,bool green,bool blue,bool alpha)899     void Pass::setColourWriteEnabled(bool red, bool green, bool blue, bool alpha)
900     {
901         mBlendState.writeR = red;
902         mBlendState.writeG = green;
903         mBlendState.writeB = blue;
904         mBlendState.writeA = alpha;
905     }
906     //-----------------------------------------------------------------------
getColourWriteEnabled(bool & red,bool & green,bool & blue,bool & alpha) const907     void Pass::getColourWriteEnabled(bool& red, bool& green, bool& blue, bool& alpha) const
908     {
909         red = mBlendState.writeR;
910         green = mBlendState.writeG;
911         blue = mBlendState.writeB;
912         alpha = mBlendState.writeA;
913     }
914     //-----------------------------------------------------------------------
setCullingMode(CullingMode mode)915     void Pass::setCullingMode( CullingMode mode)
916     {
917         mCullMode = mode;
918     }
919     //-----------------------------------------------------------------------
getCullingMode(void) const920     CullingMode Pass::getCullingMode(void) const
921     {
922         return mCullMode;
923     }
924     //-----------------------------------------------------------------------
setLightingEnabled(bool enabled)925     void Pass::setLightingEnabled(bool enabled)
926     {
927         mLightingEnabled = enabled;
928     }
929     //-----------------------------------------------------------------------
getLightingEnabled(void) const930     bool Pass::getLightingEnabled(void) const
931     {
932         return mLightingEnabled;
933     }
934     //-----------------------------------------------------------------------
setMaxSimultaneousLights(unsigned short maxLights)935     void Pass::setMaxSimultaneousLights(unsigned short maxLights)
936     {
937         mMaxSimultaneousLights = maxLights;
938     }
939     //-----------------------------------------------------------------------
getMaxSimultaneousLights(void) const940     unsigned short Pass::getMaxSimultaneousLights(void) const
941     {
942         return mMaxSimultaneousLights;
943     }
944     //-----------------------------------------------------------------------
setStartLight(unsigned short startLight)945     void Pass::setStartLight(unsigned short startLight)
946     {
947         mStartLight = startLight;
948     }
949     //-----------------------------------------------------------------------
getStartLight(void) const950     unsigned short Pass::getStartLight(void) const
951     {
952         return mStartLight;
953     }
954     //-----------------------------------------------------------------------
setLightMask(uint32 mask)955     void Pass::setLightMask(uint32 mask)
956     {
957         mLightMask = mask;
958     }
959     //-----------------------------------------------------------------------
getLightMask() const960     uint32 Pass::getLightMask() const
961     {
962         return mLightMask;
963     }
964     //-----------------------------------------------------------------------
setLightCountPerIteration(unsigned short c)965     void Pass::setLightCountPerIteration(unsigned short c)
966     {
967         mLightsPerIteration = c;
968     }
969     //-----------------------------------------------------------------------
getLightCountPerIteration(void) const970     unsigned short Pass::getLightCountPerIteration(void) const
971     {
972         return mLightsPerIteration;
973     }
974     //-----------------------------------------------------------------------
setIteratePerLight(bool enabled,bool onlyForOneLightType,Light::LightTypes lightType)975     void Pass::setIteratePerLight(bool enabled,
976             bool onlyForOneLightType, Light::LightTypes lightType)
977     {
978         mIteratePerLight = enabled;
979         mRunOnlyForOneLightType = onlyForOneLightType;
980         mOnlyLightType = lightType;
981     }
982     //-----------------------------------------------------------------------
setShadingMode(ShadeOptions mode)983     void Pass::setShadingMode(ShadeOptions mode)
984     {
985         mShadeOptions = mode;
986     }
987     //-----------------------------------------------------------------------
getShadingMode(void) const988     ShadeOptions Pass::getShadingMode(void) const
989     {
990         return mShadeOptions;
991     }
992     //-----------------------------------------------------------------------
setPolygonMode(PolygonMode mode)993     void Pass::setPolygonMode(PolygonMode mode)
994     {
995         mPolygonMode = mode;
996     }
997     //-----------------------------------------------------------------------
getPolygonMode(void) const998     PolygonMode Pass::getPolygonMode(void) const
999     {
1000         return mPolygonMode;
1001     }
1002     //-----------------------------------------------------------------------
setManualCullingMode(ManualCullingMode mode)1003     void Pass::setManualCullingMode(ManualCullingMode mode)
1004     {
1005         mManualCullMode = mode;
1006     }
1007     //-----------------------------------------------------------------------
getManualCullingMode(void) const1008     ManualCullingMode Pass::getManualCullingMode(void) const
1009     {
1010         return mManualCullMode;
1011     }
1012     //-----------------------------------------------------------------------
setFog(bool overrideScene,FogMode mode,const ColourValue & colour,Real density,Real start,Real end)1013     void Pass::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
1014     {
1015         mFogOverride = overrideScene;
1016         if (overrideScene)
1017         {
1018             mFogMode = mode;
1019             mFogColour = colour;
1020             mFogStart = start;
1021             mFogEnd = end;
1022             mFogDensity = density;
1023         }
1024     }
1025     //-----------------------------------------------------------------------
getFogOverride(void) const1026     bool Pass::getFogOverride(void) const
1027     {
1028         return mFogOverride;
1029     }
1030     //-----------------------------------------------------------------------
getFogMode(void) const1031     FogMode Pass::getFogMode(void) const
1032     {
1033         return mFogMode;
1034     }
1035     //-----------------------------------------------------------------------
getFogColour(void) const1036     const ColourValue& Pass::getFogColour(void) const
1037     {
1038         return mFogColour;
1039     }
1040     //-----------------------------------------------------------------------
getFogStart(void) const1041     Real Pass::getFogStart(void) const
1042     {
1043         return mFogStart;
1044     }
1045     //-----------------------------------------------------------------------
getFogEnd(void) const1046     Real Pass::getFogEnd(void) const
1047     {
1048         return mFogEnd;
1049     }
1050     //-----------------------------------------------------------------------
getFogDensity(void) const1051     Real Pass::getFogDensity(void) const
1052     {
1053         return mFogDensity;
1054     }
1055     //-----------------------------------------------------------------------
setDepthBias(float constantBias,float slopeScaleBias)1056     void Pass::setDepthBias(float constantBias, float slopeScaleBias)
1057     {
1058        mDepthBiasConstant = constantBias;
1059        mDepthBiasSlopeScale = slopeScaleBias;
1060     }
1061     //-----------------------------------------------------------------------
getDepthBiasConstant(void) const1062     float Pass::getDepthBiasConstant(void) const
1063     {
1064         return mDepthBiasConstant;
1065     }
1066     //-----------------------------------------------------------------------
getDepthBiasSlopeScale(void) const1067     float Pass::getDepthBiasSlopeScale(void) const
1068     {
1069         return mDepthBiasSlopeScale;
1070     }
1071     //---------------------------------------------------------------------
setIterationDepthBias(float biasPerIteration)1072     void Pass::setIterationDepthBias(float biasPerIteration)
1073     {
1074         mDepthBiasPerIteration = biasPerIteration;
1075     }
1076     //---------------------------------------------------------------------
getIterationDepthBias() const1077     float Pass::getIterationDepthBias() const
1078     {
1079         return mDepthBiasPerIteration;
1080     }
1081     //-----------------------------------------------------------------------
_split(unsigned short numUnits)1082     Pass* Pass::_split(unsigned short numUnits)
1083     {
1084         if (isProgrammable())
1085         {
1086             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Programmable passes cannot be "
1087                 "automatically split, define a fallback technique instead.",
1088                 "Pass:_split");
1089         }
1090 
1091         if (mTextureUnitStates.size() > numUnits)
1092         {
1093             size_t start = mTextureUnitStates.size() - numUnits;
1094 
1095             Pass* newPass = mParent->createPass();
1096 
1097             TextureUnitStates::iterator istart, i, iend;
1098             iend = mTextureUnitStates.end();
1099             i = istart = mTextureUnitStates.begin() + start;
1100             // Set the new pass to fallback using scene blend
1101             newPass->setSceneBlending(
1102                 (*i)->getColourBlendFallbackSrc(), (*i)->getColourBlendFallbackDest());
1103             // Fixup the texture unit 0   of new pass   blending method   to replace
1104             // all colour and alpha   with texture without adjustment, because we
1105             // assume it's detail texture.
1106             (*i)->setColourOperationEx(LBX_SOURCE1,   LBS_TEXTURE, LBS_CURRENT);
1107             (*i)->setAlphaOperation(LBX_SOURCE1, LBS_TEXTURE, LBS_CURRENT);
1108 
1109             // Add all the other texture unit states
1110             for (; i != iend; ++i)
1111             {
1112                 // detach from parent first
1113                 (*i)->_notifyParent(0);
1114                 newPass->addTextureUnitState(*i);
1115             }
1116             // Now remove texture units from this Pass, we don't need to delete since they've
1117             // been transferred
1118             mTextureUnitStates.erase(istart, iend);
1119             _dirtyHash();
1120             mContentTypeLookupBuilt = false;
1121             return newPass;
1122         }
1123         return NULL;
1124     }
1125     //-----------------------------------------------------------------------------
_notifyIndex(unsigned short index)1126     void Pass::_notifyIndex(unsigned short index)
1127     {
1128         if (mIndex != index)
1129         {
1130             mIndex = index;
1131             _dirtyHash();
1132         }
1133     }
1134     //-----------------------------------------------------------------------
_prepare(void)1135     void Pass::_prepare(void)
1136     {
1137         // We assume the Technique only calls this when the material is being
1138         // prepared
1139 
1140         // prepare each TextureUnitState
1141         TextureUnitStates::iterator i, iend;
1142         iend = mTextureUnitStates.end();
1143         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1144         {
1145             (*i)->_prepare();
1146         }
1147 
1148     }
1149     //-----------------------------------------------------------------------
_unprepare(void)1150     void Pass::_unprepare(void)
1151     {
1152         // unprepare each TextureUnitState
1153         TextureUnitStates::iterator i, iend;
1154         iend = mTextureUnitStates.end();
1155         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1156         {
1157             (*i)->_unprepare();
1158         }
1159 
1160     }
1161     //-----------------------------------------------------------------------
_load(void)1162     void Pass::_load(void)
1163     {
1164         // We assume the Technique only calls this when the material is being
1165         // loaded
1166 
1167         // Load each TextureUnitState
1168         TextureUnitStates::iterator i, iend;
1169         iend = mTextureUnitStates.end();
1170         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1171         {
1172             (*i)->_load();
1173         }
1174 
1175         // Load programs
1176         for (const auto& u : mProgramUsage)
1177             if(u) u->_load();
1178 
1179         if (mShadowCasterVertexProgramUsage)
1180         {
1181             // Load vertex program
1182             mShadowCasterVertexProgramUsage->_load();
1183         }
1184         if (mShadowCasterFragmentProgramUsage)
1185         {
1186             // Load fragment program
1187             mShadowCasterFragmentProgramUsage->_load();
1188         }
1189         if (mShadowReceiverVertexProgramUsage)
1190         {
1191             // Load vertex program
1192             mShadowReceiverVertexProgramUsage->_load();
1193         }
1194 
1195         if (mShadowReceiverFragmentProgramUsage)
1196         {
1197             // Load Fragment program
1198             mShadowReceiverFragmentProgramUsage->_load();
1199         }
1200 
1201         if (mHashDirtyQueued)
1202         {
1203             _dirtyHash();
1204         }
1205 
1206     }
1207     //-----------------------------------------------------------------------
_unload(void)1208     void Pass::_unload(void)
1209     {
1210         // Unload each TextureUnitState
1211         TextureUnitStates::iterator i, iend;
1212         iend = mTextureUnitStates.end();
1213         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1214         {
1215             (*i)->_unload();
1216         }
1217 
1218         // TODO Unload programs
1219     }
1220     //-----------------------------------------------------------------------
setVertexProgram(const String & name,bool resetParams)1221     void Pass::setVertexProgram(const String& name, bool resetParams)
1222     {
1223         setGpuProgram(GPT_VERTEX_PROGRAM, name, resetParams);
1224     }
1225     //-----------------------------------------------------------------------
setGpuProgramParameters(GpuProgramType type,const GpuProgramParametersSharedPtr & params)1226     void Pass::setGpuProgramParameters(GpuProgramType type, const GpuProgramParametersSharedPtr& params)
1227     {
1228         OGRE_LOCK_MUTEX(mGpuProgramChangeMutex);
1229 
1230         const auto& programUsage = getProgramUsage(type);
1231         if (!programUsage)
1232         {
1233             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1234                 "This pass does not have this program type assigned!");
1235         }
1236         programUsage->setParameters(params);
1237     }
setVertexProgramParameters(GpuProgramParametersSharedPtr params)1238     void Pass::setVertexProgramParameters(GpuProgramParametersSharedPtr params)
1239     {
1240         setGpuProgramParameters(GPT_VERTEX_PROGRAM, params);
1241     }
1242     //-----------------------------------------------------------------------
setGpuProgram(GpuProgramType type,const GpuProgramPtr & program,bool resetParams)1243     void Pass::setGpuProgram(GpuProgramType type, const GpuProgramPtr& program, bool resetParams)
1244     {
1245         OGRE_LOCK_MUTEX(mGpuProgramChangeMutex);
1246 
1247         std::unique_ptr<GpuProgramUsage>& programUsage = getProgramUsage(type);
1248 
1249         // Turn off fragment program if name blank
1250         if (!program)
1251         {
1252             programUsage.reset();
1253         }
1254         else
1255         {
1256             if (!programUsage)
1257             {
1258                 programUsage.reset(new GpuProgramUsage(type, this));
1259             }
1260             programUsage->setProgram(program, resetParams);
1261         }
1262         // Needs recompilation
1263         mParent->_notifyNeedsRecompile();
1264 
1265         if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_GPU_PROGRAM_CHANGE ) )
1266         {
1267             _dirtyHash();
1268         }
1269     }
1270 
setGpuProgram(GpuProgramType type,const String & name,bool resetParams)1271     void Pass::setGpuProgram(GpuProgramType type, const String& name, bool resetParams)
1272     {
1273         if (getGpuProgramName(type) == name)
1274             return;
1275 
1276         GpuProgramPtr program;
1277         if (!name.empty())
1278             program = GpuProgramUsage::_getProgramByName(name, getResourceGroup(), type);
1279 
1280         setGpuProgram(type, program, resetParams);
1281     }
1282 
setFragmentProgram(const String & name,bool resetParams)1283     void Pass::setFragmentProgram(const String& name, bool resetParams)
1284     {
1285         setGpuProgram(GPT_FRAGMENT_PROGRAM, name, resetParams);
1286     }
1287     //-----------------------------------------------------------------------
setFragmentProgramParameters(GpuProgramParametersSharedPtr params)1288     void Pass::setFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1289     {
1290         setGpuProgramParameters(GPT_FRAGMENT_PROGRAM, params);
1291     }
1292     //-----------------------------------------------------------------------
setGeometryProgram(const String & name,bool resetParams)1293     void Pass::setGeometryProgram(const String& name, bool resetParams)
1294     {
1295         setGpuProgram(GPT_GEOMETRY_PROGRAM, name, resetParams);
1296     }
1297     //-----------------------------------------------------------------------
setGeometryProgramParameters(GpuProgramParametersSharedPtr params)1298     void Pass::setGeometryProgramParameters(GpuProgramParametersSharedPtr params)
1299     {
1300         setGpuProgramParameters(GPT_GEOMETRY_PROGRAM, params);
1301     }
1302     //-----------------------------------------------------------------------
setTessellationHullProgram(const String & name,bool resetParams)1303     void Pass::setTessellationHullProgram(const String& name, bool resetParams)
1304     {
1305         setGpuProgram(GPT_HULL_PROGRAM, name, resetParams);
1306     }
1307     //-----------------------------------------------------------------------
setTessellationHullProgramParameters(GpuProgramParametersSharedPtr params)1308     void Pass::setTessellationHullProgramParameters(GpuProgramParametersSharedPtr params)
1309     {
1310         setGpuProgramParameters(GPT_HULL_PROGRAM, params);
1311     }
1312     //-----------------------------------------------------------------------
setTessellationDomainProgram(const String & name,bool resetParams)1313     void Pass::setTessellationDomainProgram(const String& name, bool resetParams)
1314     {
1315         setGpuProgram(GPT_DOMAIN_PROGRAM, name, resetParams);
1316     }
1317     //-----------------------------------------------------------------------
setTessellationDomainProgramParameters(GpuProgramParametersSharedPtr params)1318     void Pass::setTessellationDomainProgramParameters(GpuProgramParametersSharedPtr params)
1319     {
1320         setGpuProgramParameters(GPT_DOMAIN_PROGRAM, params);
1321     }
1322     //-----------------------------------------------------------------------
setComputeProgram(const String & name,bool resetParams)1323     void Pass::setComputeProgram(const String& name, bool resetParams)
1324     {
1325         setGpuProgram(GPT_COMPUTE_PROGRAM, name, resetParams);
1326     }
1327     //-----------------------------------------------------------------------
setComputeProgramParameters(GpuProgramParametersSharedPtr params)1328     void Pass::setComputeProgramParameters(GpuProgramParametersSharedPtr params)
1329     {
1330         setGpuProgramParameters(GPT_COMPUTE_PROGRAM, params);
1331     }
1332     //-----------------------------------------------------------------------
getGpuProgramParameters(GpuProgramType type) const1333     const GpuProgramParametersSharedPtr& Pass::getGpuProgramParameters(GpuProgramType type) const
1334     {
1335         OGRE_LOCK_MUTEX(mGpuProgramChangeMutex);
1336         const auto& programUsage = getProgramUsage(type);
1337         if (!programUsage)
1338         {
1339             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1340                 "This pass does not have this program type assigned!");
1341         }
1342         return programUsage->getParameters();
1343     }
1344 
getVertexProgramParameters(void) const1345     GpuProgramParametersSharedPtr Pass::getVertexProgramParameters(void) const
1346     {
1347         return getGpuProgramParameters(GPT_VERTEX_PROGRAM);
1348     }
1349 
getProgramUsage(GpuProgramType programType)1350     std::unique_ptr<GpuProgramUsage>& Pass::getProgramUsage(GpuProgramType programType) {
1351         return mProgramUsage[programType];
1352     }
1353 
getProgramUsage(GpuProgramType programType) const1354     const std::unique_ptr<GpuProgramUsage>& Pass::getProgramUsage(GpuProgramType programType) const
1355     {
1356         return mProgramUsage[programType];
1357     }
1358 
hasGpuProgram(GpuProgramType programType) const1359     bool Pass::hasGpuProgram(GpuProgramType programType) const {
1360         return getProgramUsage(programType) != NULL;
1361     }
getGpuProgram(GpuProgramType programType) const1362     const GpuProgramPtr& Pass::getGpuProgram(GpuProgramType programType) const
1363 	{
1364         OGRE_LOCK_MUTEX(mGpuProgramChangeMutex);
1365         OgreAssert(mProgramUsage[programType], "check whether program is available using hasGpuProgram()");
1366         return mProgramUsage[programType]->getProgram();
1367 	}
1368     //-----------------------------------------------------------------------
getVertexProgram(void) const1369     const GpuProgramPtr& Pass::getVertexProgram(void) const
1370     {
1371         return getGpuProgram(GPT_VERTEX_PROGRAM);
1372     }
1373     //-----------------------------------------------------------------------
getGpuProgramName(GpuProgramType type) const1374     const String& Pass::getGpuProgramName(GpuProgramType type) const
1375     {
1376         OGRE_LOCK_MUTEX(mGpuProgramChangeMutex);
1377 
1378         const std::unique_ptr<GpuProgramUsage>& programUsage = getProgramUsage(type);
1379         if (!programUsage)
1380             return BLANKSTRING;
1381         else
1382             return programUsage->getProgramName();
1383     }
1384     //-----------------------------------------------------------------------
getFragmentProgramParameters(void) const1385     GpuProgramParametersSharedPtr Pass::getFragmentProgramParameters(void) const
1386     {
1387         return getGpuProgramParameters(GPT_FRAGMENT_PROGRAM);
1388     }
1389     //-----------------------------------------------------------------------
getFragmentProgram(void) const1390     const GpuProgramPtr& Pass::getFragmentProgram(void) const
1391     {
1392         return getGpuProgram(GPT_FRAGMENT_PROGRAM);
1393     }
1394     //-----------------------------------------------------------------------
getGeometryProgramParameters(void) const1395     GpuProgramParametersSharedPtr Pass::getGeometryProgramParameters(void) const
1396     {
1397         return getGpuProgramParameters(GPT_GEOMETRY_PROGRAM);
1398     }
1399     //-----------------------------------------------------------------------
getGeometryProgram(void) const1400     const GpuProgramPtr& Pass::getGeometryProgram(void) const
1401     {
1402         return getGpuProgram(GPT_GEOMETRY_PROGRAM);
1403     }
1404     //-----------------------------------------------------------------------
getTessellationHullProgramParameters(void) const1405     GpuProgramParametersSharedPtr Pass::getTessellationHullProgramParameters(void) const
1406     {
1407         return getGpuProgramParameters(GPT_HULL_PROGRAM);
1408     }
1409     //-----------------------------------------------------------------------
getTessellationHullProgram(void) const1410     const GpuProgramPtr& Pass::getTessellationHullProgram(void) const
1411     {
1412         return getGpuProgram(GPT_HULL_PROGRAM);
1413     }
1414     //-----------------------------------------------------------------------
getTessellationDomainProgramParameters(void) const1415     GpuProgramParametersSharedPtr Pass::getTessellationDomainProgramParameters(void) const
1416     {
1417         return getGpuProgramParameters(GPT_DOMAIN_PROGRAM);
1418     }
1419     //-----------------------------------------------------------------------
getTessellationDomainProgram(void) const1420     const GpuProgramPtr& Pass::getTessellationDomainProgram(void) const
1421     {
1422         return getGpuProgram(GPT_DOMAIN_PROGRAM);
1423     }
1424     //-----------------------------------------------------------------------
getComputeProgramParameters(void) const1425     GpuProgramParametersSharedPtr Pass::getComputeProgramParameters(void) const
1426     {
1427         return getGpuProgramParameters(GPT_COMPUTE_PROGRAM);
1428     }
1429     //-----------------------------------------------------------------------
getComputeProgram(void) const1430     const GpuProgramPtr& Pass::getComputeProgram(void) const
1431     {
1432         return getGpuProgram(GPT_COMPUTE_PROGRAM);
1433     }
1434     //-----------------------------------------------------------------------
isLoaded(void) const1435     bool Pass::isLoaded(void) const
1436     {
1437         return mParent->isLoaded();
1438     }
1439     //-----------------------------------------------------------------------
_recalculateHash(void)1440     void Pass::_recalculateHash(void)
1441     {
1442         /* Hash format is 32-bit, divided as follows (high to low bits)
1443            bits   purpose
1444             4     Pass index (i.e. max 16 passes!)
1445            28     Pass contents
1446        */
1447         mHash = (*msHashFunc)(this);
1448 
1449         // overwrite the 4 upper bits with pass index
1450         mHash = (uint32(mIndex) << 28) | (mHash >> 4);
1451     }
1452     //-----------------------------------------------------------------------
_dirtyHash(void)1453     void Pass::_dirtyHash(void)
1454     {
1455         Material* mat = mParent->getParent();
1456         if (mat->isLoading() || mat->isLoaded())
1457         {
1458                     OGRE_LOCK_MUTEX(msDirtyHashListMutex);
1459             // Mark this hash as for follow up
1460             msDirtyHashList.insert(this);
1461             mHashDirtyQueued = false;
1462         }
1463         else
1464         {
1465             mHashDirtyQueued = true;
1466         }
1467     }
1468     //---------------------------------------------------------------------
clearDirtyHashList(void)1469     void Pass::clearDirtyHashList(void)
1470     {
1471             OGRE_LOCK_MUTEX(msDirtyHashListMutex);
1472         msDirtyHashList.clear();
1473     }
1474     //-----------------------------------------------------------------------
_notifyNeedsRecompile(void)1475     void Pass::_notifyNeedsRecompile(void)
1476     {
1477         mParent->_notifyNeedsRecompile();
1478     }
1479     //-----------------------------------------------------------------------
setTextureFiltering(TextureFilterOptions filterType)1480     void Pass::setTextureFiltering(TextureFilterOptions filterType)
1481     {
1482         OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
1483 
1484         TextureUnitStates::iterator i, iend;
1485         iend = mTextureUnitStates.end();
1486         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1487         {
1488             (*i)->setTextureFiltering(filterType);
1489         }
1490     }
1491     // --------------------------------------------------------------------
setTextureAnisotropy(unsigned int maxAniso)1492     void Pass::setTextureAnisotropy(unsigned int maxAniso)
1493     {
1494         OGRE_LOCK_MUTEX(mTexUnitChangeMutex);
1495         TextureUnitStates::iterator i, iend;
1496         iend = mTextureUnitStates.end();
1497         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1498         {
1499             (*i)->setTextureAnisotropy(maxAniso);
1500         }
1501     }
1502     //-----------------------------------------------------------------------
_updateAutoParams(const AutoParamDataSource * source,uint16 mask) const1503     void Pass::_updateAutoParams(const AutoParamDataSource* source, uint16 mask) const
1504     {
1505         for(int i = 0; i < GPT_COUNT; i++)
1506         {
1507             const auto& programUsage = getProgramUsage(GpuProgramType(i));
1508             if (programUsage)
1509             {
1510                 // Update program auto params
1511                 programUsage->getParameters()->_updateAutoParams(source, mask);
1512             }
1513         }
1514     }
1515     //-----------------------------------------------------------------------
processPendingPassUpdates(void)1516     void Pass::processPendingPassUpdates(void)
1517     {
1518         {
1519                     OGRE_LOCK_MUTEX(msPassGraveyardMutex);
1520             // Delete items in the graveyard
1521             PassSet::iterator i, iend;
1522             iend = msPassGraveyard.end();
1523             for (i = msPassGraveyard.begin(); i != iend; ++i)
1524             {
1525                 OGRE_DELETE *i;
1526             }
1527             msPassGraveyard.clear();
1528         }
1529         PassSet tempDirtyHashList;
1530         {
1531                     OGRE_LOCK_MUTEX(msDirtyHashListMutex);
1532             // The dirty ones will have been removed from the groups above using the old hash now
1533             tempDirtyHashList.swap(msDirtyHashList);
1534         }
1535         PassSet::iterator i, iend;
1536         iend = tempDirtyHashList.end();
1537         for (i = tempDirtyHashList.begin(); i != iend; ++i)
1538         {
1539             Pass* p = *i;
1540             p->_recalculateHash();
1541         }
1542     }
1543     //-----------------------------------------------------------------------
queueForDeletion(void)1544     void Pass::queueForDeletion(void)
1545     {
1546         mQueuedForDeletion = true;
1547 
1548         removeAllTextureUnitStates();
1549         for (auto& u : mProgramUsage)
1550             u.reset();
1551 
1552         mShadowCasterVertexProgramUsage.reset();
1553         mShadowCasterFragmentProgramUsage.reset();
1554         mShadowReceiverVertexProgramUsage.reset();
1555         mShadowReceiverFragmentProgramUsage.reset();
1556 
1557         // remove from dirty list, if there
1558         {
1559             OGRE_LOCK_MUTEX(msDirtyHashListMutex);
1560             msDirtyHashList.erase(this);
1561         }
1562         {
1563             OGRE_LOCK_MUTEX(msPassGraveyardMutex);
1564             msPassGraveyard.insert(this);
1565         }
1566     }
1567     //-----------------------------------------------------------------------
isAmbientOnly(void) const1568     bool Pass::isAmbientOnly(void) const
1569     {
1570         // treat as ambient if lighting is off, or colour write is off,
1571         // or all non-ambient (& emissive) colours are black
1572         // NB a vertex program could override this, but passes using vertex
1573         // programs are expected to indicate they are ambient only by
1574         // setting the state so it matches one of the conditions above, even
1575         // though this state is not used in rendering.
1576         return (!mLightingEnabled || !getColourWriteEnabled() ||
1577             (mDiffuse == ColourValue::Black &&
1578              mSpecular == ColourValue::Black));
1579     }
1580     //-----------------------------------------------------------------------
setShadowCasterVertexProgram(const String & name)1581     void Pass::setShadowCasterVertexProgram(const String& name)
1582     {
1583         // Turn off vertex program if name blank
1584         if (name.empty())
1585         {
1586             mShadowCasterVertexProgramUsage.reset();
1587         }
1588         else
1589         {
1590             if (!mShadowCasterVertexProgramUsage)
1591             {
1592                 mShadowCasterVertexProgramUsage.reset(new GpuProgramUsage(GPT_VERTEX_PROGRAM, this));
1593             }
1594             mShadowCasterVertexProgramUsage->setProgramName(name);
1595         }
1596         // Needs recompilation
1597         mParent->_notifyNeedsRecompile();
1598     }
1599     //-----------------------------------------------------------------------
setShadowCasterVertexProgramParameters(GpuProgramParametersSharedPtr params)1600     void Pass::setShadowCasterVertexProgramParameters(GpuProgramParametersSharedPtr params)
1601     {
1602         if (!mShadowCasterVertexProgramUsage)
1603         {
1604             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1605                 "This pass does not have a shadow caster vertex program assigned!",
1606                 "Pass::setShadowCasterVertexProgramParameters");
1607         }
1608         mShadowCasterVertexProgramUsage->setParameters(params);
1609     }
1610     //-----------------------------------------------------------------------
getShadowCasterVertexProgramName(void) const1611     const String& Pass::getShadowCasterVertexProgramName(void) const
1612     {
1613         if (!mShadowCasterVertexProgramUsage)
1614             return BLANKSTRING;
1615         else
1616             return mShadowCasterVertexProgramUsage->getProgramName();
1617     }
1618     //-----------------------------------------------------------------------
getShadowCasterVertexProgramParameters(void) const1619     GpuProgramParametersSharedPtr Pass::getShadowCasterVertexProgramParameters(void) const
1620     {
1621         if (!mShadowCasterVertexProgramUsage)
1622         {
1623             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1624                 "This pass does not have a shadow caster vertex program assigned!",
1625                 "Pass::getShadowCasterVertexProgramParameters");
1626         }
1627         return mShadowCasterVertexProgramUsage->getParameters();
1628     }
1629     //-----------------------------------------------------------------------
getShadowCasterVertexProgram(void) const1630     const GpuProgramPtr& Pass::getShadowCasterVertexProgram(void) const
1631     {
1632         return mShadowCasterVertexProgramUsage->getProgram();
1633     }
1634     //-----------------------------------------------------------------------
setShadowCasterFragmentProgram(const String & name)1635     void Pass::setShadowCasterFragmentProgram(const String& name)
1636     {
1637         // Turn off fragment program if name blank
1638         if (name.empty())
1639         {
1640             mShadowCasterFragmentProgramUsage.reset();
1641         }
1642         else
1643         {
1644             if (!mShadowCasterFragmentProgramUsage)
1645             {
1646                 mShadowCasterFragmentProgramUsage.reset(new GpuProgramUsage(GPT_FRAGMENT_PROGRAM, this));
1647             }
1648             mShadowCasterFragmentProgramUsage->setProgramName(name);
1649         }
1650         // Needs recompilation
1651         mParent->_notifyNeedsRecompile();
1652     }
1653     //-----------------------------------------------------------------------
setShadowCasterFragmentProgramParameters(GpuProgramParametersSharedPtr params)1654     void Pass::setShadowCasterFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1655     {
1656         if (!mShadowCasterFragmentProgramUsage &&
1657             !Root::getSingletonPtr()->getRenderSystem()->getCapabilities()->hasCapability(
1658                 RSC_FIXED_FUNCTION))
1659         {
1660             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1661                         "This pass does not have a shadow caster fragment program assigned!",
1662                         "Pass::setShadowCasterFragmentProgramParameters");
1663         }
1664         mShadowCasterFragmentProgramUsage->setParameters(params);
1665     }
1666     //-----------------------------------------------------------------------
getShadowCasterFragmentProgramName(void) const1667     const String& Pass::getShadowCasterFragmentProgramName(void) const
1668     {
1669         if (!mShadowCasterFragmentProgramUsage)
1670             return BLANKSTRING;
1671         else
1672             return mShadowCasterFragmentProgramUsage->getProgramName();
1673     }
1674     //-----------------------------------------------------------------------
getShadowCasterFragmentProgramParameters(void) const1675     GpuProgramParametersSharedPtr Pass::getShadowCasterFragmentProgramParameters(void) const
1676     {
1677 
1678         if (!mShadowCasterFragmentProgramUsage &&
1679             !Root::getSingletonPtr()->getRenderSystem()->getCapabilities()->hasCapability(
1680                 RSC_FIXED_FUNCTION))
1681         {
1682             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1683                         "This pass does not have a shadow caster fragment program assigned!",
1684                         "Pass::getShadowCasterFragmentProgramParameters");
1685         }
1686 
1687         return mShadowCasterFragmentProgramUsage->getParameters();
1688     }
1689     //-----------------------------------------------------------------------
getShadowCasterFragmentProgram(void) const1690     const GpuProgramPtr& Pass::getShadowCasterFragmentProgram(void) const
1691     {
1692         return mShadowCasterFragmentProgramUsage->getProgram();
1693     }
1694     //-----------------------------------------------------------------------
setShadowReceiverVertexProgram(const String & name)1695     void Pass::setShadowReceiverVertexProgram(const String& name)
1696     {
1697         // Turn off vertex program if name blank
1698         if (name.empty())
1699         {
1700             mShadowReceiverVertexProgramUsage.reset();
1701         }
1702         else
1703         {
1704             if (!mShadowReceiverVertexProgramUsage)
1705             {
1706                 mShadowReceiverVertexProgramUsage.reset(new GpuProgramUsage(GPT_VERTEX_PROGRAM, this));
1707             }
1708             mShadowReceiverVertexProgramUsage->setProgramName(name);
1709         }
1710         // Needs recompilation
1711         mParent->_notifyNeedsRecompile();
1712     }
1713     //-----------------------------------------------------------------------
setShadowReceiverVertexProgramParameters(GpuProgramParametersSharedPtr params)1714     void Pass::setShadowReceiverVertexProgramParameters(GpuProgramParametersSharedPtr params)
1715     {
1716         if (!mShadowReceiverVertexProgramUsage)
1717         {
1718             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1719                 "This pass does not have a shadow receiver vertex program assigned!",
1720                 "Pass::setShadowReceiverVertexProgramParameters");
1721         }
1722         mShadowReceiverVertexProgramUsage->setParameters(params);
1723     }
1724     //-----------------------------------------------------------------------
getShadowReceiverVertexProgramName(void) const1725     const String& Pass::getShadowReceiverVertexProgramName(void) const
1726     {
1727         if (!mShadowReceiverVertexProgramUsage)
1728             return BLANKSTRING;
1729         else
1730             return mShadowReceiverVertexProgramUsage->getProgramName();
1731     }
1732     //-----------------------------------------------------------------------
getShadowReceiverVertexProgramParameters(void) const1733     GpuProgramParametersSharedPtr Pass::getShadowReceiverVertexProgramParameters(void) const
1734     {
1735         if (!mShadowReceiverVertexProgramUsage)
1736         {
1737             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1738                 "This pass does not have a shadow receiver vertex program assigned!",
1739                 "Pass::getShadowReceiverVertexProgramParameters");
1740         }
1741         return mShadowReceiverVertexProgramUsage->getParameters();
1742     }
1743     //-----------------------------------------------------------------------
getShadowReceiverVertexProgram(void) const1744     const GpuProgramPtr& Pass::getShadowReceiverVertexProgram(void) const
1745     {
1746         return mShadowReceiverVertexProgramUsage->getProgram();
1747     }
1748     //-----------------------------------------------------------------------
setShadowReceiverFragmentProgram(const String & name)1749     void Pass::setShadowReceiverFragmentProgram(const String& name)
1750     {
1751         // Turn off Fragment program if name blank
1752         if (name.empty())
1753         {
1754             mShadowReceiverFragmentProgramUsage.reset();
1755         }
1756         else
1757         {
1758             if (!mShadowReceiverFragmentProgramUsage)
1759             {
1760                 mShadowReceiverFragmentProgramUsage.reset(new GpuProgramUsage(GPT_FRAGMENT_PROGRAM, this));
1761             }
1762             mShadowReceiverFragmentProgramUsage->setProgramName(name);
1763         }
1764         // Needs recompilation
1765         mParent->_notifyNeedsRecompile();
1766     }
1767     //-----------------------------------------------------------------------
setShadowReceiverFragmentProgramParameters(GpuProgramParametersSharedPtr params)1768     void Pass::setShadowReceiverFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1769     {
1770         if (!mShadowReceiverFragmentProgramUsage)
1771         {
1772             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1773                 "This pass does not have a shadow receiver fragment program assigned!",
1774                 "Pass::setShadowReceiverFragmentProgramParameters");
1775         }
1776         mShadowReceiverFragmentProgramUsage->setParameters(params);
1777     }
1778     //-----------------------------------------------------------------------
getShadowReceiverFragmentProgramName(void) const1779     const String& Pass::getShadowReceiverFragmentProgramName(void) const
1780     {
1781         if (!mShadowReceiverFragmentProgramUsage)
1782             return BLANKSTRING;
1783         else
1784             return mShadowReceiverFragmentProgramUsage->getProgramName();
1785     }
1786     //-----------------------------------------------------------------------
getShadowReceiverFragmentProgramParameters(void) const1787     GpuProgramParametersSharedPtr Pass::getShadowReceiverFragmentProgramParameters(void) const
1788     {
1789         if (!mShadowReceiverFragmentProgramUsage)
1790         {
1791             OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1792                 "This pass does not have a shadow receiver fragment program assigned!",
1793                 "Pass::getShadowReceiverFragmentProgramParameters");
1794         }
1795         return mShadowReceiverFragmentProgramUsage->getParameters();
1796     }
1797     //-----------------------------------------------------------------------
getShadowReceiverFragmentProgram(void) const1798     const GpuProgramPtr& Pass::getShadowReceiverFragmentProgram(void) const
1799     {
1800         return mShadowReceiverFragmentProgramUsage->getProgram();
1801     }
1802     //-----------------------------------------------------------------------
getResourceGroup(void) const1803     const String& Pass::getResourceGroup(void) const
1804     {
1805         return mParent->getResourceGroup();
1806     }
1807 
1808     //-----------------------------------------------------------------------
applyTextureAliases(const AliasTextureNamePairList & aliasList,const bool apply) const1809     bool Pass::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const
1810     {
1811         // iterate through each texture unit state and apply the texture alias if it applies
1812         TextureUnitStates::const_iterator i, iend;
1813         iend = mTextureUnitStates.end();
1814         bool testResult = false;
1815 
1816         for (i = mTextureUnitStates.begin(); i != iend; ++i)
1817         {
1818             if ((*i)->applyTextureAliases(aliasList, apply))
1819                 testResult = true;
1820         }
1821 
1822         return testResult;
1823 
1824     }
1825     //-----------------------------------------------------------------------
_getTextureUnitWithContentTypeIndex(TextureUnitState::ContentType contentType,unsigned short index) const1826     unsigned short Pass::_getTextureUnitWithContentTypeIndex(
1827         TextureUnitState::ContentType contentType, unsigned short index) const
1828     {
1829         if (!mContentTypeLookupBuilt)
1830         {
1831             mShadowContentTypeLookup.clear();
1832             for (unsigned short i = 0; i < mTextureUnitStates.size(); ++i)
1833             {
1834                 if (mTextureUnitStates[i]->getContentType() == TextureUnitState::CONTENT_SHADOW)
1835                 {
1836                     mShadowContentTypeLookup.push_back(i);
1837                 }
1838             }
1839             mContentTypeLookupBuilt = true;
1840         }
1841 
1842         switch(contentType)
1843         {
1844         case TextureUnitState::CONTENT_SHADOW:
1845             if (index < mShadowContentTypeLookup.size())
1846             {
1847                 return mShadowContentTypeLookup[index];
1848             }
1849             break;
1850         default:
1851             // Simple iteration
1852             for (unsigned short i = 0; i < mTextureUnitStates.size(); ++i)
1853             {
1854                 if (mTextureUnitStates[i]->getContentType() == TextureUnitState::CONTENT_SHADOW)
1855                 {
1856                     if (index == 0)
1857                     {
1858                         return i;
1859                     }
1860                     else
1861                     {
1862                         --index;
1863                     }
1864                 }
1865             }
1866             break;
1867         }
1868 
1869         // not found - return out of range
1870         return static_cast<unsigned short>(mTextureUnitStates.size() + 1);
1871 
1872     }
1873 }
1874