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