Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreTechnique.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 
00027 #include "OgreTechnique.h"
00028 #include "OgreMaterial.h"
00029 #include "OgrePass.h"
00030 #include "OgreRoot.h"
00031 #include "OgreRenderSystem.h"
00032 #include "OgreRenderSystemCapabilities.h"
00033 #include "OgreGpuProgramManager.h"
00034 
00035 
00036 namespace Ogre {
00037     //-----------------------------------------------------------------------------
00038     Technique::Technique(Material* parent)
00039         : mParent(parent), mIsSupported(false), mLodIndex(0)
00040     {
00041         // See above, defaults to unsupported until examined
00042     }
00043     //-----------------------------------------------------------------------------
00044     Technique::Technique(Material* parent, const Technique& oth)
00045         : mParent(parent), mLodIndex(0)
00046     {
00047         // Copy using operator=
00048         *this = oth;
00049     }
00050     //-----------------------------------------------------------------------------
00051     Technique::~Technique()
00052     {
00053         removeAllPasses();
00054         clearIlluminationPasses();
00055     }
00056     //-----------------------------------------------------------------------------
00057     bool Technique::isSupported(void) const
00058     {
00059         return mIsSupported;
00060     }
00061     //-----------------------------------------------------------------------------
00062     void Technique::_compile(bool autoManageTextureUnits)
00063     {
00064         // assume not supported
00065         mIsSupported = false;
00066         // Go through each pass, checking requirements
00067         Passes::iterator i, iend;
00068         iend = mPasses.end();
00069         for (i = mPasses.begin(); i != iend; ++i)
00070         {
00071             Pass* currPass = *i;
00072             // Check texture unit requirements
00073             size_t numTexUnitsRequested = currPass->getNumTextureUnitStates();
00074             const RenderSystemCapabilities* caps = 
00075                 Root::getSingleton().getRenderSystem()->getCapabilities();
00076             unsigned short numTexUnits = caps->getNumTextureUnits();
00077 
00078             if (currPass->hasFragmentProgram())
00079             {
00080                 // Check texture units
00081                 if (numTexUnitsRequested > numTexUnits)
00082                 {
00083                     // Can't do this one, and can't split a fragment pass
00084                     return;
00085                 }
00086                 // Check fragment program version
00087                 if (!currPass->getFragmentProgram()->isSupported())
00088                 {
00089                     // Can't do this one
00090                     return;
00091                 }
00092             }
00093             else
00094             {
00095                 // Check a few fixed-function options in texture layers
00096                 Pass::TextureUnitStateIterator texi = currPass->getTextureUnitStateIterator();
00097                 while (texi.hasMoreElements())
00098                 {
00099                     TextureUnitState* tex = texi.getNext();
00100                     // Any Cube textures? NB we make the assumption that any 
00101                     // card capable of running fragment programs can support
00102                     // cubic textures, which has to be true, surely?
00103                     if (tex->is3D() && !caps->hasCapability(RSC_CUBEMAPPING))
00104                     {
00105                         // Fail
00106                         return;
00107                     }
00108                     // Any Dot3 blending?
00109                     if (tex->getColourBlendMode().operation == LBX_DOTPRODUCT &&
00110                             !caps->hasCapability(RSC_DOT3))
00111                     {
00112                         // Fail
00113                         return;
00114                     }
00115                 }
00116                 
00117                 // We're ok on operations, now we need to check # texture units
00118                 // Keep splitting this pass so long as units requested > gpu units
00119                 while (numTexUnitsRequested > numTexUnits)
00120                 {
00121                     // chop this pass into many passes
00122                     currPass = currPass->_split(numTexUnits);
00123                     numTexUnitsRequested = currPass->getNumTextureUnitStates();
00124                 }
00125             }
00126 
00127             if (currPass->hasVertexProgram())
00128             {
00129                 // Check vertex program version
00130                 if (!currPass->getVertexProgram()->isSupported() )
00131                 {
00132                     // Can't do this one
00133                     return;
00134                 }
00135             }
00136         
00137         }
00138         // If we got this far, we're ok
00139         mIsSupported = true;
00140 
00141         // Now compile for categorised illumination, incase we need it
00142         _compileIlluminationPasses();
00143 
00144     }
00145     //-----------------------------------------------------------------------------
00146     Pass* Technique::createPass(void)
00147     {
00148         Pass* newPass = new Pass(this, static_cast<unsigned short>(mPasses.size()));
00149         mPasses.push_back(newPass);
00150         return newPass;
00151     }
00152     //-----------------------------------------------------------------------------
00153     Pass* Technique::getPass(unsigned short index)
00154     {
00155         assert(index < mPasses.size() && "Index out of bounds");
00156         return mPasses[index];
00157     }
00158     //-----------------------------------------------------------------------------
00159     unsigned short Technique::getNumPasses(void) const
00160     {
00161         return static_cast<unsigned short>(mPasses.size());
00162     }
00163     //-----------------------------------------------------------------------------
00164     void Technique::removePass(unsigned short index)
00165     {
00166         assert(index < mPasses.size() && "Index out of bounds");
00167         Passes::iterator i = mPasses.begin() + index;
00168         (*i)->queueForDeletion();
00169         mPasses.erase(i);
00170     }
00171     //-----------------------------------------------------------------------------
00172     void Technique::removeAllPasses(void)
00173     {
00174         Passes::iterator i, iend;
00175         iend = mPasses.end();
00176         for (i = mPasses.begin(); i != iend; ++i)
00177         {
00178             (*i)->queueForDeletion();
00179         }
00180         mPasses.clear();
00181     }
00182     //-----------------------------------------------------------------------------
00183     const Technique::PassIterator Technique::getPassIterator(void)
00184     {
00185         return PassIterator(mPasses.begin(), mPasses.end());
00186     }
00187     //-----------------------------------------------------------------------------
00188     Technique& Technique::operator=(const Technique& rhs)
00189     {
00190         this->mIsSupported = rhs.mIsSupported;
00191         this->mLodIndex = rhs.mLodIndex;
00192         // copy passes
00193         removeAllPasses();
00194         Passes::const_iterator i, iend;
00195         iend = rhs.mPasses.end();
00196         for (i = rhs.mPasses.begin(); i != iend; ++i)
00197         {
00198             Pass* p = new Pass(this, (*i)->getIndex(), *(*i));
00199             mPasses.push_back(p);
00200         }
00201         // recompile illumination passes
00202         _compileIlluminationPasses();
00203         return *this;
00204     }
00205     //-----------------------------------------------------------------------------
00206     bool Technique::isTransparent(void) const
00207     {
00208         if (mPasses.empty())
00209         {
00210             return false;
00211         }
00212         else
00213         {
00214             // Base decision on the transparency of the first pass
00215             return mPasses[0]->isTransparent();
00216         }
00217     }
00218     //-----------------------------------------------------------------------------
00219     bool Technique::isDepthWriteEnabled(void) const
00220     {
00221         if (mPasses.empty())
00222         {
00223             return false;
00224         }
00225         else
00226         {
00227             // Base decision on the depth settings of the first pass
00228             return mPasses[0]->getDepthWriteEnabled();
00229         }
00230     }
00231     //-----------------------------------------------------------------------------
00232     bool Technique::isDepthCheckEnabled(void) const
00233     {
00234         if (mPasses.empty())
00235         {
00236             return false;
00237         }
00238         else
00239         {
00240             // Base decision on the depth settings of the first pass
00241             return mPasses[0]->getDepthCheckEnabled();
00242         }
00243     }
00244     //-----------------------------------------------------------------------------
00245     void Technique::_load(void)
00246     {
00247         assert (mIsSupported && "This technique is not supported");
00248         // Load each pass
00249         Passes::iterator i, iend;
00250         iend = mPasses.end();
00251         for (i = mPasses.begin(); i != iend; ++i)
00252         {
00253             (*i)->_load();
00254         }
00255     }
00256     //-----------------------------------------------------------------------------
00257     void Technique::_unload(void)
00258     {
00259         // Unload each pass
00260         Passes::iterator i, iend;
00261         iend = mPasses.end();
00262         for (i = mPasses.begin(); i != iend; ++i)
00263         {
00264             (*i)->_unload();
00265         }
00266     }
00267     //-----------------------------------------------------------------------------
00268     bool Technique::isLoaded(void) const
00269     {
00270         return mParent->isLoaded();
00271     }
00272     //-----------------------------------------------------------------------
00273     void Technique::setAmbient(Real red, Real green, Real blue)
00274     {
00275         Passes::iterator i, iend;
00276         iend = mPasses.end();
00277         for (i = mPasses.begin(); i != iend; ++i)
00278         {
00279             (*i)->setAmbient(red, green, blue);
00280         }
00281 
00282     }
00283     //-----------------------------------------------------------------------
00284     void Technique::setAmbient(const ColourValue& ambient)
00285     {
00286         setAmbient(ambient.r, ambient.g, ambient.b);
00287     }
00288     //-----------------------------------------------------------------------
00289     void Technique::setDiffuse(Real red, Real green, Real blue, Real alpha)
00290     {
00291         Passes::iterator i, iend;
00292         iend = mPasses.end();
00293         for (i = mPasses.begin(); i != iend; ++i)
00294         {
00295             (*i)->setDiffuse(red, green, blue, alpha);
00296         }
00297     }
00298     //-----------------------------------------------------------------------
00299     void Technique::setDiffuse(const ColourValue& diffuse)
00300     {
00301         setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
00302     }
00303     //-----------------------------------------------------------------------
00304     void Technique::setSpecular(Real red, Real green, Real blue, Real alpha)
00305     {
00306         Passes::iterator i, iend;
00307         iend = mPasses.end();
00308         for (i = mPasses.begin(); i != iend; ++i)
00309         {
00310             (*i)->setSpecular(red, green, blue, alpha);
00311         }
00312     }
00313     //-----------------------------------------------------------------------
00314     void Technique::setSpecular(const ColourValue& specular)
00315     {
00316         setSpecular(specular.r, specular.g, specular.b, specular.a);
00317     }
00318     //-----------------------------------------------------------------------
00319     void Technique::setShininess(Real val)
00320     {
00321         Passes::iterator i, iend;
00322         iend = mPasses.end();
00323         for (i = mPasses.begin(); i != iend; ++i)
00324         {
00325             (*i)->setShininess(val);
00326         }
00327     }
00328     //-----------------------------------------------------------------------
00329     void Technique::setSelfIllumination(Real red, Real green, Real blue)
00330     {
00331         Passes::iterator i, iend;
00332         iend = mPasses.end();
00333         for (i = mPasses.begin(); i != iend; ++i)
00334         {
00335             (*i)->setSelfIllumination(red, green, blue);
00336         }
00337     }
00338     //-----------------------------------------------------------------------
00339     void Technique::setSelfIllumination(const ColourValue& selfIllum)
00340     {
00341         setSelfIllumination(selfIllum.r, selfIllum.g, selfIllum.b);
00342     }
00343     //-----------------------------------------------------------------------
00344     void Technique::setDepthCheckEnabled(bool enabled)
00345     {
00346         Passes::iterator i, iend;
00347         iend = mPasses.end();
00348         for (i = mPasses.begin(); i != iend; ++i)
00349         {
00350             (*i)->setDepthCheckEnabled(enabled);
00351         }
00352     }
00353     //-----------------------------------------------------------------------
00354     void Technique::setDepthWriteEnabled(bool enabled)
00355     {
00356         Passes::iterator i, iend;
00357         iend = mPasses.end();
00358         for (i = mPasses.begin(); i != iend; ++i)
00359         {
00360             (*i)->setDepthWriteEnabled(enabled);
00361         }
00362     }
00363     //-----------------------------------------------------------------------
00364     void Technique::setDepthFunction( CompareFunction func )
00365     {
00366         Passes::iterator i, iend;
00367         iend = mPasses.end();
00368         for (i = mPasses.begin(); i != iend; ++i)
00369         {
00370             (*i)->setDepthFunction(func);
00371         }
00372     }
00373     //-----------------------------------------------------------------------
00374     void Technique::setColourWriteEnabled(bool enabled)
00375     {
00376         Passes::iterator i, iend;
00377         iend = mPasses.end();
00378         for (i = mPasses.begin(); i != iend; ++i)
00379         {
00380             (*i)->setColourWriteEnabled(enabled);
00381         }
00382     }
00383     //-----------------------------------------------------------------------
00384     void Technique::setCullingMode( CullingMode mode )
00385     {
00386         Passes::iterator i, iend;
00387         iend = mPasses.end();
00388         for (i = mPasses.begin(); i != iend; ++i)
00389         {
00390             (*i)->setCullingMode(mode);
00391         }
00392     }
00393     //-----------------------------------------------------------------------
00394     void Technique::setManualCullingMode( ManualCullingMode mode )
00395     {
00396         Passes::iterator i, iend;
00397         iend = mPasses.end();
00398         for (i = mPasses.begin(); i != iend; ++i)
00399         {
00400             (*i)->setManualCullingMode(mode);
00401         }
00402     }
00403     //-----------------------------------------------------------------------
00404     void Technique::setLightingEnabled(bool enabled)
00405     {
00406         Passes::iterator i, iend;
00407         iend = mPasses.end();
00408         for (i = mPasses.begin(); i != iend; ++i)
00409         {
00410             (*i)->setLightingEnabled(enabled);
00411         }
00412     }
00413     //-----------------------------------------------------------------------
00414     void Technique::setShadingMode( ShadeOptions mode )
00415     {
00416         Passes::iterator i, iend;
00417         iend = mPasses.end();
00418         for (i = mPasses.begin(); i != iend; ++i)
00419         {
00420             (*i)->setShadingMode(mode);
00421         }
00422     }
00423     //-----------------------------------------------------------------------
00424     void Technique::setFog(bool overrideScene, FogMode mode, const ColourValue& colour,
00425         Real expDensity, Real linearStart, Real linearEnd)
00426     {
00427         Passes::iterator i, iend;
00428         iend = mPasses.end();
00429         for (i = mPasses.begin(); i != iend; ++i)
00430         {
00431             (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd);
00432         }
00433     }
00434     //-----------------------------------------------------------------------
00435     void Technique::setDepthBias(ushort bias)
00436     {
00437         Passes::iterator i, iend;
00438         iend = mPasses.end();
00439         for (i = mPasses.begin(); i != iend; ++i)
00440         {
00441             (*i)->setDepthBias(bias);
00442         }
00443     }
00444     //-----------------------------------------------------------------------
00445     void Technique::setTextureFiltering(TextureFilterOptions filterType)
00446     {
00447         Passes::iterator i, iend;
00448         iend = mPasses.end();
00449         for (i = mPasses.begin(); i != iend; ++i)
00450         {
00451             (*i)->setTextureFiltering(filterType);
00452         }
00453     }
00454     // --------------------------------------------------------------------
00455     void Technique::setTextureAnisotropy(unsigned int maxAniso)
00456     {
00457         Passes::iterator i, iend;
00458         iend = mPasses.end();
00459         for (i = mPasses.begin(); i != iend; ++i)
00460         {
00461             (*i)->setTextureAnisotropy(maxAniso);
00462         }
00463     }
00464     // --------------------------------------------------------------------
00465     void Technique::setSceneBlending( const SceneBlendType sbt )
00466     {
00467         Passes::iterator i, iend;
00468         iend = mPasses.end();
00469         for (i = mPasses.begin(); i != iend; ++i)
00470         {
00471             (*i)->setSceneBlending(sbt);
00472         }
00473     }
00474     // --------------------------------------------------------------------
00475     void Technique::setSceneBlending( const SceneBlendFactor sourceFactor, 
00476         const SceneBlendFactor destFactor)
00477     {
00478         Passes::iterator i, iend;
00479         iend = mPasses.end();
00480         for (i = mPasses.begin(); i != iend; ++i)
00481         {
00482             (*i)->setSceneBlending(sourceFactor, destFactor);
00483         }
00484     }
00485 
00486     //-----------------------------------------------------------------------
00487     void Technique::_notifyNeedsRecompile(void)
00488     {
00489         mParent->_notifyNeedsRecompile();
00490     }
00491     //-----------------------------------------------------------------------
00492     void Technique::setLodIndex(unsigned short index)
00493     {
00494         mLodIndex = index;
00495         _notifyNeedsRecompile();
00496     }
00497     //-----------------------------------------------------------------------
00498     void Technique::_compileIlluminationPasses(void)
00499     {
00500         clearIlluminationPasses();
00501 
00502         if (isTransparent())
00503         {
00504             // Don't need to split transparents since they are rendered separately
00505             return;
00506         }
00507 
00508         Passes::iterator i, iend;
00509         iend = mPasses.end();
00510         i = mPasses.begin();
00511         
00512         IlluminationStage iStage = IS_AMBIENT;
00513 
00514         bool haveAmbient = false;
00515         while (i != iend)
00516         {
00517             IlluminationPass* iPass;
00518             Pass* p = *i;
00519             switch(iStage)
00520             {
00521             case IS_AMBIENT:
00522                 // Keep looking for ambient only
00523                 if (p->isAmbientOnly())
00524                 {
00525                     // Add this pass wholesale
00526                     iPass = new IlluminationPass();
00527                     iPass->destroyOnShutdown = false;
00528                     iPass->originalPass = iPass->pass = p;
00529                     iPass->stage = iStage;
00530                     mIlluminationPasses.push_back(iPass);
00531                     haveAmbient = true;
00532                     // progress to next pass
00533                     ++i;
00534                 }
00535                 else
00536                 {
00537                     // Split off any ambient part
00538                     if (p->getAmbient() != ColourValue::Black ||
00539                         p->getSelfIllumination() != ColourValue::Black)
00540                     {
00541                         // Copy existing pass
00542                         Pass* newPass = new Pass(this, p->getIndex());
00543                         *newPass = *p;
00544                         // Remove any texture units
00545                         newPass->removeAllTextureUnitStates();
00546                         // Remove any fragment program
00547                         if (newPass->hasFragmentProgram())
00548                             newPass->setFragmentProgram("");
00549                         // We have to leave vertex program alone (if any) and
00550                         // just trust that the author is using light bindings, which 
00551                         // we will ensure there are none in the ambient pass
00552                         newPass->setDiffuse(ColourValue::Black);
00553                         newPass->setSpecular(ColourValue::Black);
00554 
00555                         // If ambient & emissive are zero, then no colour write
00556                         if (newPass->getAmbient() == ColourValue::Black && 
00557                             newPass->getSelfIllumination() == ColourValue::Black)
00558                         {
00559                             newPass->setColourWriteEnabled(false);
00560                         }
00561 
00562                         iPass = new IlluminationPass();
00563                         iPass->destroyOnShutdown = true;
00564                         iPass->originalPass = p;
00565                         iPass->pass = newPass;
00566                         iPass->stage = iStage;
00567 
00568                         mIlluminationPasses.push_back(iPass);
00569                         haveAmbient = true;
00570                         
00571                     }
00572                     
00573                     if (!haveAmbient)
00574                     {
00575                         // Make up a new basic pass
00576                         Pass* newPass = new Pass(this, p->getIndex());
00577                         newPass->setAmbient(ColourValue::Black);
00578                         newPass->setDiffuse(ColourValue::Black);
00579                         iPass = new IlluminationPass();
00580                         iPass->destroyOnShutdown = true;
00581                         iPass->originalPass = p;
00582                         iPass->pass = newPass;
00583                         iPass->stage = iStage;
00584                         mIlluminationPasses.push_back(iPass);
00585                         haveAmbient = true;
00586                     }
00587                     // This means we're done with ambients, progress to per-light
00588                     iStage = IS_PER_LIGHT;
00589                 }
00590                 break;
00591             case IS_PER_LIGHT:
00592                 if (p->getRunOncePerLight())
00593                 {
00594                     // If this is per-light already, use it directly
00595                     iPass = new IlluminationPass();
00596                     iPass->destroyOnShutdown = false;
00597                     iPass->originalPass = iPass->pass = p;
00598                     iPass->stage = iStage;
00599                     mIlluminationPasses.push_back(iPass);
00600                     // progress to next pass
00601                     ++i;
00602                 }
00603                 else
00604                 {
00605                     // Split off per-light details (can only be done for one)
00606                     if (p->getLightingEnabled() && 
00607                         (p->getDiffuse() != ColourValue::Black ||
00608                         p->getSpecular() != ColourValue::Black))
00609                     {
00610                         // Copy existing pass
00611                         Pass* newPass = new Pass(this, p->getIndex());
00612                         *newPass = *p;
00613                         // remove texture units
00614                         newPass->removeAllTextureUnitStates();
00615                         // remove fragment programs
00616                         if (newPass->hasFragmentProgram())
00617                             newPass->setFragmentProgram("");
00618                         // Cannot remove vertex program, have to assume that
00619                         // it will process diffuse lights, ambient will be turned off
00620                         newPass->setAmbient(ColourValue::Black);
00621                         newPass->setSelfIllumination(ColourValue::Black);
00622                         // must be additive
00623                         newPass->setSceneBlending(SBF_ONE, SBF_ONE);
00624 
00625                         iPass = new IlluminationPass();
00626                         iPass->destroyOnShutdown = true;
00627                         iPass->originalPass = p;
00628                         iPass->pass = newPass;
00629                         iPass->stage = iStage;
00630 
00631                         mIlluminationPasses.push_back(iPass);
00632 
00633                     }
00634                     // This means the end of per-light passes
00635                     iStage = IS_DECAL;
00636                 }
00637                 break;
00638             case IS_DECAL:
00639                 // We just want a 'lighting off' pass to finish off
00640                 // and only if there are texture units
00641                 if (p->getNumTextureUnitStates() > 0)
00642                 {
00643                     if (!p->getLightingEnabled())
00644                     {
00645                         // we assume this pass already combines as required with the scene
00646                         iPass = new IlluminationPass();
00647                         iPass->destroyOnShutdown = false;
00648                         iPass->originalPass = iPass->pass = p;
00649                         iPass->stage = iStage;
00650                         mIlluminationPasses.push_back(iPass);
00651                     }
00652                     else
00653                     {
00654                         // Copy the pass and tweak away the lighting parts
00655                         Pass* newPass = new Pass(this, p->getIndex());
00656                         *newPass = *p;
00657                         newPass->setAmbient(ColourValue::Black);
00658                         newPass->setDiffuse(ColourValue::Black);
00659                         newPass->setSpecular(ColourValue::Black);
00660                         newPass->setSelfIllumination(ColourValue::Black);
00661                         newPass->setLightingEnabled(false);
00662                         // modulate
00663                         newPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
00664 
00665                         // NB there is nothing we can do about vertex & fragment
00666                         // programs here, so people will just have to make their
00667                         // programs friendly-like if they want to use this technique
00668                         iPass = new IlluminationPass();
00669                         iPass->destroyOnShutdown = true;
00670                         iPass->originalPass = p;
00671                         iPass->pass = newPass;
00672                         iPass->stage = iStage;
00673                         mIlluminationPasses.push_back(iPass);
00674 
00675                     }
00676                 }
00677                 ++i; // always increment on decal, since nothing more to do with this pass
00678 
00679                 break;
00680             }
00681         }
00682 
00683     }
00684     //-----------------------------------------------------------------------
00685     void Technique::clearIlluminationPasses(void)
00686     {
00687         IlluminationPassList::iterator i, iend;
00688         iend = mIlluminationPasses.end();
00689         for (i = mIlluminationPasses.begin(); i != iend; ++i)
00690         {
00691             if ((*i)->destroyOnShutdown)
00692             {
00693                 (*i)->pass->queueForDeletion();
00694             }
00695             delete *i;
00696         }
00697         mIlluminationPasses.clear();
00698     }
00699     //-----------------------------------------------------------------------
00700     const Technique::IlluminationPassIterator 
00701     Technique::getIlluminationPassIterator(void)
00702     {
00703         return IlluminationPassIterator(mIlluminationPasses.begin(), 
00704             mIlluminationPasses.end());
00705     }
00706 
00707 
00708 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:48 2004