Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgrePass.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 50.6 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30
31#include "OgrePass.h"
32#include "OgreTechnique.h"
33#include "OgreException.h"
34#include "OgreGpuProgramUsage.h"
35#include "OgreTextureUnitState.h"
36#include "OgreStringConverter.h"
37
38namespace Ogre {
39
40        /** Default pass hash function.
41        @remarks
42                Tries to minimise the number of texture changes.
43        */
44        struct MinTextureStateChangeHashFunc : public Pass::HashFunc
45        {
46                uint32 operator()(const Pass* p) const
47                {
48
49                        _StringHash H;
50                        uint32 hash = p->getIndex() << 28;
51                        size_t c = p->getNumTextureUnitStates();
52
53                        const TextureUnitState* t0 = 0;
54                        const TextureUnitState* t1 = 0;
55                        if (c)
56                                t0 = p->getTextureUnitState(0);
57                        if (c > 1)
58                                t1 = p->getTextureUnitState(1);
59
60                        if (t0 && !t0->getTextureName().empty())
61                                hash += (static_cast<uint32>(H(t0->getTextureName())) 
62                                        % (1 << 14)) << 14;
63                        if (t1 && !t1->getTextureName().empty())
64                                hash += (static_cast<uint32>(H(t1->getTextureName()))
65                                        % (1 << 14));
66
67                        return hash;
68                }
69        };
70        MinTextureStateChangeHashFunc sMinTextureStateChangeHashFunc;
71        /** Alternate pass hash function.
72        @remarks
73                Tries to minimise the number of GPU program changes.
74        */
75        struct MinGpuProgramChangeHashFunc : public Pass::HashFunc
76        {
77                uint32 operator()(const Pass* p) const
78                {
79
80                        _StringHash H;
81                        uint32 hash = p->getIndex() << 28;
82                        if (p->hasVertexProgram())
83                                hash += (static_cast<uint32>(H(p->getVertexProgramName()))
84                                        % (1 << 14)) << 14;
85                        if (p->hasFragmentProgram())
86                                hash += (static_cast<uint32>(H(p->getFragmentProgramName()))
87                                        % (1 << 14));
88
89                        return hash;
90                }
91        };
92        MinGpuProgramChangeHashFunc sMinGpuProgramChangeHashFunc;
93    //-----------------------------------------------------------------------------
94        Pass::PassSet Pass::msDirtyHashList;
95    Pass::PassSet Pass::msPassGraveyard;
96        OGRE_STATIC_MUTEX_INSTANCE(Pass::msDirtyHashListMutex)
97        OGRE_STATIC_MUTEX_INSTANCE(Pass::msPassGraveyardMutex)
98
99        Pass::HashFunc* Pass::msHashFunc = &sMinTextureStateChangeHashFunc;
100        //-----------------------------------------------------------------------------
101        void Pass::setHashFunction(BuiltinHashFunction builtin)
102        {
103                switch(builtin)
104                {
105                case MIN_TEXTURE_CHANGE:
106                        msHashFunc = &sMinTextureStateChangeHashFunc;
107                        break;
108                case MIN_GPU_PROGRAM_CHANGE:
109                        msHashFunc = &sMinGpuProgramChangeHashFunc;
110                        break;
111                }
112        }
113    //-----------------------------------------------------------------------------
114        Pass::Pass(Technique* parent, unsigned short index)
115        : mParent(parent)
116                , mIndex(index)
117                , mHash(0)
118                , mAmbient(ColourValue::White)
119                , mDiffuse(ColourValue::White)
120                , mSpecular(ColourValue::Black)
121                , mEmissive(ColourValue::Black)
122                , mShininess(0)
123                , mTracking(TVC_NONE)
124                , mSourceBlendFactor(SBF_ONE)
125                , mDestBlendFactor(SBF_ZERO)
126                , mDepthCheck(true)
127                , mDepthWrite(true)
128                , mDepthFunc(CMPF_LESS_EQUAL)
129                , mDepthBiasConstant(0.0f)
130                , mDepthBiasSlopeScale(0.0f)
131                , mColourWrite(true)
132                , mAlphaRejectFunc(CMPF_ALWAYS_PASS)
133                , mAlphaRejectVal(0)
134                , mCullMode(CULL_CLOCKWISE)
135                , mManualCullMode(MANUAL_CULL_BACK)
136                , mLightingEnabled(true)
137                , mMaxSimultaneousLights(OGRE_MAX_SIMULTANEOUS_LIGHTS)
138                , mStartLight(0)
139                , mIteratePerLight(false)
140                , mLightsPerIteration(1)
141                , mRunOnlyForOneLightType(false)
142                , mOnlyLightType(Light::LT_POINT)
143                , mShadeOptions(SO_GOURAUD)
144                , mPolygonMode(PM_SOLID)
145                , mFogOverride(false)
146                , mFogMode(FOG_NONE)
147                , mFogColour(ColourValue::White)
148                , mFogStart(0.0)
149                , mFogEnd(1.0)
150                , mFogDensity(0.001)
151                , mVertexProgramUsage(0)
152                , mShadowCasterVertexProgramUsage(0)
153                , mShadowReceiverVertexProgramUsage(0)
154                , mFragmentProgramUsage(0)
155                , mShadowReceiverFragmentProgramUsage(0)
156                , mQueuedForDeletion(false)
157                , mPassIterationCount(1)
158                , mPointSize(1.0f)
159                , mPointMinSize(0.0f)
160                , mPointMaxSize(0.0f)
161                , mPointSpritesEnabled(false)
162                , mPointAttenuationEnabled(false)
163                , mContentTypeLookupBuilt(false)
164    {
165                mPointAttenuationCoeffs[0] = 1.0f;
166                mPointAttenuationCoeffs[1] = mPointAttenuationCoeffs[2] = 0.0f;
167
168        // default name to index
169        mName = StringConverter::toString(mIndex);
170
171        _dirtyHash();
172   }
173
174    //-----------------------------------------------------------------------------
175        Pass::Pass(Technique *parent, unsigned short index, const Pass& oth)
176        :mParent(parent), mIndex(index), mQueuedForDeletion(false), mPassIterationCount(1)
177    {
178        *this = oth;
179        mParent = parent;
180        mIndex = index;
181        mQueuedForDeletion = false;
182        _dirtyHash();
183    }
184    //-----------------------------------------------------------------------------
185    Pass::~Pass()
186    {
187
188    }
189    //-----------------------------------------------------------------------------
190    Pass& Pass::operator=(const Pass& oth)
191    {
192        mName = oth.mName;
193        mHash = oth.mHash;
194            mAmbient = oth.mAmbient;
195        mDiffuse = oth.mDiffuse;
196            mSpecular = oth.mSpecular;
197        mEmissive = oth.mEmissive;
198            mShininess = oth.mShininess;
199        mTracking = oth.mTracking;
200
201        // Copy fog parameters
202        mFogOverride = oth.mFogOverride;
203        mFogMode = oth.mFogMode;
204        mFogColour = oth.mFogColour;
205        mFogStart = oth.mFogStart;
206        mFogEnd = oth.mFogEnd;
207        mFogDensity = oth.mFogDensity;
208
209            // Default blending (overwrite)
210            mSourceBlendFactor = oth.mSourceBlendFactor;
211            mDestBlendFactor = oth.mDestBlendFactor;
212
213            mDepthCheck = oth.mDepthCheck;
214            mDepthWrite = oth.mDepthWrite;
215                mAlphaRejectFunc = oth.mAlphaRejectFunc;
216                mAlphaRejectVal = oth.mAlphaRejectVal;
217        mColourWrite = oth.mColourWrite;
218            mDepthFunc = oth.mDepthFunc;
219        mDepthBiasConstant = oth.mDepthBiasConstant;
220                mDepthBiasSlopeScale = oth.mDepthBiasSlopeScale;
221            mCullMode = oth.mCullMode;
222            mManualCullMode = oth.mManualCullMode;
223            mLightingEnabled = oth.mLightingEnabled;
224        mMaxSimultaneousLights = oth.mMaxSimultaneousLights;
225                mStartLight = oth.mStartLight;
226                mIteratePerLight = oth.mIteratePerLight;
227                mLightsPerIteration = oth.mLightsPerIteration;
228        mRunOnlyForOneLightType = oth.mRunOnlyForOneLightType;
229        mOnlyLightType = oth.mOnlyLightType;
230            mShadeOptions = oth.mShadeOptions;
231                mPolygonMode = oth.mPolygonMode;
232        mPassIterationCount = oth.mPassIterationCount;
233                mPointSize = oth.mPointSize;
234                mPointMinSize = oth.mPointMinSize;
235                mPointMaxSize = oth.mPointMaxSize;
236                mPointSpritesEnabled = oth.mPointSpritesEnabled;
237                mPointAttenuationEnabled = oth.mPointAttenuationEnabled;
238                memcpy(mPointAttenuationCoeffs, oth.mPointAttenuationCoeffs, sizeof(Real)*3);
239                mShadowContentTypeLookup = oth.mShadowContentTypeLookup;
240                mContentTypeLookupBuilt = oth.mContentTypeLookupBuilt;
241
242
243                if (oth.mVertexProgramUsage)
244                {
245                        mVertexProgramUsage = new GpuProgramUsage(*(oth.mVertexProgramUsage));
246                }
247                else
248                {
249                    mVertexProgramUsage = NULL;
250                }
251        if (oth.mShadowCasterVertexProgramUsage)
252        {
253            mShadowCasterVertexProgramUsage = new GpuProgramUsage(*(oth.mShadowCasterVertexProgramUsage));
254        }
255        else
256        {
257            mShadowCasterVertexProgramUsage = NULL;
258        }
259        if (oth.mShadowReceiverVertexProgramUsage)
260        {
261            mShadowReceiverVertexProgramUsage = new GpuProgramUsage(*(oth.mShadowReceiverVertexProgramUsage));
262        }
263        else
264        {
265            mShadowReceiverVertexProgramUsage = NULL;
266        }
267                if (oth.mFragmentProgramUsage)
268                {
269                    mFragmentProgramUsage = new GpuProgramUsage(*(oth.mFragmentProgramUsage));
270        }
271        else
272        {
273                    mFragmentProgramUsage = NULL;
274        }
275                if (oth.mShadowReceiverFragmentProgramUsage)
276                {
277                        mShadowReceiverFragmentProgramUsage = new GpuProgramUsage(*(oth.mShadowReceiverFragmentProgramUsage));
278                }
279                else
280                {
281                        mShadowReceiverFragmentProgramUsage = NULL;
282                }
283
284                TextureUnitStates::const_iterator i, iend;
285
286        // Clear texture units but doesn't notify need recompilation in the case
287        // we are cloning, The parent material will take care of this.
288        iend = mTextureUnitStates.end();
289        for (i = mTextureUnitStates.begin(); i != iend; ++i)
290        {
291            delete *i;
292        }
293
294        mTextureUnitStates.clear();
295
296                // Copy texture units
297                iend = oth.mTextureUnitStates.end();
298                for (i = oth.mTextureUnitStates.begin(); i != iend; ++i)
299                {
300                        TextureUnitState* t = new TextureUnitState(this, *(*i));
301                        mTextureUnitStates.push_back(t);
302                }
303
304        _dirtyHash();
305
306                return *this;
307    }
308    //-----------------------------------------------------------------------
309    void Pass::setName(const String& name)
310    {
311        mName = name;
312    }
313    //-----------------------------------------------------------------------
314    void Pass::setPointSize(Real ps)
315    {
316            mPointSize = ps;
317    }
318    //-----------------------------------------------------------------------
319        void Pass::setPointSpritesEnabled(bool enabled)
320        {
321                mPointSpritesEnabled = enabled;
322        }
323    //-----------------------------------------------------------------------
324        bool Pass::getPointSpritesEnabled(void) const
325        {
326                return mPointSpritesEnabled;
327        }
328    //-----------------------------------------------------------------------
329        void Pass::setPointAttenuation(bool enabled,
330                Real constant, Real linear, Real quadratic)
331        {
332                mPointAttenuationEnabled = enabled;
333                mPointAttenuationCoeffs[0] = constant;
334                mPointAttenuationCoeffs[1] = linear;
335                mPointAttenuationCoeffs[2] = quadratic;
336        }
337    //-----------------------------------------------------------------------
338        bool Pass::isPointAttenuationEnabled(void) const
339        {
340                return mPointAttenuationEnabled;
341        }
342    //-----------------------------------------------------------------------
343        Real Pass::getPointAttenuationConstant(void) const
344        {
345                return mPointAttenuationCoeffs[0];
346        }
347    //-----------------------------------------------------------------------
348        Real Pass::getPointAttenuationLinear(void) const
349        {
350                return mPointAttenuationCoeffs[1];
351        }
352    //-----------------------------------------------------------------------
353        Real Pass::getPointAttenuationQuadratic(void) const
354        {
355                return mPointAttenuationCoeffs[2];
356        }
357    //-----------------------------------------------------------------------
358        void Pass::setPointMinSize(Real min)
359        {
360                mPointMinSize = min;
361        }
362    //-----------------------------------------------------------------------
363        Real Pass::getPointMinSize(void) const
364        {
365                return mPointMinSize;
366        }
367    //-----------------------------------------------------------------------
368        void Pass::setPointMaxSize(Real max)
369        {
370                mPointMaxSize = max;
371        }
372    //-----------------------------------------------------------------------
373        Real Pass::getPointMaxSize(void) const
374        {
375                return mPointMaxSize;
376        }
377    //-----------------------------------------------------------------------
378    void Pass::setAmbient(Real red, Real green, Real blue)
379    {
380            mAmbient.r = red;
381            mAmbient.g = green;
382            mAmbient.b = blue;
383
384    }
385    //-----------------------------------------------------------------------
386    void Pass::setAmbient(const ColourValue& ambient)
387    {
388            mAmbient = ambient;
389    }
390    //-----------------------------------------------------------------------
391    void Pass::setDiffuse(Real red, Real green, Real blue, Real alpha)
392    {
393            mDiffuse.r = red;
394            mDiffuse.g = green;
395            mDiffuse.b = blue;
396                mDiffuse.a = alpha;
397    }
398    //-----------------------------------------------------------------------
399    void Pass::setDiffuse(const ColourValue& diffuse)
400    {
401            mDiffuse = diffuse;
402    }
403    //-----------------------------------------------------------------------
404    void Pass::setSpecular(Real red, Real green, Real blue, Real alpha)
405    {
406            mSpecular.r = red;
407            mSpecular.g = green;
408            mSpecular.b = blue;
409                mSpecular.a = alpha;
410    }
411    //-----------------------------------------------------------------------
412    void Pass::setSpecular(const ColourValue& specular)
413    {
414            mSpecular = specular;
415    }
416    //-----------------------------------------------------------------------
417    void Pass::setShininess(Real val)
418    {
419            mShininess = val;
420    }
421    //-----------------------------------------------------------------------
422    void Pass::setSelfIllumination(Real red, Real green, Real blue)
423    {
424            mEmissive.r = red;
425            mEmissive.g = green;
426            mEmissive.b = blue;
427
428    }
429    //-----------------------------------------------------------------------
430    void Pass::setSelfIllumination(const ColourValue& selfIllum)
431    {
432            mEmissive = selfIllum;
433    }
434    //-----------------------------------------------------------------------
435    void Pass::setVertexColourTracking(TrackVertexColourType tracking)
436    {
437        mTracking = tracking;
438    }
439    //-----------------------------------------------------------------------
440    Real Pass::getPointSize(void) const
441    {
442            return mPointSize;
443    }
444    //-----------------------------------------------------------------------
445    const ColourValue& Pass::getAmbient(void) const
446    {
447            return mAmbient;
448    }
449    //-----------------------------------------------------------------------
450    const ColourValue& Pass::getDiffuse(void) const
451    {
452            return mDiffuse;
453    }
454    //-----------------------------------------------------------------------
455    const ColourValue& Pass::getSpecular(void) const
456    {
457            return mSpecular;
458    }
459    //-----------------------------------------------------------------------
460    const ColourValue& Pass::getSelfIllumination(void) const
461    {
462            return mEmissive;
463    }
464    //-----------------------------------------------------------------------
465    Real Pass::getShininess(void) const
466    {
467            return mShininess;
468    }
469    //-----------------------------------------------------------------------
470    TrackVertexColourType Pass::getVertexColourTracking(void) const
471    {
472        return mTracking;
473    }
474    //-----------------------------------------------------------------------
475    TextureUnitState* Pass::createTextureUnitState(void)
476    {
477        TextureUnitState *t = new TextureUnitState(this);
478        addTextureUnitState(t);
479                mContentTypeLookupBuilt = false;
480            return t;
481    }
482    //-----------------------------------------------------------------------
483    TextureUnitState* Pass::createTextureUnitState(
484        const String& textureName, unsigned short texCoordSet)
485    {
486        TextureUnitState *t = new TextureUnitState(this);
487            t->setTextureName(textureName);
488            t->setTextureCoordSet(texCoordSet);
489        addTextureUnitState(t);
490                mContentTypeLookupBuilt = false;
491            return t;
492    }
493    //-----------------------------------------------------------------------
494        void Pass::addTextureUnitState(TextureUnitState* state)
495        {
496        assert(state && "state is 0 in Pass::addTextureUnitState()");
497        if (state)
498        {
499            // only attach TUS to pass if TUS does not belong to another pass
500            if ((state->getParent() == 0) || (state->getParent() == this))
501            {
502                        mTextureUnitStates.push_back(state);
503                                // Notify state
504                                state->_notifyParent(this);
505                // if texture unit state name is empty then give it a default name based on its index
506                if (state->getName().empty())
507                {
508                    // its the last entry in the container so its index is size - 1
509                    size_t idx = mTextureUnitStates.size() - 1;
510                    state->setName( StringConverter::toString(idx) );
511                    /** since the name was never set and a default one has been made, clear the alias name
512                     so that when the texture unit name is set by the user, the alias name will be set to
513                     that name
514                    */
515                    state->setTextureNameAlias(StringUtil::BLANK);
516                }
517                // Needs recompilation
518                mParent->_notifyNeedsRecompile();
519                _dirtyHash();
520            }
521            else
522            {
523                            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState already attached to another pass",
524                                    "Pass:addTextureUnitState");
525
526            }
527                        mContentTypeLookupBuilt = false;
528        }
529        }
530    //-----------------------------------------------------------------------
531    TextureUnitState* Pass::getTextureUnitState(unsigned short index)
532    {
533        assert (index < mTextureUnitStates.size() && "Index out of bounds");
534            return mTextureUnitStates[index];
535    }
536    //-----------------------------------------------------------------------------
537    TextureUnitState* Pass::getTextureUnitState(const String& name)
538    {
539        TextureUnitStates::iterator i    = mTextureUnitStates.begin();
540        TextureUnitStates::iterator iend = mTextureUnitStates.end();
541        TextureUnitState* foundTUS = 0;
542
543        // iterate through TUS Container to find a match
544        while (i != iend)
545        {
546            if ( (*i)->getName() == name )
547            {
548                foundTUS = (*i);
549                break;
550            }
551
552            ++i;
553        }
554
555        return foundTUS;
556    }
557        //-----------------------------------------------------------------------
558        const TextureUnitState* Pass::getTextureUnitState(unsigned short index) const
559        {
560                assert (index < mTextureUnitStates.size() && "Index out of bounds");
561                return mTextureUnitStates[index];
562        }
563        //-----------------------------------------------------------------------------
564        const TextureUnitState* Pass::getTextureUnitState(const String& name) const
565        {
566                TextureUnitStates::const_iterator i    = mTextureUnitStates.begin();
567                TextureUnitStates::const_iterator iend = mTextureUnitStates.end();
568                const TextureUnitState* foundTUS = 0;
569
570                // iterate through TUS Container to find a match
571                while (i != iend)
572                {
573                        if ( (*i)->getName() == name )
574                        {
575                                foundTUS = (*i);
576                                break;
577                        }
578
579                        ++i;
580                }
581
582                return foundTUS;
583        }
584
585    //-----------------------------------------------------------------------
586    unsigned short Pass::getTextureUnitStateIndex(const TextureUnitState* state) const
587    {
588        assert(state && "state is 0 in Pass::getTextureUnitStateIndex()");
589
590        // only find index for state attached to this pass
591        if (state->getParent() == this)
592        {
593            TextureUnitStates::const_iterator i =
594                std::find(mTextureUnitStates.begin(), mTextureUnitStates.end(), state);
595            assert(i != mTextureUnitStates.end() && "state is supposed to attached to this pass");
596            return static_cast<unsigned short>(std::distance(mTextureUnitStates.begin(), i));
597        }
598        else
599        {
600                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState is not attached to this pass",
601                                "Pass:getTextureUnitStateIndex");
602        }
603    }
604
605    //-----------------------------------------------------------------------
606    Pass::TextureUnitStateIterator
607        Pass::getTextureUnitStateIterator(void)
608    {
609        return TextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
610    }
611        //-----------------------------------------------------------------------
612        Pass::ConstTextureUnitStateIterator
613                Pass::getTextureUnitStateIterator(void) const
614        {
615                return ConstTextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
616        }
617    //-----------------------------------------------------------------------
618    void Pass::removeTextureUnitState(unsigned short index)
619    {
620        assert (index < mTextureUnitStates.size() && "Index out of bounds");
621
622        TextureUnitStates::iterator i = mTextureUnitStates.begin() + index;
623        delete *i;
624            mTextureUnitStates.erase(i);
625        if (!mQueuedForDeletion)
626        {
627            // Needs recompilation
628            mParent->_notifyNeedsRecompile();
629        }
630        _dirtyHash();
631                mContentTypeLookupBuilt = false;
632    }
633    //-----------------------------------------------------------------------
634    void Pass::removeAllTextureUnitStates(void)
635    {
636        TextureUnitStates::iterator i, iend;
637        iend = mTextureUnitStates.end();
638        for (i = mTextureUnitStates.begin(); i != iend; ++i)
639        {
640            delete *i;
641        }
642        mTextureUnitStates.clear();
643        if (!mQueuedForDeletion)
644        {
645            // Needs recompilation
646            mParent->_notifyNeedsRecompile();
647        }
648        _dirtyHash();
649                mContentTypeLookupBuilt = false;
650    }
651    //-----------------------------------------------------------------------
652    void Pass::setSceneBlending(SceneBlendType sbt)
653    {
654            // Turn predefined type into blending factors
655            switch (sbt)
656            {
657            case SBT_TRANSPARENT_ALPHA:
658                    setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);
659                    break;
660            case SBT_TRANSPARENT_COLOUR:
661                    setSceneBlending(SBF_SOURCE_COLOUR, SBF_ONE_MINUS_SOURCE_COLOUR);
662                    break;
663                case SBT_MODULATE:
664                        setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
665                        break;
666            case SBT_ADD:
667                    setSceneBlending(SBF_ONE, SBF_ONE);
668                    break;
669        case SBT_REPLACE:
670            setSceneBlending(SBF_ONE, SBF_ZERO);
671            break;
672            // TODO: more
673            }
674
675    }
676    //-----------------------------------------------------------------------
677    void Pass::setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
678    {
679            mSourceBlendFactor = sourceFactor;
680            mDestBlendFactor = destFactor;
681    }
682    //-----------------------------------------------------------------------
683    SceneBlendFactor Pass::getSourceBlendFactor(void) const
684    {
685            return mSourceBlendFactor;
686    }
687    //-----------------------------------------------------------------------
688    SceneBlendFactor Pass::getDestBlendFactor(void) const
689    {
690            return mDestBlendFactor;
691    }
692    //-----------------------------------------------------------------------
693    bool Pass::isTransparent(void) const
694    {
695                // Transparent if any of the destination colour is taken into account
696                if (mDestBlendFactor == SBF_ZERO &&
697                        mSourceBlendFactor != SBF_DEST_COLOUR &&
698                        mSourceBlendFactor != SBF_ONE_MINUS_DEST_COLOUR &&
699                        mSourceBlendFactor != SBF_DEST_ALPHA &&
700                        mSourceBlendFactor != SBF_ONE_MINUS_DEST_ALPHA)
701                {
702                    return false;
703                }
704            else
705                {
706                    return true;
707                }
708    }
709    //-----------------------------------------------------------------------
710    void Pass::setDepthCheckEnabled(bool enabled)
711    {
712            mDepthCheck = enabled;
713    }
714    //-----------------------------------------------------------------------
715    bool Pass::getDepthCheckEnabled(void) const
716    {
717            return mDepthCheck;
718    }
719    //-----------------------------------------------------------------------
720    void Pass::setDepthWriteEnabled(bool enabled)
721    {
722            mDepthWrite = enabled;
723    }
724    //-----------------------------------------------------------------------
725    bool Pass::getDepthWriteEnabled(void) const
726    {
727            return mDepthWrite;
728    }
729    //-----------------------------------------------------------------------
730    void Pass::setDepthFunction( CompareFunction func)
731    {
732            mDepthFunc = func;
733    }
734    //-----------------------------------------------------------------------
735    CompareFunction Pass::getDepthFunction(void) const
736    {
737            return mDepthFunc;
738    }
739        //-----------------------------------------------------------------------
740        void Pass::setAlphaRejectSettings(CompareFunction func, unsigned char value)
741        {
742                mAlphaRejectFunc = func;
743                mAlphaRejectVal = value;
744        }
745        //-----------------------------------------------------------------------
746        void Pass::setAlphaRejectFunction(CompareFunction func)
747        {
748                mAlphaRejectFunc = func;
749        }
750        //-----------------------------------------------------------------------
751        void Pass::setAlphaRejectValue(unsigned char val)
752        {
753                mAlphaRejectVal = val;
754        }
755    //-----------------------------------------------------------------------
756        void Pass::setColourWriteEnabled(bool enabled)
757        {
758                mColourWrite = enabled;
759        }
760    //-----------------------------------------------------------------------
761        bool Pass::getColourWriteEnabled(void) const
762        {
763                return mColourWrite;
764        }
765    //-----------------------------------------------------------------------
766    void Pass::setCullingMode( CullingMode mode)
767    {
768            mCullMode = mode;
769    }
770    //-----------------------------------------------------------------------
771    CullingMode Pass::getCullingMode(void) const
772    {
773            return mCullMode;
774    }
775    //-----------------------------------------------------------------------
776    void Pass::setLightingEnabled(bool enabled)
777    {
778            mLightingEnabled = enabled;
779    }
780    //-----------------------------------------------------------------------
781    bool Pass::getLightingEnabled(void) const
782    {
783            return mLightingEnabled;
784    }
785    //-----------------------------------------------------------------------
786    void Pass::setMaxSimultaneousLights(unsigned short maxLights)
787    {
788        mMaxSimultaneousLights = maxLights;
789    }
790    //-----------------------------------------------------------------------
791    unsigned short Pass::getMaxSimultaneousLights(void) const
792    {
793        return mMaxSimultaneousLights;
794    }
795        //-----------------------------------------------------------------------
796        void Pass::setStartLight(unsigned short startLight)
797        {
798                mStartLight = startLight;
799        }
800        //-----------------------------------------------------------------------
801        unsigned short Pass::getStartLight(void) const
802        {
803                return mStartLight;
804        }
805        //-----------------------------------------------------------------------
806        void Pass::setLightCountPerIteration(unsigned short c)
807        {
808                mLightsPerIteration = c;
809        }
810        //-----------------------------------------------------------------------
811        unsigned short Pass::getLightCountPerIteration(void) const
812        {
813                return mLightsPerIteration;
814        }
815    //-----------------------------------------------------------------------
816    void Pass::setIteratePerLight(bool enabled,
817            bool onlyForOneLightType, Light::LightTypes lightType)
818    {
819        mIteratePerLight = enabled;
820        mRunOnlyForOneLightType = onlyForOneLightType;
821        mOnlyLightType = lightType;
822    }
823    //-----------------------------------------------------------------------
824    void Pass::setShadingMode(ShadeOptions mode)
825    {
826            mShadeOptions = mode;
827    }
828    //-----------------------------------------------------------------------
829    ShadeOptions Pass::getShadingMode(void) const
830    {
831            return mShadeOptions;
832    }
833        //-----------------------------------------------------------------------
834        void Pass::setPolygonMode(PolygonMode mode)
835        {
836                mPolygonMode = mode;
837        }
838        //-----------------------------------------------------------------------
839        PolygonMode Pass::getPolygonMode(void) const
840        {
841                return mPolygonMode;
842        }
843    //-----------------------------------------------------------------------
844    void Pass::setManualCullingMode(ManualCullingMode mode)
845    {
846            mManualCullMode = mode;
847    }
848    //-----------------------------------------------------------------------
849    ManualCullingMode Pass::getManualCullingMode(void) const
850    {
851            return mManualCullMode;
852    }
853    //-----------------------------------------------------------------------
854    void Pass::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
855    {
856            mFogOverride = overrideScene;
857            if (overrideScene)
858            {
859                    mFogMode = mode;
860                    mFogColour = colour;
861                    mFogStart = start;
862                    mFogEnd = end;
863                    mFogDensity = density;
864            }
865    }
866    //-----------------------------------------------------------------------
867    bool Pass::getFogOverride(void) const
868    {
869            return mFogOverride;
870    }
871    //-----------------------------------------------------------------------
872    FogMode Pass::getFogMode(void) const
873    {
874            return mFogMode;
875    }
876    //-----------------------------------------------------------------------
877    const ColourValue& Pass::getFogColour(void) const
878    {
879            return mFogColour;
880    }
881    //-----------------------------------------------------------------------
882    Real Pass::getFogStart(void) const
883    {
884            return mFogStart;
885    }
886    //-----------------------------------------------------------------------
887    Real Pass::getFogEnd(void) const
888    {
889            return mFogEnd;
890    }
891    //-----------------------------------------------------------------------
892    Real Pass::getFogDensity(void) const
893    {
894            return mFogDensity;
895    }
896    //-----------------------------------------------------------------------
897    void Pass::setDepthBias(float constantBias, float slopeScaleBias)
898    {
899       mDepthBiasConstant = constantBias;
900           mDepthBiasSlopeScale = slopeScaleBias;
901    }
902    //-----------------------------------------------------------------------
903    float Pass::getDepthBiasConstant(void) const
904    {
905        return mDepthBiasConstant;
906    }
907        //-----------------------------------------------------------------------
908        float Pass::getDepthBiasSlopeScale(void) const
909        {
910                return mDepthBiasSlopeScale;
911        }
912    //-----------------------------------------------------------------------
913        Pass* Pass::_split(unsigned short numUnits)
914        {
915                if (mVertexProgramUsage || mFragmentProgramUsage)
916                {
917                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Programmable passes cannot be "
918                                "automatically split, define a fallback technique instead.",
919                                "Pass:_split");
920                }
921
922                if (mTextureUnitStates.size() > numUnits)
923                {
924                        size_t start = mTextureUnitStates.size() - numUnits;
925
926                        Pass* newPass = mParent->createPass();
927
928                        TextureUnitStates::iterator istart, i, iend;
929                        iend = mTextureUnitStates.end();
930                        i = istart = mTextureUnitStates.begin() + start;
931                        // Set the new pass to fallback using scene blend
932                        newPass->setSceneBlending(
933                                (*i)->getColourBlendFallbackSrc(), (*i)->getColourBlendFallbackDest());
934                        // Fixup the texture unit 0   of new pass   blending method   to replace
935                        // all colour and alpha   with texture without adjustment, because we
936                        // assume it's detail texture.
937                        (*i)->setColourOperationEx(LBX_SOURCE1,   LBS_TEXTURE, LBS_CURRENT);
938                        (*i)->setAlphaOperation(LBX_SOURCE1, LBS_TEXTURE, LBS_CURRENT);
939
940                        // Add all the other texture unit states
941                        for (; i != iend; ++i)
942                        {
943                                // detach from parent first
944                                (*i)->_notifyParent(0);
945                                newPass->addTextureUnitState(*i);
946                        }
947                        // Now remove texture units from this Pass, we don't need to delete since they've
948                        // been transferred
949                        mTextureUnitStates.erase(istart, iend);
950                        _dirtyHash();
951                        mContentTypeLookupBuilt = false;
952                        return newPass;
953                }
954                return NULL;
955        }
956        //-----------------------------------------------------------------------------
957        void Pass::_notifyIndex(unsigned short index)
958        {
959                if (mIndex != index)
960                {
961                        mIndex = index;
962                        _dirtyHash();
963                }
964        }
965    //-----------------------------------------------------------------------
966        void Pass::_load(void)
967        {
968                // We assume the Technique only calls this when the material is being
969                // loaded
970
971                // Load each TextureUnitState
972                TextureUnitStates::iterator i, iend;
973                iend = mTextureUnitStates.end();
974                for (i = mTextureUnitStates.begin(); i != iend; ++i)
975                {
976                        (*i)->_load();
977                }
978
979                // Load programs
980                if (mVertexProgramUsage)
981                {
982                        // Load vertex program
983            mVertexProgramUsage->_load();
984        }
985        if (mShadowCasterVertexProgramUsage)
986        {
987            // Load vertex program
988            mShadowCasterVertexProgramUsage->_load();
989        }
990        if (mShadowReceiverVertexProgramUsage)
991        {
992            // Load vertex program
993            mShadowReceiverVertexProgramUsage->_load();
994        }
995
996        if (mFragmentProgramUsage)
997        {
998                        // Load fragment program
999            mFragmentProgramUsage->_load();
1000                }
1001                if (mShadowReceiverFragmentProgramUsage)
1002                {
1003                        // Load Fragment program
1004                        mShadowReceiverFragmentProgramUsage->_load();
1005                }
1006
1007        }
1008    //-----------------------------------------------------------------------
1009        void Pass::_unload(void)
1010        {
1011                // Unload each TextureUnitState
1012                TextureUnitStates::iterator i, iend;
1013                iend = mTextureUnitStates.end();
1014                for (i = mTextureUnitStates.begin(); i != iend; ++i)
1015                {
1016                        (*i)->_unload();
1017                }
1018
1019                // Unload programs
1020                if (mVertexProgramUsage)
1021                {
1022                        // TODO
1023                }
1024        if (mFragmentProgramUsage)
1025        {
1026            // TODO
1027        }
1028        }
1029    //-----------------------------------------------------------------------
1030        void Pass::setVertexProgram(const String& name, bool resetParams)
1031        {
1032        // Turn off vertex program if name blank
1033        if (name.empty())
1034        {
1035            if (mVertexProgramUsage) delete mVertexProgramUsage;
1036            mVertexProgramUsage = NULL;
1037        }
1038        else
1039        {
1040            if (!mVertexProgramUsage)
1041            {
1042                mVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
1043            }
1044                    mVertexProgramUsage->setProgramName(name, resetParams);
1045        }
1046        // Needs recompilation
1047        mParent->_notifyNeedsRecompile();
1048        }
1049    //-----------------------------------------------------------------------
1050        void Pass::setVertexProgramParameters(GpuProgramParametersSharedPtr params)
1051        {
1052                if (!mVertexProgramUsage)
1053        {
1054            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1055                "This pass does not have a vertex program assigned!",
1056                "Pass::setVertexProgramParameters");
1057        }
1058                mVertexProgramUsage->setParameters(params);
1059        }
1060    //-----------------------------------------------------------------------
1061        void Pass::setFragmentProgram(const String& name, bool resetParams)
1062        {
1063        // Turn off fragment program if name blank
1064        if (name.empty())
1065        {
1066            if (mFragmentProgramUsage) delete mFragmentProgramUsage;
1067            mFragmentProgramUsage = NULL;
1068        }
1069        else
1070        {
1071            if (!mFragmentProgramUsage)
1072            {
1073                mFragmentProgramUsage = new GpuProgramUsage(GPT_FRAGMENT_PROGRAM);
1074            }
1075                    mFragmentProgramUsage->setProgramName(name, resetParams);
1076        }
1077        // Needs recompilation
1078        mParent->_notifyNeedsRecompile();
1079        }
1080    //-----------------------------------------------------------------------
1081        void Pass::setFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1082        {
1083                if (!mFragmentProgramUsage)
1084        {
1085            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1086                "This pass does not have a fragment program assigned!",
1087                "Pass::setFragmentProgramParameters");
1088        }
1089                mFragmentProgramUsage->setParameters(params);
1090        }
1091        //-----------------------------------------------------------------------
1092        const String& Pass::getVertexProgramName(void) const
1093        {
1094        if (!mVertexProgramUsage)
1095            return StringUtil::BLANK;
1096        else
1097                    return mVertexProgramUsage->getProgramName();
1098        }
1099        //-----------------------------------------------------------------------
1100        GpuProgramParametersSharedPtr Pass::getVertexProgramParameters(void) const
1101        {
1102                if (!mVertexProgramUsage)
1103        {
1104            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1105                "This pass does not have a vertex program assigned!",
1106                "Pass::getVertexProgramParameters");
1107        }
1108                return mVertexProgramUsage->getParameters();
1109        }
1110        //-----------------------------------------------------------------------
1111        const GpuProgramPtr& Pass::getVertexProgram(void) const
1112        {
1113                return mVertexProgramUsage->getProgram();
1114        }
1115        //-----------------------------------------------------------------------
1116        const String& Pass::getFragmentProgramName(void) const
1117        {
1118        if (!mFragmentProgramUsage)
1119            return StringUtil::BLANK;
1120        else
1121                return mFragmentProgramUsage->getProgramName();
1122        }
1123        //-----------------------------------------------------------------------
1124        GpuProgramParametersSharedPtr Pass::getFragmentProgramParameters(void) const
1125        {
1126                return mFragmentProgramUsage->getParameters();
1127        }
1128        //-----------------------------------------------------------------------
1129        const GpuProgramPtr& Pass::getFragmentProgram(void) const
1130        {
1131                return mFragmentProgramUsage->getProgram();
1132        }
1133        //-----------------------------------------------------------------------
1134    bool Pass::isLoaded(void) const
1135    {
1136        return mParent->isLoaded();
1137    }
1138        //-----------------------------------------------------------------------
1139    void Pass::_recalculateHash(void)
1140    {
1141        /* Hash format is 32-bit, divided as follows (high to low bits)
1142           bits   purpose
1143            4     Pass index (i.e. max 16 passes!)
1144           14     Hashed texture name from unit 0
1145           14     Hashed texture name from unit 1
1146
1147           Note that at the moment we don't sort on the 3rd texture unit plus
1148           on the assumption that these are less frequently used; sorting on
1149           the first 2 gives us the most benefit for now.
1150       */
1151        mHash = (*msHashFunc)(this);
1152    }
1153    //-----------------------------------------------------------------------
1154        void Pass::_dirtyHash(void)
1155        {
1156                OGRE_LOCK_MUTEX(msDirtyHashListMutex)
1157                // Mark this hash as for follow up
1158                msDirtyHashList.insert(this);
1159        }
1160        //---------------------------------------------------------------------
1161        void Pass::clearDirtyHashList(void) 
1162        { 
1163                OGRE_LOCK_MUTEX(msDirtyHashListMutex)
1164                msDirtyHashList.clear(); 
1165        }
1166    //-----------------------------------------------------------------------
1167    void Pass::_notifyNeedsRecompile(void)
1168    {
1169        mParent->_notifyNeedsRecompile();
1170    }
1171    //-----------------------------------------------------------------------
1172    void Pass::setTextureFiltering(TextureFilterOptions filterType)
1173    {
1174        TextureUnitStates::iterator i, iend;
1175        iend = mTextureUnitStates.end();
1176        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1177        {
1178            (*i)->setTextureFiltering(filterType);
1179        }
1180    }
1181    // --------------------------------------------------------------------
1182    void Pass::setTextureAnisotropy(unsigned int maxAniso)
1183    {
1184        TextureUnitStates::iterator i, iend;
1185        iend = mTextureUnitStates.end();
1186        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1187        {
1188            (*i)->setTextureAnisotropy(maxAniso);
1189        }
1190    }
1191    //-----------------------------------------------------------------------
1192    void Pass::_updateAutoParamsNoLights(const AutoParamDataSource& source) const
1193    {
1194        if (hasVertexProgram())
1195        {
1196            // Update vertex program auto params
1197            mVertexProgramUsage->getParameters()->_updateAutoParamsNoLights(source);
1198        }
1199
1200        if (hasFragmentProgram())
1201        {
1202            // Update fragment program auto params
1203            mFragmentProgramUsage->getParameters()->_updateAutoParamsNoLights(source);
1204        }
1205    }
1206    //-----------------------------------------------------------------------
1207    void Pass::_updateAutoParamsLightsOnly(const AutoParamDataSource& source) const
1208    {
1209        if (hasVertexProgram())
1210        {
1211            // Update vertex program auto params
1212            mVertexProgramUsage->getParameters()->_updateAutoParamsLightsOnly(source);
1213        }
1214
1215        if (hasFragmentProgram())
1216        {
1217            // Update fragment program auto params
1218            mFragmentProgramUsage->getParameters()->_updateAutoParamsLightsOnly(source);
1219        }
1220    }
1221    //-----------------------------------------------------------------------
1222    void Pass::processPendingPassUpdates(void)
1223    {
1224                {
1225                        OGRE_LOCK_MUTEX(msPassGraveyardMutex)
1226                        // Delete items in the graveyard
1227                        PassSet::iterator i, iend;
1228                        iend = msPassGraveyard.end();
1229                        for (i = msPassGraveyard.begin(); i != iend; ++i)
1230                        {
1231                                delete *i;
1232                        }
1233                        msPassGraveyard.clear();
1234                }
1235
1236                {
1237                        OGRE_LOCK_MUTEX(msDirtyHashListMutex)
1238                        PassSet::iterator i, iend;
1239                        // The dirty ones will have been removed from the groups above using the old hash now
1240                        iend = msDirtyHashList.end();
1241                        for (i = msDirtyHashList.begin(); i != iend; ++i)
1242                        {
1243                                Pass* p = *i;
1244                                p->_recalculateHash();
1245                        }
1246                        // Clear the dirty list
1247                        msDirtyHashList.clear();
1248                }
1249    }
1250    //-----------------------------------------------------------------------
1251    void Pass::queueForDeletion(void)
1252    {
1253        mQueuedForDeletion = true;
1254
1255        removeAllTextureUnitStates();
1256        if (mVertexProgramUsage)
1257        {
1258            delete mVertexProgramUsage;
1259            mVertexProgramUsage = 0;
1260        }
1261        if (mShadowCasterVertexProgramUsage)
1262        {
1263            delete mShadowCasterVertexProgramUsage;
1264            mShadowCasterVertexProgramUsage = 0;
1265        }
1266        if (mShadowReceiverVertexProgramUsage)
1267        {
1268            delete mShadowReceiverVertexProgramUsage;
1269            mShadowReceiverVertexProgramUsage = 0;
1270        }
1271        if (mFragmentProgramUsage)
1272        {
1273            delete mFragmentProgramUsage;
1274            mFragmentProgramUsage = 0;
1275        }
1276                if (mShadowReceiverFragmentProgramUsage)
1277                {
1278                        delete mShadowReceiverFragmentProgramUsage;
1279                        mShadowReceiverFragmentProgramUsage = 0;
1280                }
1281        // remove from dirty list, if there
1282                {
1283                        OGRE_LOCK_MUTEX(msDirtyHashListMutex)
1284                        msDirtyHashList.erase(this);
1285                }
1286                {
1287                        OGRE_LOCK_MUTEX(msPassGraveyardMutex)
1288                        msPassGraveyard.insert(this);
1289                }
1290    }
1291    //-----------------------------------------------------------------------
1292    bool Pass::isAmbientOnly(void) const
1293    {
1294        // treat as ambient if lighting is off, or colour write is off,
1295        // or all non-ambient (& emissive) colours are black
1296        // NB a vertex program could override this, but passes using vertex
1297        // programs are expected to indicate they are ambient only by
1298        // setting the state so it matches one of the conditions above, even
1299        // though this state is not used in rendering.
1300        return (!mLightingEnabled || !mColourWrite ||
1301            (mDiffuse == ColourValue::Black &&
1302             mSpecular == ColourValue::Black));
1303    }
1304    //-----------------------------------------------------------------------
1305    void Pass::setShadowCasterVertexProgram(const String& name)
1306    {
1307        // Turn off vertex program if name blank
1308        if (name.empty())
1309        {
1310            if (mShadowCasterVertexProgramUsage) delete mShadowCasterVertexProgramUsage;
1311            mShadowCasterVertexProgramUsage = NULL;
1312        }
1313        else
1314        {
1315            if (!mShadowCasterVertexProgramUsage)
1316            {
1317                mShadowCasterVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
1318            }
1319            mShadowCasterVertexProgramUsage->setProgramName(name);
1320        }
1321        // Needs recompilation
1322        mParent->_notifyNeedsRecompile();
1323    }
1324    //-----------------------------------------------------------------------
1325    void Pass::setShadowCasterVertexProgramParameters(GpuProgramParametersSharedPtr params)
1326    {
1327        if (!mShadowCasterVertexProgramUsage)
1328        {
1329            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1330                "This pass does not have a shadow caster vertex program assigned!",
1331                "Pass::setShadowCasterVertexProgramParameters");
1332        }
1333        mShadowCasterVertexProgramUsage->setParameters(params);
1334    }
1335    //-----------------------------------------------------------------------
1336    const String& Pass::getShadowCasterVertexProgramName(void) const
1337    {
1338        if (!mShadowCasterVertexProgramUsage)
1339            return StringUtil::BLANK;
1340        else
1341            return mShadowCasterVertexProgramUsage->getProgramName();
1342    }
1343    //-----------------------------------------------------------------------
1344    GpuProgramParametersSharedPtr Pass::getShadowCasterVertexProgramParameters(void) const
1345    {
1346        if (!mShadowCasterVertexProgramUsage)
1347        {
1348            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1349                "This pass does not have a shadow caster vertex program assigned!",
1350                "Pass::getShadowCasterVertexProgramParameters");
1351        }
1352        return mShadowCasterVertexProgramUsage->getParameters();
1353    }
1354    //-----------------------------------------------------------------------
1355    const GpuProgramPtr& Pass::getShadowCasterVertexProgram(void) const
1356    {
1357        return mShadowCasterVertexProgramUsage->getProgram();
1358    }
1359    //-----------------------------------------------------------------------
1360    void Pass::setShadowReceiverVertexProgram(const String& name)
1361    {
1362        // Turn off vertex program if name blank
1363        if (name.empty())
1364        {
1365            if (mShadowReceiverVertexProgramUsage) delete mShadowReceiverVertexProgramUsage;
1366            mShadowReceiverVertexProgramUsage = NULL;
1367        }
1368        else
1369        {
1370            if (!mShadowReceiverVertexProgramUsage)
1371            {
1372                mShadowReceiverVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
1373            }
1374            mShadowReceiverVertexProgramUsage->setProgramName(name);
1375        }
1376        // Needs recompilation
1377        mParent->_notifyNeedsRecompile();
1378    }
1379    //-----------------------------------------------------------------------
1380    void Pass::setShadowReceiverVertexProgramParameters(GpuProgramParametersSharedPtr params)
1381    {
1382        if (!mShadowReceiverVertexProgramUsage)
1383        {
1384            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1385                "This pass does not have a shadow receiver vertex program assigned!",
1386                "Pass::setShadowReceiverVertexProgramParameters");
1387        }
1388        mShadowReceiverVertexProgramUsage->setParameters(params);
1389    }
1390    //-----------------------------------------------------------------------
1391    const String& Pass::getShadowReceiverVertexProgramName(void) const
1392    {
1393        if (!mShadowReceiverVertexProgramUsage)
1394            return StringUtil::BLANK;
1395        else
1396            return mShadowReceiverVertexProgramUsage->getProgramName();
1397    }
1398    //-----------------------------------------------------------------------
1399    GpuProgramParametersSharedPtr Pass::getShadowReceiverVertexProgramParameters(void) const
1400    {
1401        if (!mShadowReceiverVertexProgramUsage)
1402        {
1403            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1404                "This pass does not have a shadow receiver vertex program assigned!",
1405                "Pass::getShadowReceiverVertexProgramParameters");
1406        }
1407        return mShadowReceiverVertexProgramUsage->getParameters();
1408    }
1409    //-----------------------------------------------------------------------
1410    const GpuProgramPtr& Pass::getShadowReceiverVertexProgram(void) const
1411    {
1412        return mShadowReceiverVertexProgramUsage->getProgram();
1413    }
1414        //-----------------------------------------------------------------------
1415        void Pass::setShadowReceiverFragmentProgram(const String& name)
1416        {
1417                // Turn off Fragment program if name blank
1418                if (name.empty())
1419                {
1420                        if (mShadowReceiverFragmentProgramUsage) delete mShadowReceiverFragmentProgramUsage;
1421                        mShadowReceiverFragmentProgramUsage = NULL;
1422                }
1423                else
1424                {
1425                        if (!mShadowReceiverFragmentProgramUsage)
1426                        {
1427                                mShadowReceiverFragmentProgramUsage = new GpuProgramUsage(GPT_FRAGMENT_PROGRAM);
1428                        }
1429                        mShadowReceiverFragmentProgramUsage->setProgramName(name);
1430                }
1431                // Needs recompilation
1432                mParent->_notifyNeedsRecompile();
1433        }
1434        //-----------------------------------------------------------------------
1435        void Pass::setShadowReceiverFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1436        {
1437                if (!mShadowReceiverFragmentProgramUsage)
1438                {
1439                        OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1440                                "This pass does not have a shadow receiver fragment program assigned!",
1441                                "Pass::setShadowReceiverFragmentProgramParameters");
1442                }
1443                mShadowReceiverFragmentProgramUsage->setParameters(params);
1444        }
1445        //-----------------------------------------------------------------------
1446        const String& Pass::getShadowReceiverFragmentProgramName(void) const
1447        {
1448                if (!mShadowReceiverFragmentProgramUsage)
1449                        return StringUtil::BLANK;
1450                else
1451                        return mShadowReceiverFragmentProgramUsage->getProgramName();
1452        }
1453        //-----------------------------------------------------------------------
1454        GpuProgramParametersSharedPtr Pass::getShadowReceiverFragmentProgramParameters(void) const
1455        {
1456                if (!mShadowReceiverFragmentProgramUsage)
1457                {
1458                        OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1459                                "This pass does not have a shadow receiver fragment program assigned!",
1460                                "Pass::getShadowReceiverFragmentProgramParameters");
1461                }
1462                return mShadowReceiverFragmentProgramUsage->getParameters();
1463        }
1464        //-----------------------------------------------------------------------
1465        const GpuProgramPtr& Pass::getShadowReceiverFragmentProgram(void) const
1466        {
1467                return mShadowReceiverFragmentProgramUsage->getProgram();
1468        }
1469    //-----------------------------------------------------------------------
1470        const String& Pass::getResourceGroup(void) const
1471        {
1472                return mParent->getResourceGroup();
1473        }
1474
1475    //-----------------------------------------------------------------------
1476    bool Pass::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const
1477    {
1478        // iterate through each texture unit state and apply the texture alias if it applies
1479        TextureUnitStates::const_iterator i, iend;
1480        iend = mTextureUnitStates.end();
1481        bool testResult = false;
1482
1483        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1484        {
1485            if ((*i)->applyTextureAliases(aliasList, apply))
1486                testResult = true;
1487        }
1488
1489        return testResult;
1490
1491    }
1492        //-----------------------------------------------------------------------
1493        unsigned short Pass::_getTextureUnitWithContentTypeIndex(
1494                TextureUnitState::ContentType contentType, unsigned short index) const
1495        {
1496                if (!mContentTypeLookupBuilt)
1497                {
1498                        mShadowContentTypeLookup.clear();
1499                        for (unsigned short i = 0; i < mTextureUnitStates.size(); ++i)
1500                        {
1501                                if (mTextureUnitStates[i]->getContentType() == TextureUnitState::CONTENT_SHADOW)
1502                                {
1503                                        mShadowContentTypeLookup.push_back(i);
1504                                }
1505                        }
1506                        mContentTypeLookupBuilt = true;
1507                }
1508
1509                switch(contentType)
1510                {
1511                case TextureUnitState::CONTENT_SHADOW:
1512                        if (index < mShadowContentTypeLookup.size())
1513                        {
1514                                return mShadowContentTypeLookup[index];
1515                        }
1516                        break;
1517                default:
1518                        // Simple iteration
1519                        for (unsigned short i = 0; i < mTextureUnitStates.size(); ++i)
1520                        {
1521                                if (mTextureUnitStates[i]->getContentType() == TextureUnitState::CONTENT_SHADOW)
1522                                {
1523                                        if (index == 0)
1524                                        {
1525                                                return i;
1526                                        }
1527                                        else
1528                                        {
1529                                                --index;
1530                                        }
1531                                }
1532                        }
1533                        break;
1534                }
1535
1536                // not found - return out of range
1537                return static_cast<unsigned short>(mTextureUnitStates.size() + 1);
1538
1539        }
1540
1541
1542}
Note: See TracBrowser for help on using the repository browser.