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     }
00055     //-----------------------------------------------------------------------------
00056     bool Technique::isSupported(void) const
00057     {
00058         return mIsSupported;
00059     }
00060     //-----------------------------------------------------------------------------
00061     void Technique::_compile(bool autoManageTextureUnits)
00062     {
00063         // assume not supported
00064         mIsSupported = false;
00065         // Go through each pass, checking requirements
00066         Passes::iterator i, iend;
00067         iend = mPasses.end();
00068         for (i = mPasses.begin(); i != iend; ++i)
00069         {
00070             Pass* currPass = *i;
00071             // Check texture unit requirements
00072             size_t numTexUnitsRequested = currPass->getNumTextureUnitStates();
00073             const RenderSystemCapabilities* caps = 
00074                 Root::getSingleton().getRenderSystem()->getCapabilities();
00075             unsigned short numTexUnits = caps->getNumTextureUnits();
00076 
00077             if (currPass->hasFragmentProgram())
00078             {
00079                 // Check texture units
00080                 if (numTexUnitsRequested > numTexUnits)
00081                 {
00082                     // Can't do this one, and can't split a fragment pass
00083                     return;
00084                 }
00085                 // Check fragment program version
00086                 if (!currPass->getFragmentProgram()->isSupported())
00087                 {
00088                     // Can't do this one
00089                     return;
00090                 }
00091             }
00092             else
00093             {
00094                 // Check a few fixed-function options in texture layers
00095                 Pass::TextureUnitStateIterator texi = currPass->getTextureUnitStateIterator();
00096                 while (texi.hasMoreElements())
00097                 {
00098                     TextureUnitState* tex = texi.getNext();
00099                     // Any Cube textures? NB we make the assumption that any 
00100                     // card capable of running fragment programs can support
00101                     // cubic textures, which has to be true, surely?
00102                     if (tex->is3D() && !caps->hasCapability(RSC_CUBEMAPPING))
00103                     {
00104                         // Fail
00105                         return;
00106                     }
00107                     // Any Dot3 blending?
00108                     if (tex->getColourBlendMode().operation == LBX_DOTPRODUCT &&
00109                             !caps->hasCapability(RSC_DOT3))
00110                     {
00111                         // Fail
00112                         return;
00113                     }
00114                 }
00115                 
00116                 // We're ok on operations, now we need to check # texture units
00117                 // Keep splitting this pass so long as units requested > gpu units
00118                 while (numTexUnitsRequested > numTexUnits)
00119                 {
00120                     // chop this pass into many passes
00121                     currPass = currPass->_split(numTexUnits);
00122                     numTexUnitsRequested = currPass->getNumTextureUnitStates();
00123                 }
00124             }
00125 
00126             if (currPass->hasVertexProgram())
00127             {
00128                 // Check vertex program version
00129                 if (!currPass->getVertexProgram()->isSupported() )
00130                 {
00131                     // Can't do this one
00132                     return;
00133                 }
00134             }
00135         
00136         }
00137         // If we got this far, we're ok
00138         mIsSupported = true;
00139 
00140     }
00141     //-----------------------------------------------------------------------------
00142     Pass* Technique::createPass(void)
00143     {
00144         Pass* newPass = new Pass(this, static_cast<unsigned short>(mPasses.size()));
00145         mPasses.push_back(newPass);
00146         return newPass;
00147     }
00148     //-----------------------------------------------------------------------------
00149     Pass* Technique::getPass(unsigned short index)
00150     {
00151         assert(index < mPasses.size() && "Index out of bounds");
00152         return mPasses[index];
00153     }
00154     //-----------------------------------------------------------------------------
00155     unsigned short Technique::getNumPasses(void) const
00156     {
00157         return static_cast<unsigned short>(mPasses.size());
00158     }
00159     //-----------------------------------------------------------------------------
00160     void Technique::removePass(unsigned short index)
00161     {
00162         assert(index < mPasses.size() && "Index out of bounds");
00163         Passes::iterator i = mPasses.begin() + index;
00164         delete *i;
00165         mPasses.erase(i);
00166     }
00167     //-----------------------------------------------------------------------------
00168     void Technique::removeAllPasses(void)
00169     {
00170         Passes::iterator i, iend;
00171         iend = mPasses.end();
00172         for (i = mPasses.begin(); i != iend; ++i)
00173         {
00174             delete(*i);
00175         }
00176         mPasses.clear();
00177     }
00178     //-----------------------------------------------------------------------------
00179     const Technique::PassIterator Technique::getPassIterator(void)
00180     {
00181         return PassIterator(mPasses.begin(), mPasses.end());
00182     }
00183     //-----------------------------------------------------------------------------
00184     Technique& Technique::operator=(const Technique& rhs)
00185     {
00186         this->mIsSupported = rhs.mIsSupported;
00187         // copy passes
00188         removeAllPasses();
00189         Passes::const_iterator i, iend;
00190         iend = rhs.mPasses.end();
00191         for (i = rhs.mPasses.begin(); i != iend; ++i)
00192         {
00193             Pass* p = new Pass(this, (*i)->getIndex(), *(*i));
00194             mPasses.push_back(p);
00195         }
00196         return *this;
00197     }
00198     //-----------------------------------------------------------------------------
00199     bool Technique::isTransparent(void) const
00200     {
00201         if (mPasses.empty())
00202         {
00203             return false;
00204         }
00205         else
00206         {
00207             // Base decision on the transparency of the first pass
00208             return mPasses[0]->isTransparent();
00209         }
00210     }
00211     //-----------------------------------------------------------------------------
00212     void Technique::_load(void)
00213     {
00214         assert (mIsSupported && "This technique is not supported");
00215         // Load each pass
00216         Passes::iterator i, iend;
00217         iend = mPasses.end();
00218         for (i = mPasses.begin(); i != iend; ++i)
00219         {
00220             (*i)->_load();
00221         }
00222     }
00223     //-----------------------------------------------------------------------------
00224     void Technique::_unload(void)
00225     {
00226         // Unload each pass
00227         Passes::iterator i, iend;
00228         iend = mPasses.end();
00229         for (i = mPasses.begin(); i != iend; ++i)
00230         {
00231             (*i)->_unload();
00232         }
00233     }
00234     //-----------------------------------------------------------------------------
00235     bool Technique::isLoaded(void) const
00236     {
00237         return mParent->isLoaded();
00238     }
00239     //-----------------------------------------------------------------------
00240     void Technique::setAmbient(Real red, Real green, Real blue)
00241     {
00242         Passes::iterator i, iend;
00243         iend = mPasses.end();
00244         for (i = mPasses.begin(); i != iend; ++i)
00245         {
00246             (*i)->setAmbient(red, green, blue);
00247         }
00248 
00249     }
00250     //-----------------------------------------------------------------------
00251     void Technique::setAmbient(const ColourValue& ambient)
00252     {
00253         setAmbient(ambient.r, ambient.g, ambient.b);
00254     }
00255     //-----------------------------------------------------------------------
00256     void Technique::setDiffuse(Real red, Real green, Real blue)
00257     {
00258         Passes::iterator i, iend;
00259         iend = mPasses.end();
00260         for (i = mPasses.begin(); i != iend; ++i)
00261         {
00262             (*i)->setDiffuse(red, green, blue);
00263         }
00264     }
00265     //-----------------------------------------------------------------------
00266     void Technique::setDiffuse(const ColourValue& diffuse)
00267     {
00268         setDiffuse(diffuse.r, diffuse.g, diffuse.b);
00269     }
00270     //-----------------------------------------------------------------------
00271     void Technique::setSpecular(Real red, Real green, Real blue)
00272     {
00273         Passes::iterator i, iend;
00274         iend = mPasses.end();
00275         for (i = mPasses.begin(); i != iend; ++i)
00276         {
00277             (*i)->setSpecular(red, green, blue);
00278         }
00279     }
00280     //-----------------------------------------------------------------------
00281     void Technique::setSpecular(const ColourValue& specular)
00282     {
00283         setSpecular(specular.r, specular.g, specular.b);
00284     }
00285     //-----------------------------------------------------------------------
00286     void Technique::setShininess(Real val)
00287     {
00288         Passes::iterator i, iend;
00289         iend = mPasses.end();
00290         for (i = mPasses.begin(); i != iend; ++i)
00291         {
00292             (*i)->setShininess(val);
00293         }
00294     }
00295     //-----------------------------------------------------------------------
00296     void Technique::setSelfIllumination(Real red, Real green, Real blue)
00297     {
00298         Passes::iterator i, iend;
00299         iend = mPasses.end();
00300         for (i = mPasses.begin(); i != iend; ++i)
00301         {
00302             (*i)->setSelfIllumination(red, green, blue);
00303         }
00304     }
00305     //-----------------------------------------------------------------------
00306     void Technique::setSelfIllumination(const ColourValue& selfIllum)
00307     {
00308         setSelfIllumination(selfIllum.r, selfIllum.g, selfIllum.b);
00309     }
00310     //-----------------------------------------------------------------------
00311     void Technique::setDepthCheckEnabled(bool enabled)
00312     {
00313         Passes::iterator i, iend;
00314         iend = mPasses.end();
00315         for (i = mPasses.begin(); i != iend; ++i)
00316         {
00317             (*i)->setDepthCheckEnabled(enabled);
00318         }
00319     }
00320     //-----------------------------------------------------------------------
00321     void Technique::setDepthWriteEnabled(bool enabled)
00322     {
00323         Passes::iterator i, iend;
00324         iend = mPasses.end();
00325         for (i = mPasses.begin(); i != iend; ++i)
00326         {
00327             (*i)->setDepthWriteEnabled(enabled);
00328         }
00329     }
00330     //-----------------------------------------------------------------------
00331     void Technique::setDepthFunction( CompareFunction func )
00332     {
00333         Passes::iterator i, iend;
00334         iend = mPasses.end();
00335         for (i = mPasses.begin(); i != iend; ++i)
00336         {
00337             (*i)->setDepthFunction(func);
00338         }
00339     }
00340     //-----------------------------------------------------------------------
00341     void Technique::setColourWriteEnabled(bool enabled)
00342     {
00343         Passes::iterator i, iend;
00344         iend = mPasses.end();
00345         for (i = mPasses.begin(); i != iend; ++i)
00346         {
00347             (*i)->setColourWriteEnabled(enabled);
00348         }
00349     }
00350     //-----------------------------------------------------------------------
00351     void Technique::setCullingMode( CullingMode mode )
00352     {
00353         Passes::iterator i, iend;
00354         iend = mPasses.end();
00355         for (i = mPasses.begin(); i != iend; ++i)
00356         {
00357             (*i)->setCullingMode(mode);
00358         }
00359     }
00360     //-----------------------------------------------------------------------
00361     void Technique::setManualCullingMode( ManualCullingMode mode )
00362     {
00363         Passes::iterator i, iend;
00364         iend = mPasses.end();
00365         for (i = mPasses.begin(); i != iend; ++i)
00366         {
00367             (*i)->setManualCullingMode(mode);
00368         }
00369     }
00370     //-----------------------------------------------------------------------
00371     void Technique::setLightingEnabled(bool enabled)
00372     {
00373         Passes::iterator i, iend;
00374         iend = mPasses.end();
00375         for (i = mPasses.begin(); i != iend; ++i)
00376         {
00377             (*i)->setLightingEnabled(enabled);
00378         }
00379     }
00380     //-----------------------------------------------------------------------
00381     void Technique::setShadingMode( ShadeOptions mode )
00382     {
00383         Passes::iterator i, iend;
00384         iend = mPasses.end();
00385         for (i = mPasses.begin(); i != iend; ++i)
00386         {
00387             (*i)->setShadingMode(mode);
00388         }
00389     }
00390     //-----------------------------------------------------------------------
00391     void Technique::setFog(bool overrideScene, FogMode mode, const ColourValue& colour,
00392         Real expDensity, Real linearStart, Real linearEnd)
00393     {
00394         Passes::iterator i, iend;
00395         iend = mPasses.end();
00396         for (i = mPasses.begin(); i != iend; ++i)
00397         {
00398             (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd);
00399         }
00400     }
00401     //-----------------------------------------------------------------------
00402     void Technique::setDepthBias(ushort bias)
00403     {
00404         Passes::iterator i, iend;
00405         iend = mPasses.end();
00406         for (i = mPasses.begin(); i != iend; ++i)
00407         {
00408             (*i)->setDepthBias(bias);
00409         }
00410     }
00411     //-----------------------------------------------------------------------
00412     void Technique::setTextureFiltering(TextureFilterOptions filterType)
00413     {
00414         Passes::iterator i, iend;
00415         iend = mPasses.end();
00416         for (i = mPasses.begin(); i != iend; ++i)
00417         {
00418             (*i)->setTextureFiltering(filterType);
00419         }
00420     }
00421     // --------------------------------------------------------------------
00422     void Technique::setTextureAnisotropy(unsigned int maxAniso)
00423     {
00424         Passes::iterator i, iend;
00425         iend = mPasses.end();
00426         for (i = mPasses.begin(); i != iend; ++i)
00427         {
00428             (*i)->setTextureAnisotropy(maxAniso);
00429         }
00430     }
00431     // --------------------------------------------------------------------
00432     void Technique::setSceneBlending( const SceneBlendType sbt )
00433     {
00434         Passes::iterator i, iend;
00435         iend = mPasses.end();
00436         for (i = mPasses.begin(); i != iend; ++i)
00437         {
00438             (*i)->setSceneBlending(sbt);
00439         }
00440     }
00441     // --------------------------------------------------------------------
00442     void Technique::setSceneBlending( const SceneBlendFactor sourceFactor, 
00443         const SceneBlendFactor destFactor)
00444     {
00445         Passes::iterator i, iend;
00446         iend = mPasses.end();
00447         for (i = mPasses.begin(); i != iend; ++i)
00448         {
00449             (*i)->setSceneBlending(sourceFactor, destFactor);
00450         }
00451     }
00452 
00453     //-----------------------------------------------------------------------
00454     void Technique::_notifyNeedsRecompile(void)
00455     {
00456         mParent->_notifyNeedsRecompile();
00457     }
00458     //-----------------------------------------------------------------------
00459     void Technique::setLodIndex(unsigned short index)
00460     {
00461         mLodIndex = index;
00462         _notifyNeedsRecompile();
00463     }
00464 
00465 
00466 
00467 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:29 2004