1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreStableHeaders.h" 29 30 #include "OgreTechnique.h" 31 #include "OgreMaterial.h" 32 #include "OgrePass.h" 33 #include "OgreRoot.h" 34 #include "OgreRenderSystem.h" 35 #include "OgreGpuProgramManager.h" 36 #include "OgreMaterialManager.h" 37 38 39 namespace Ogre { 40 //----------------------------------------------------------------------------- Technique(Material * parent)41 Technique::Technique(Material* parent) 42 : mParent(parent), mIsSupported(false), mIlluminationPassesCompilationPhase(IPS_NOT_COMPILED), mLodIndex(0), mSchemeIndex(0) 43 { 44 // See above, defaults to unsupported until examined 45 } 46 //----------------------------------------------------------------------------- Technique(Material * parent,const Technique & oth)47 Technique::Technique(Material* parent, const Technique& oth) 48 : mParent(parent), mLodIndex(0), mSchemeIndex(0) 49 { 50 // Copy using operator= 51 *this = oth; 52 } 53 //----------------------------------------------------------------------------- ~Technique()54 Technique::~Technique() 55 { 56 removeAllPasses(); 57 clearIlluminationPasses(); 58 } 59 //----------------------------------------------------------------------------- isSupported(void) const60 bool Technique::isSupported(void) const 61 { 62 return mIsSupported; 63 } 64 //----------------------------------------------------------------------------- calculateSize(void) const65 size_t Technique::calculateSize(void) const 66 { 67 size_t memSize = 0; 68 69 // Tally up passes 70 Passes::const_iterator i, iend; 71 iend = mPasses.end(); 72 for (i = mPasses.begin(); i != iend; ++i) 73 { 74 memSize += (*i)->calculateSize(); 75 } 76 return memSize; 77 } 78 //----------------------------------------------------------------------------- _compile(bool autoManageTextureUnits)79 String Technique::_compile(bool autoManageTextureUnits) 80 { 81 StringUtil::StrStreamType errors; 82 83 mIsSupported = checkGPURules(errors); 84 if (mIsSupported) 85 { 86 mIsSupported = checkHardwareSupport(autoManageTextureUnits, errors); 87 } 88 89 // Compile for categorised illumination on demand 90 clearIlluminationPasses(); 91 mIlluminationPassesCompilationPhase = IPS_NOT_COMPILED; 92 93 return errors.str(); 94 95 } 96 //--------------------------------------------------------------------- checkHardwareSupport(bool autoManageTextureUnits,StringUtil::StrStreamType & compileErrors)97 bool Technique::checkHardwareSupport(bool autoManageTextureUnits, StringUtil::StrStreamType& compileErrors) 98 { 99 // Go through each pass, checking requirements 100 Passes::iterator i; 101 unsigned short passNum = 0; 102 const RenderSystemCapabilities* caps = 103 Root::getSingleton().getRenderSystem()->getCapabilities(); 104 unsigned short numTexUnits = caps->getNumTextureUnits(); 105 for (i = mPasses.begin(); i != mPasses.end(); ++i, ++passNum) 106 { 107 Pass* currPass = *i; 108 // Adjust pass index 109 currPass->_notifyIndex(passNum); 110 // Check for advanced blending operation support 111 if((currPass->getSceneBlendingOperation() != SBO_ADD || currPass->getSceneBlendingOperationAlpha() != SBO_ADD) && 112 !caps->hasCapability(RSC_ADVANCED_BLEND_OPERATIONS)) 113 { 114 return false; 115 } 116 // Check texture unit requirements 117 size_t numTexUnitsRequested = currPass->getNumTextureUnitStates(); 118 // Don't trust getNumTextureUnits for programmable 119 if(!currPass->hasFragmentProgram()) 120 { 121 #if defined(OGRE_PRETEND_TEXTURE_UNITS) && OGRE_PRETEND_TEXTURE_UNITS > 0 122 if (numTexUnits > OGRE_PRETEND_TEXTURE_UNITS) 123 numTexUnits = OGRE_PRETEND_TEXTURE_UNITS; 124 #endif 125 if (numTexUnitsRequested > numTexUnits) 126 { 127 if (!autoManageTextureUnits) 128 { 129 // The user disabled auto pass split 130 compileErrors << "Pass " << passNum << 131 ": Too many texture units for the current hardware and no splitting allowed." 132 << std::endl; 133 return false; 134 } 135 else if (currPass->hasVertexProgram()) 136 { 137 // Can't do this one, and can't split a programmable pass 138 compileErrors << "Pass " << passNum << 139 ": Too many texture units for the current hardware and " 140 "cannot split programmable passes." 141 << std::endl; 142 return false; 143 } 144 } 145 } 146 if (currPass->hasComputeProgram()) 147 { 148 // Check fragment program version 149 if (!currPass->getComputeProgram()->isSupported()) 150 { 151 // Can't do this one 152 compileErrors << "Pass " << passNum << 153 ": Compute program " << currPass->getComputeProgram()->getName() 154 << " cannot be used - "; 155 if (currPass->getComputeProgram()->hasCompileError()) 156 compileErrors << "compile error."; 157 else 158 compileErrors << "not supported."; 159 160 compileErrors << std::endl; 161 return false; 162 } 163 } 164 if (currPass->hasVertexProgram()) 165 { 166 // Check vertex program version 167 if (!currPass->getVertexProgram()->isSupported() ) 168 { 169 // Can't do this one 170 compileErrors << "Pass " << passNum << 171 ": Vertex program " << currPass->getVertexProgram()->getName() 172 << " cannot be used - "; 173 if (currPass->getVertexProgram()->hasCompileError()) 174 compileErrors << "compile error."; 175 else 176 compileErrors << "not supported."; 177 178 compileErrors << std::endl; 179 return false; 180 } 181 } 182 if (currPass->hasTesselationHullProgram()) 183 { 184 // Check tesselation control program version 185 if (!currPass->getTesselationHullProgram()->isSupported() ) 186 { 187 // Can't do this one 188 compileErrors << "Pass " << passNum << 189 ": Tesselation Hull program " << currPass->getTesselationHullProgram()->getName() 190 << " cannot be used - "; 191 if (currPass->getTesselationHullProgram()->hasCompileError()) 192 compileErrors << "compile error."; 193 else 194 compileErrors << "not supported."; 195 196 compileErrors << std::endl; 197 return false; 198 } 199 } 200 if (currPass->hasTesselationDomainProgram()) 201 { 202 // Check tesselation control program version 203 if (!currPass->getTesselationDomainProgram()->isSupported() ) 204 { 205 // Can't do this one 206 compileErrors << "Pass " << passNum << 207 ": Tesselation Domain program " << currPass->getTesselationDomainProgram()->getName() 208 << " cannot be used - "; 209 if (currPass->getTesselationDomainProgram()->hasCompileError()) 210 compileErrors << "compile error."; 211 else 212 compileErrors << "not supported."; 213 214 compileErrors << std::endl; 215 return false; 216 } 217 } 218 if (currPass->hasGeometryProgram()) 219 { 220 // Check geometry program version 221 if (!currPass->getGeometryProgram()->isSupported() ) 222 { 223 // Can't do this one 224 compileErrors << "Pass " << passNum << 225 ": Geometry program " << currPass->getGeometryProgram()->getName() 226 << " cannot be used - "; 227 if (currPass->getGeometryProgram()->hasCompileError()) 228 compileErrors << "compile error."; 229 else 230 compileErrors << "not supported."; 231 232 compileErrors << std::endl; 233 return false; 234 } 235 } 236 if (currPass->hasFragmentProgram()) 237 { 238 // Check fragment program version 239 if (!currPass->getFragmentProgram()->isSupported()) 240 { 241 // Can't do this one 242 compileErrors << "Pass " << passNum << 243 ": Fragment program " << currPass->getFragmentProgram()->getName() 244 << " cannot be used - "; 245 if (currPass->getFragmentProgram()->hasCompileError()) 246 compileErrors << "compile error."; 247 else 248 compileErrors << "not supported."; 249 250 compileErrors << std::endl; 251 return false; 252 } 253 } 254 else 255 { 256 // Check a few fixed-function options in texture layers 257 Pass::TextureUnitStateIterator texi = currPass->getTextureUnitStateIterator(); 258 size_t texUnit = 0; 259 while (texi.hasMoreElements()) 260 { 261 TextureUnitState* tex = texi.getNext(); 262 // Any Cube textures? NB we make the assumption that any 263 // card capable of running fragment programs can support 264 // cubic textures, which has to be true, surely? 265 if (tex->is3D() && !caps->hasCapability(RSC_CUBEMAPPING)) 266 { 267 // Fail 268 compileErrors << "Pass " << passNum << 269 " Tex " << texUnit << 270 ": Cube maps not supported by current environment." 271 << std::endl; 272 return false; 273 } 274 // Any 3D textures? NB we make the assumption that any 275 // card capable of running fragment programs can support 276 // 3D textures, which has to be true, surely? 277 if (((tex->getTextureType() == TEX_TYPE_3D) || (tex->getTextureType() == TEX_TYPE_2D_ARRAY)) && 278 !caps->hasCapability(RSC_TEXTURE_3D)) 279 { 280 // Fail 281 compileErrors << "Pass " << passNum << 282 " Tex " << texUnit << 283 ": Volume textures not supported by current environment." 284 << std::endl; 285 return false; 286 } 287 // Any Dot3 blending? 288 if (tex->getColourBlendMode().operation == LBX_DOTPRODUCT && 289 !caps->hasCapability(RSC_DOT3)) 290 { 291 // Fail 292 compileErrors << "Pass " << passNum << 293 " Tex " << texUnit << 294 ": DOT3 blending not supported by current environment." 295 << std::endl; 296 return false; 297 } 298 ++texUnit; 299 } 300 301 // We're ok on operations, now we need to check # texture units 302 if (!currPass->hasFragmentProgram()) 303 { 304 // Keep splitting this pass so long as units requested > gpu units 305 while (numTexUnitsRequested > numTexUnits) 306 { 307 // chop this pass into many passes 308 currPass = currPass->_split(numTexUnits); 309 numTexUnitsRequested = currPass->getNumTextureUnitStates(); 310 // Advance pass number 311 ++passNum; 312 // Reset iterator 313 i = mPasses.begin() + passNum; 314 // Move the new pass to the right place (will have been created 315 // at the end, may be other passes in between) 316 assert(mPasses.back() == currPass); 317 std::copy_backward(i, (mPasses.end()-1), mPasses.end()); 318 *i = currPass; 319 // Adjust pass index 320 currPass->_notifyIndex(passNum); 321 } 322 } 323 } 324 325 } 326 // If we got this far, we're ok 327 return true; 328 } 329 //--------------------------------------------------------------------- checkGPURules(StringUtil::StrStreamType & errors)330 bool Technique::checkGPURules(StringUtil::StrStreamType& errors) 331 { 332 const RenderSystemCapabilities* caps = 333 Root::getSingleton().getRenderSystem()->getCapabilities(); 334 335 StringUtil::StrStreamType includeRules; 336 bool includeRulesPresent = false; 337 bool includeRuleMatched = false; 338 339 // Check vendors first 340 for (GPUVendorRuleList::const_iterator i = mGPUVendorRules.begin(); 341 i != mGPUVendorRules.end(); ++i) 342 { 343 if (i->includeOrExclude == INCLUDE) 344 { 345 includeRulesPresent = true; 346 includeRules << caps->vendorToString(i->vendor) << " "; 347 if (i->vendor == caps->getVendor()) 348 includeRuleMatched = true; 349 } 350 else // EXCLUDE 351 { 352 if (i->vendor == caps->getVendor()) 353 { 354 errors << "Excluded GPU vendor: " << caps->vendorToString(i->vendor) 355 << std::endl; 356 return false; 357 } 358 359 } 360 } 361 362 if (includeRulesPresent && !includeRuleMatched) 363 { 364 errors << "Failed to match GPU vendor: " << includeRules.str( ) 365 << std::endl; 366 return false; 367 } 368 369 // now check device names 370 includeRules.str(StringUtil::BLANK); 371 includeRulesPresent = false; 372 includeRuleMatched = false; 373 374 for (GPUDeviceNameRuleList::const_iterator i = mGPUDeviceNameRules.begin(); 375 i != mGPUDeviceNameRules.end(); ++i) 376 { 377 if (i->includeOrExclude == INCLUDE) 378 { 379 includeRulesPresent = true; 380 includeRules << i->devicePattern << " "; 381 if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive)) 382 includeRuleMatched = true; 383 } 384 else // EXCLUDE 385 { 386 if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive)) 387 { 388 errors << "Excluded GPU device: " << i->devicePattern 389 << std::endl; 390 return false; 391 } 392 393 } 394 } 395 396 if (includeRulesPresent && !includeRuleMatched) 397 { 398 errors << "Failed to match GPU device: " << includeRules.str( ) 399 << std::endl; 400 return false; 401 } 402 403 // passed 404 return true; 405 } 406 //----------------------------------------------------------------------------- createPass(void)407 Pass* Technique::createPass(void) 408 { 409 Pass* newPass = OGRE_NEW Pass(this, static_cast<unsigned short>(mPasses.size())); 410 mPasses.push_back(newPass); 411 return newPass; 412 } 413 //----------------------------------------------------------------------------- getPass(unsigned short index)414 Pass* Technique::getPass(unsigned short index) 415 { 416 assert(index < mPasses.size() && "Index out of bounds"); 417 return mPasses[index]; 418 } 419 //----------------------------------------------------------------------------- getPass(const String & name)420 Pass* Technique::getPass(const String& name) 421 { 422 Passes::iterator i = mPasses.begin(); 423 Passes::iterator iend = mPasses.end(); 424 Pass* foundPass = 0; 425 426 // iterate through techniques to find a match 427 while (i != iend) 428 { 429 if ( (*i)->getName() == name ) 430 { 431 foundPass = (*i); 432 break; 433 } 434 ++i; 435 } 436 437 return foundPass; 438 } 439 //----------------------------------------------------------------------------- getNumPasses(void) const440 unsigned short Technique::getNumPasses(void) const 441 { 442 return static_cast<unsigned short>(mPasses.size()); 443 } 444 //----------------------------------------------------------------------------- removePass(unsigned short index)445 void Technique::removePass(unsigned short index) 446 { 447 assert(index < mPasses.size() && "Index out of bounds"); 448 Passes::iterator i = mPasses.begin() + index; 449 (*i)->queueForDeletion(); 450 i = mPasses.erase(i); 451 // Adjust passes index 452 for (; i != mPasses.end(); ++i, ++index) 453 { 454 (*i)->_notifyIndex(index); 455 } 456 } 457 //----------------------------------------------------------------------------- removeAllPasses(void)458 void Technique::removeAllPasses(void) 459 { 460 Passes::iterator i, iend; 461 iend = mPasses.end(); 462 for (i = mPasses.begin(); i != iend; ++i) 463 { 464 (*i)->queueForDeletion(); 465 } 466 mPasses.clear(); 467 } 468 469 //----------------------------------------------------------------------------- movePass(const unsigned short sourceIndex,const unsigned short destinationIndex)470 bool Technique::movePass(const unsigned short sourceIndex, const unsigned short destinationIndex) 471 { 472 bool moveSuccessful = false; 473 474 // don't move the pass if source == destination 475 if (sourceIndex == destinationIndex) return true; 476 477 if( (sourceIndex < mPasses.size()) && (destinationIndex < mPasses.size())) 478 { 479 Passes::iterator i = mPasses.begin() + sourceIndex; 480 //Passes::iterator DestinationIterator = mPasses.begin() + destinationIndex; 481 482 Pass* pass = (*i); 483 mPasses.erase(i); 484 485 i = mPasses.begin() + destinationIndex; 486 487 mPasses.insert(i, pass); 488 489 // Adjust passes index 490 unsigned short beginIndex, endIndex; 491 if (destinationIndex > sourceIndex) 492 { 493 beginIndex = sourceIndex; 494 endIndex = destinationIndex; 495 } 496 else 497 { 498 beginIndex = destinationIndex; 499 endIndex = sourceIndex; 500 } 501 for (unsigned short index = beginIndex; index <= endIndex; ++index) 502 { 503 mPasses[index]->_notifyIndex(index); 504 } 505 moveSuccessful = true; 506 } 507 508 return moveSuccessful; 509 } 510 511 //----------------------------------------------------------------------------- getPassIterator(void)512 const Technique::PassIterator Technique::getPassIterator(void) 513 { 514 return PassIterator(mPasses.begin(), mPasses.end()); 515 } 516 //----------------------------------------------------------------------------- operator =(const Technique & rhs)517 Technique& Technique::operator=(const Technique& rhs) 518 { 519 mName = rhs.mName; 520 this->mIsSupported = rhs.mIsSupported; 521 this->mLodIndex = rhs.mLodIndex; 522 this->mSchemeIndex = rhs.mSchemeIndex; 523 this->mShadowCasterMaterial = rhs.mShadowCasterMaterial; 524 this->mShadowCasterMaterialName = rhs.mShadowCasterMaterialName; 525 this->mShadowReceiverMaterial = rhs.mShadowReceiverMaterial; 526 this->mShadowReceiverMaterialName = rhs.mShadowReceiverMaterialName; 527 this->mGPUVendorRules = rhs.mGPUVendorRules; 528 this->mGPUDeviceNameRules = rhs.mGPUDeviceNameRules; 529 530 // copy passes 531 removeAllPasses(); 532 Passes::const_iterator i, iend; 533 iend = rhs.mPasses.end(); 534 for (i = rhs.mPasses.begin(); i != iend; ++i) 535 { 536 Pass* p = OGRE_NEW Pass(this, (*i)->getIndex(), *(*i)); 537 mPasses.push_back(p); 538 } 539 // Compile for categorised illumination on demand 540 clearIlluminationPasses(); 541 mIlluminationPassesCompilationPhase = IPS_NOT_COMPILED; 542 return *this; 543 } 544 //----------------------------------------------------------------------------- isTransparent(void) const545 bool Technique::isTransparent(void) const 546 { 547 if (mPasses.empty()) 548 { 549 return false; 550 } 551 else 552 { 553 // Base decision on the transparency of the first pass 554 return mPasses[0]->isTransparent(); 555 } 556 } 557 //----------------------------------------------------------------------------- isTransparentSortingEnabled(void) const558 bool Technique::isTransparentSortingEnabled(void) const 559 { 560 if (mPasses.empty()) 561 { 562 return true; 563 } 564 else 565 { 566 // Base decision on the transparency of the first pass 567 return mPasses[0]->getTransparentSortingEnabled(); 568 } 569 } 570 //----------------------------------------------------------------------------- isTransparentSortingForced(void) const571 bool Technique::isTransparentSortingForced(void) const 572 { 573 if (mPasses.empty()) 574 { 575 return false; 576 } 577 else 578 { 579 // Base decision on the first pass 580 return mPasses[0]->getTransparentSortingForced(); 581 } 582 } 583 //----------------------------------------------------------------------------- isDepthWriteEnabled(void) const584 bool Technique::isDepthWriteEnabled(void) const 585 { 586 if (mPasses.empty()) 587 { 588 return false; 589 } 590 else 591 { 592 // Base decision on the depth settings of the first pass 593 return mPasses[0]->getDepthWriteEnabled(); 594 } 595 } 596 //----------------------------------------------------------------------------- isDepthCheckEnabled(void) const597 bool Technique::isDepthCheckEnabled(void) const 598 { 599 if (mPasses.empty()) 600 { 601 return false; 602 } 603 else 604 { 605 // Base decision on the depth settings of the first pass 606 return mPasses[0]->getDepthCheckEnabled(); 607 } 608 } 609 //----------------------------------------------------------------------------- hasColourWriteDisabled(void) const610 bool Technique::hasColourWriteDisabled(void) const 611 { 612 if (mPasses.empty()) 613 { 614 return true; 615 } 616 else 617 { 618 // Base decision on the colour write settings of the first pass 619 return !mPasses[0]->getColourWriteEnabled(); 620 } 621 } 622 //----------------------------------------------------------------------------- _prepare(void)623 void Technique::_prepare(void) 624 { 625 assert (mIsSupported && "This technique is not supported"); 626 // Load each pass 627 Passes::iterator i, iend; 628 iend = mPasses.end(); 629 for (i = mPasses.begin(); i != iend; ++i) 630 { 631 (*i)->_prepare(); 632 } 633 634 IlluminationPassList::iterator il, ilend; 635 ilend = mIlluminationPasses.end(); 636 for (il = mIlluminationPasses.begin(); il != ilend; ++il) 637 { 638 if((*il)->pass != (*il)->originalPass) 639 (*il)->pass->_prepare(); 640 } 641 } 642 //----------------------------------------------------------------------------- _unprepare(void)643 void Technique::_unprepare(void) 644 { 645 // Unload each pass 646 Passes::iterator i, iend; 647 iend = mPasses.end(); 648 for (i = mPasses.begin(); i != iend; ++i) 649 { 650 (*i)->_unprepare(); 651 } 652 } 653 //----------------------------------------------------------------------------- _load(void)654 void Technique::_load(void) 655 { 656 assert (mIsSupported && "This technique is not supported"); 657 // Load each pass 658 Passes::iterator i, iend; 659 iend = mPasses.end(); 660 for (i = mPasses.begin(); i != iend; ++i) 661 { 662 (*i)->_load(); 663 } 664 665 IlluminationPassList::iterator il, ilend; 666 ilend = mIlluminationPasses.end(); 667 for (il = mIlluminationPasses.begin(); il != ilend; ++il) 668 { 669 if((*il)->pass != (*il)->originalPass) 670 (*il)->pass->_load(); 671 } 672 673 if (!mShadowCasterMaterial.isNull()) 674 { 675 mShadowCasterMaterial->load(); 676 } 677 else if (!mShadowCasterMaterialName.empty()) 678 { 679 // in case we could not get material as it wasn't yet parsed/existent at that time. 680 mShadowCasterMaterial = MaterialManager::getSingleton().getByName(mShadowCasterMaterialName); 681 if (!mShadowCasterMaterial.isNull()) 682 mShadowCasterMaterial->load(); 683 } 684 if (!mShadowReceiverMaterial.isNull()) 685 { 686 mShadowReceiverMaterial->load(); 687 } 688 else if (!mShadowReceiverMaterialName.empty()) 689 { 690 // in case we could not get material as it wasn't yet parsed/existent at that time. 691 mShadowReceiverMaterial = MaterialManager::getSingleton().getByName(mShadowReceiverMaterialName); 692 if (!mShadowReceiverMaterial.isNull()) 693 mShadowReceiverMaterial->load(); 694 } 695 } 696 //----------------------------------------------------------------------------- _unload(void)697 void Technique::_unload(void) 698 { 699 // Unload each pass 700 Passes::iterator i, iend; 701 iend = mPasses.end(); 702 for (i = mPasses.begin(); i != iend; ++i) 703 { 704 (*i)->_unload(); 705 } 706 } 707 //----------------------------------------------------------------------------- isLoaded(void) const708 bool Technique::isLoaded(void) const 709 { 710 // Only supported technique will be loaded 711 return mParent->isLoaded() && mIsSupported; 712 } 713 //----------------------------------------------------------------------- setPointSize(Real ps)714 void Technique::setPointSize(Real ps) 715 { 716 Passes::iterator i, iend; 717 iend = mPasses.end(); 718 for (i = mPasses.begin(); i != iend; ++i) 719 { 720 (*i)->setPointSize(ps); 721 } 722 723 } 724 //----------------------------------------------------------------------- setAmbient(Real red,Real green,Real blue)725 void Technique::setAmbient(Real red, Real green, Real blue) 726 { 727 setAmbient(ColourValue(red, green, blue)); 728 729 730 } 731 //----------------------------------------------------------------------- setAmbient(const ColourValue & ambient)732 void Technique::setAmbient(const ColourValue& ambient) 733 { 734 Passes::iterator i, iend; 735 iend = mPasses.end(); 736 for (i = mPasses.begin(); i != iend; ++i) 737 { 738 (*i)->setAmbient(ambient); 739 } 740 } 741 //----------------------------------------------------------------------- setDiffuse(Real red,Real green,Real blue,Real alpha)742 void Technique::setDiffuse(Real red, Real green, Real blue, Real alpha) 743 { 744 Passes::iterator i, iend; 745 iend = mPasses.end(); 746 for (i = mPasses.begin(); i != iend; ++i) 747 { 748 (*i)->setDiffuse(red, green, blue, alpha); 749 } 750 } 751 //----------------------------------------------------------------------- setDiffuse(const ColourValue & diffuse)752 void Technique::setDiffuse(const ColourValue& diffuse) 753 { 754 setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a); 755 } 756 //----------------------------------------------------------------------- setSpecular(Real red,Real green,Real blue,Real alpha)757 void Technique::setSpecular(Real red, Real green, Real blue, Real alpha) 758 { 759 Passes::iterator i, iend; 760 iend = mPasses.end(); 761 for (i = mPasses.begin(); i != iend; ++i) 762 { 763 (*i)->setSpecular(red, green, blue, alpha); 764 } 765 } 766 //----------------------------------------------------------------------- setSpecular(const ColourValue & specular)767 void Technique::setSpecular(const ColourValue& specular) 768 { 769 setSpecular(specular.r, specular.g, specular.b, specular.a); 770 } 771 //----------------------------------------------------------------------- setShininess(Real val)772 void Technique::setShininess(Real val) 773 { 774 Passes::iterator i, iend; 775 iend = mPasses.end(); 776 for (i = mPasses.begin(); i != iend; ++i) 777 { 778 (*i)->setShininess(val); 779 } 780 } 781 //----------------------------------------------------------------------- setSelfIllumination(Real red,Real green,Real blue)782 void Technique::setSelfIllumination(Real red, Real green, Real blue) 783 { 784 setSelfIllumination(ColourValue(red, green, blue)); 785 } 786 //----------------------------------------------------------------------- setSelfIllumination(const ColourValue & selfIllum)787 void Technique::setSelfIllumination(const ColourValue& selfIllum) 788 { 789 Passes::iterator i, iend; 790 iend = mPasses.end(); 791 for (i = mPasses.begin(); i != iend; ++i) 792 { 793 (*i)->setSelfIllumination(selfIllum); 794 } 795 } 796 //----------------------------------------------------------------------- setDepthCheckEnabled(bool enabled)797 void Technique::setDepthCheckEnabled(bool enabled) 798 { 799 Passes::iterator i, iend; 800 iend = mPasses.end(); 801 for (i = mPasses.begin(); i != iend; ++i) 802 { 803 (*i)->setDepthCheckEnabled(enabled); 804 } 805 } 806 //----------------------------------------------------------------------- setDepthWriteEnabled(bool enabled)807 void Technique::setDepthWriteEnabled(bool enabled) 808 { 809 Passes::iterator i, iend; 810 iend = mPasses.end(); 811 for (i = mPasses.begin(); i != iend; ++i) 812 { 813 (*i)->setDepthWriteEnabled(enabled); 814 } 815 } 816 //----------------------------------------------------------------------- setDepthFunction(CompareFunction func)817 void Technique::setDepthFunction( CompareFunction func ) 818 { 819 Passes::iterator i, iend; 820 iend = mPasses.end(); 821 for (i = mPasses.begin(); i != iend; ++i) 822 { 823 (*i)->setDepthFunction(func); 824 } 825 } 826 //----------------------------------------------------------------------- setColourWriteEnabled(bool enabled)827 void Technique::setColourWriteEnabled(bool enabled) 828 { 829 Passes::iterator i, iend; 830 iend = mPasses.end(); 831 for (i = mPasses.begin(); i != iend; ++i) 832 { 833 (*i)->setColourWriteEnabled(enabled); 834 } 835 } 836 //----------------------------------------------------------------------- setCullingMode(CullingMode mode)837 void Technique::setCullingMode( CullingMode mode ) 838 { 839 Passes::iterator i, iend; 840 iend = mPasses.end(); 841 for (i = mPasses.begin(); i != iend; ++i) 842 { 843 (*i)->setCullingMode(mode); 844 } 845 } 846 //----------------------------------------------------------------------- setManualCullingMode(ManualCullingMode mode)847 void Technique::setManualCullingMode( ManualCullingMode mode ) 848 { 849 Passes::iterator i, iend; 850 iend = mPasses.end(); 851 for (i = mPasses.begin(); i != iend; ++i) 852 { 853 (*i)->setManualCullingMode(mode); 854 } 855 } 856 //----------------------------------------------------------------------- setLightingEnabled(bool enabled)857 void Technique::setLightingEnabled(bool enabled) 858 { 859 Passes::iterator i, iend; 860 iend = mPasses.end(); 861 for (i = mPasses.begin(); i != iend; ++i) 862 { 863 (*i)->setLightingEnabled(enabled); 864 } 865 } 866 //----------------------------------------------------------------------- setShadingMode(ShadeOptions mode)867 void Technique::setShadingMode( ShadeOptions mode ) 868 { 869 Passes::iterator i, iend; 870 iend = mPasses.end(); 871 for (i = mPasses.begin(); i != iend; ++i) 872 { 873 (*i)->setShadingMode(mode); 874 } 875 } 876 //----------------------------------------------------------------------- setFog(bool overrideScene,FogMode mode,const ColourValue & colour,Real expDensity,Real linearStart,Real linearEnd)877 void Technique::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, 878 Real expDensity, Real linearStart, Real linearEnd) 879 { 880 Passes::iterator i, iend; 881 iend = mPasses.end(); 882 for (i = mPasses.begin(); i != iend; ++i) 883 { 884 (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd); 885 } 886 } 887 //----------------------------------------------------------------------- setDepthBias(float constantBias,float slopeScaleBias)888 void Technique::setDepthBias(float constantBias, float slopeScaleBias) 889 { 890 Passes::iterator i, iend; 891 iend = mPasses.end(); 892 for (i = mPasses.begin(); i != iend; ++i) 893 { 894 (*i)->setDepthBias(constantBias, slopeScaleBias); 895 } 896 } 897 //----------------------------------------------------------------------- setTextureFiltering(TextureFilterOptions filterType)898 void Technique::setTextureFiltering(TextureFilterOptions filterType) 899 { 900 Passes::iterator i, iend; 901 iend = mPasses.end(); 902 for (i = mPasses.begin(); i != iend; ++i) 903 { 904 (*i)->setTextureFiltering(filterType); 905 } 906 } 907 // -------------------------------------------------------------------- setTextureAnisotropy(unsigned int maxAniso)908 void Technique::setTextureAnisotropy(unsigned int maxAniso) 909 { 910 Passes::iterator i, iend; 911 iend = mPasses.end(); 912 for (i = mPasses.begin(); i != iend; ++i) 913 { 914 (*i)->setTextureAnisotropy(maxAniso); 915 } 916 } 917 // -------------------------------------------------------------------- setSceneBlending(const SceneBlendType sbt)918 void Technique::setSceneBlending( const SceneBlendType sbt ) 919 { 920 Passes::iterator i, iend; 921 iend = mPasses.end(); 922 for (i = mPasses.begin(); i != iend; ++i) 923 { 924 (*i)->setSceneBlending(sbt); 925 } 926 } 927 // -------------------------------------------------------------------- setSeparateSceneBlending(const SceneBlendType sbt,const SceneBlendType sbta)928 void Technique::setSeparateSceneBlending( const SceneBlendType sbt, const SceneBlendType sbta ) 929 { 930 Passes::iterator i, iend; 931 iend = mPasses.end(); 932 for (i = mPasses.begin(); i != iend; ++i) 933 { 934 (*i)->setSeparateSceneBlending(sbt, sbta); 935 } 936 } 937 // -------------------------------------------------------------------- setSceneBlending(const SceneBlendFactor sourceFactor,const SceneBlendFactor destFactor)938 void Technique::setSceneBlending( const SceneBlendFactor sourceFactor, 939 const SceneBlendFactor destFactor) 940 { 941 Passes::iterator i, iend; 942 iend = mPasses.end(); 943 for (i = mPasses.begin(); i != iend; ++i) 944 { 945 (*i)->setSceneBlending(sourceFactor, destFactor); 946 } 947 } 948 // -------------------------------------------------------------------- setSeparateSceneBlending(const SceneBlendFactor sourceFactor,const SceneBlendFactor destFactor,const SceneBlendFactor sourceFactorAlpha,const SceneBlendFactor destFactorAlpha)949 void Technique::setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha) 950 { 951 Passes::iterator i, iend; 952 iend = mPasses.end(); 953 for (i = mPasses.begin(); i != iend; ++i) 954 { 955 (*i)->setSeparateSceneBlending(sourceFactor, destFactor, sourceFactorAlpha, destFactorAlpha); 956 } 957 } 958 959 // -------------------------------------------------------------------- setName(const String & name)960 void Technique::setName(const String& name) 961 { 962 mName = name; 963 } 964 965 966 //----------------------------------------------------------------------- _notifyNeedsRecompile(void)967 void Technique::_notifyNeedsRecompile(void) 968 { 969 // Disable require to recompile when splitting illumination passes 970 if (mIlluminationPassesCompilationPhase != IPS_COMPILE_DISABLED) 971 { 972 mParent->_notifyNeedsRecompile(); 973 } 974 } 975 //----------------------------------------------------------------------- setLodIndex(unsigned short index)976 void Technique::setLodIndex(unsigned short index) 977 { 978 mLodIndex = index; 979 _notifyNeedsRecompile(); 980 } 981 //----------------------------------------------------------------------- setSchemeName(const String & schemeName)982 void Technique::setSchemeName(const String& schemeName) 983 { 984 mSchemeIndex = MaterialManager::getSingleton()._getSchemeIndex(schemeName); 985 _notifyNeedsRecompile(); 986 } 987 //----------------------------------------------------------------------- getSchemeName(void) const988 const String& Technique::getSchemeName(void) const 989 { 990 return MaterialManager::getSingleton()._getSchemeName(mSchemeIndex); 991 } 992 //----------------------------------------------------------------------- _getSchemeIndex(void) const993 unsigned short Technique::_getSchemeIndex(void) const 994 { 995 return mSchemeIndex; 996 } 997 //--------------------------------------------------------------------- checkManuallyOrganisedIlluminationPasses()998 bool Technique::checkManuallyOrganisedIlluminationPasses() 999 { 1000 // first check whether all passes have manually assigned illumination 1001 Passes::iterator i, ibegin, iend; 1002 ibegin = mPasses.begin(); 1003 iend = mPasses.end(); 1004 1005 for (i = ibegin; i != iend; ++i) 1006 { 1007 if ((*i)->getIlluminationStage() == IS_UNKNOWN) 1008 return false; 1009 } 1010 1011 // ok, all manually controlled, so just use that 1012 for (i = ibegin; i != iend; ++i) 1013 { 1014 IlluminationPass* iPass = OGRE_NEW IlluminationPass(); 1015 iPass->destroyOnShutdown = false; 1016 iPass->originalPass = iPass->pass = *i; 1017 iPass->stage = (*i)->getIlluminationStage(); 1018 mIlluminationPasses.push_back(iPass); 1019 } 1020 1021 return true; 1022 } 1023 //----------------------------------------------------------------------- _compileIlluminationPasses(void)1024 void Technique::_compileIlluminationPasses(void) 1025 { 1026 clearIlluminationPasses(); 1027 1028 if (!checkManuallyOrganisedIlluminationPasses()) 1029 { 1030 // Build based on our own heuristics 1031 1032 Passes::iterator i, iend; 1033 iend = mPasses.end(); 1034 i = mPasses.begin(); 1035 1036 IlluminationStage iStage = IS_AMBIENT; 1037 1038 bool haveAmbient = false; 1039 while (i != iend) 1040 { 1041 IlluminationPass* iPass; 1042 Pass* p = *i; 1043 switch(iStage) 1044 { 1045 case IS_AMBIENT: 1046 // Keep looking for ambient only 1047 if (p->isAmbientOnly()) 1048 { 1049 // Add this pass wholesale 1050 iPass = OGRE_NEW IlluminationPass(); 1051 iPass->destroyOnShutdown = false; 1052 iPass->originalPass = iPass->pass = p; 1053 iPass->stage = iStage; 1054 mIlluminationPasses.push_back(iPass); 1055 haveAmbient = true; 1056 // progress to next pass 1057 ++i; 1058 } 1059 else 1060 { 1061 // Split off any ambient part 1062 if (p->getAmbient() != ColourValue::Black || 1063 p->getSelfIllumination() != ColourValue::Black || 1064 p->getAlphaRejectFunction() != CMPF_ALWAYS_PASS) 1065 { 1066 // Copy existing pass 1067 Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p); 1068 if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS) 1069 { 1070 // Alpha rejection passes must retain their transparency, so 1071 // we allow the texture units, but override the colour functions 1072 Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator(); 1073 while (tusi.hasMoreElements()) 1074 { 1075 TextureUnitState* tus = tusi.getNext(); 1076 tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT); 1077 } 1078 } 1079 else 1080 { 1081 // Remove any texture units 1082 newPass->removeAllTextureUnitStates(); 1083 } 1084 // Remove any fragment program 1085 if (newPass->hasFragmentProgram()) 1086 newPass->setFragmentProgram(""); 1087 // We have to leave vertex program alone (if any) and 1088 // just trust that the author is using light bindings, which 1089 // we will ensure there are none in the ambient pass 1090 newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a); // Preserving alpha 1091 newPass->setSpecular(ColourValue::Black); 1092 1093 // Calculate hash value for new pass, because we are compiling 1094 // illumination passes on demand, which will loss hash calculate 1095 // before it add to render queue first time. 1096 newPass->_recalculateHash(); 1097 1098 iPass = OGRE_NEW IlluminationPass(); 1099 iPass->destroyOnShutdown = true; 1100 iPass->originalPass = p; 1101 iPass->pass = newPass; 1102 iPass->stage = iStage; 1103 1104 mIlluminationPasses.push_back(iPass); 1105 haveAmbient = true; 1106 1107 } 1108 1109 if (!haveAmbient) 1110 { 1111 // Make up a new basic pass 1112 Pass* newPass = OGRE_NEW Pass(this, p->getIndex()); 1113 newPass->setAmbient(ColourValue::Black); 1114 newPass->setDiffuse(ColourValue::Black); 1115 1116 // Calculate hash value for new pass, because we are compiling 1117 // illumination passes on demand, which will loss hash calculate 1118 // before it add to render queue first time. 1119 newPass->_recalculateHash(); 1120 1121 iPass = OGRE_NEW IlluminationPass(); 1122 iPass->destroyOnShutdown = true; 1123 iPass->originalPass = p; 1124 iPass->pass = newPass; 1125 iPass->stage = iStage; 1126 mIlluminationPasses.push_back(iPass); 1127 haveAmbient = true; 1128 } 1129 // This means we're done with ambients, progress to per-light 1130 iStage = IS_PER_LIGHT; 1131 } 1132 break; 1133 case IS_PER_LIGHT: 1134 if (p->getIteratePerLight()) 1135 { 1136 // If this is per-light already, use it directly 1137 iPass = OGRE_NEW IlluminationPass(); 1138 iPass->destroyOnShutdown = false; 1139 iPass->originalPass = iPass->pass = p; 1140 iPass->stage = iStage; 1141 mIlluminationPasses.push_back(iPass); 1142 // progress to next pass 1143 ++i; 1144 } 1145 else 1146 { 1147 // Split off per-light details (can only be done for one) 1148 if (p->getLightingEnabled() && 1149 (p->getDiffuse() != ColourValue::Black || 1150 p->getSpecular() != ColourValue::Black)) 1151 { 1152 // Copy existing pass 1153 Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p); 1154 if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS) 1155 { 1156 // Alpha rejection passes must retain their transparency, so 1157 // we allow the texture units, but override the colour functions 1158 Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator(); 1159 while (tusi.hasMoreElements()) 1160 { 1161 TextureUnitState* tus = tusi.getNext(); 1162 tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT); 1163 } 1164 } 1165 else 1166 { 1167 // remove texture units 1168 newPass->removeAllTextureUnitStates(); 1169 } 1170 // remove fragment programs 1171 if (newPass->hasFragmentProgram()) 1172 newPass->setFragmentProgram(""); 1173 // Cannot remove vertex program, have to assume that 1174 // it will process diffuse lights, ambient will be turned off 1175 newPass->setAmbient(ColourValue::Black); 1176 newPass->setSelfIllumination(ColourValue::Black); 1177 // must be additive 1178 newPass->setSceneBlending(SBF_ONE, SBF_ONE); 1179 1180 // Calculate hash value for new pass, because we are compiling 1181 // illumination passes on demand, which will loss hash calculate 1182 // before it add to render queue first time. 1183 newPass->_recalculateHash(); 1184 1185 iPass = OGRE_NEW IlluminationPass(); 1186 iPass->destroyOnShutdown = true; 1187 iPass->originalPass = p; 1188 iPass->pass = newPass; 1189 iPass->stage = iStage; 1190 1191 mIlluminationPasses.push_back(iPass); 1192 1193 } 1194 // This means the end of per-light passes 1195 iStage = IS_DECAL; 1196 } 1197 break; 1198 case IS_DECAL: 1199 // We just want a 'lighting off' pass to finish off 1200 // and only if there are texture units 1201 if (p->getNumTextureUnitStates() > 0) 1202 { 1203 if (!p->getLightingEnabled()) 1204 { 1205 // we assume this pass already combines as required with the scene 1206 iPass = OGRE_NEW IlluminationPass(); 1207 iPass->destroyOnShutdown = false; 1208 iPass->originalPass = iPass->pass = p; 1209 iPass->stage = iStage; 1210 mIlluminationPasses.push_back(iPass); 1211 } 1212 else 1213 { 1214 // Copy the pass and tweak away the lighting parts 1215 Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p); 1216 newPass->setAmbient(ColourValue::Black); 1217 newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a); // Preserving alpha 1218 newPass->setSpecular(ColourValue::Black); 1219 newPass->setSelfIllumination(ColourValue::Black); 1220 newPass->setLightingEnabled(false); 1221 newPass->setIteratePerLight(false, false); 1222 // modulate 1223 newPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO); 1224 1225 // Calculate hash value for new pass, because we are compiling 1226 // illumination passes on demand, which will loss hash calculate 1227 // before it add to render queue first time. 1228 newPass->_recalculateHash(); 1229 1230 // NB there is nothing we can do about vertex & fragment 1231 // programs here, so people will just have to make their 1232 // programs friendly-like if they want to use this technique 1233 iPass = OGRE_NEW IlluminationPass(); 1234 iPass->destroyOnShutdown = true; 1235 iPass->originalPass = p; 1236 iPass->pass = newPass; 1237 iPass->stage = iStage; 1238 mIlluminationPasses.push_back(iPass); 1239 1240 } 1241 } 1242 ++i; // always increment on decal, since nothing more to do with this pass 1243 1244 break; 1245 case IS_UNKNOWN: 1246 break; 1247 } 1248 } 1249 } 1250 1251 } 1252 //----------------------------------------------------------------------- clearIlluminationPasses(void)1253 void Technique::clearIlluminationPasses(void) 1254 { 1255 IlluminationPassList::iterator i, iend; 1256 iend = mIlluminationPasses.end(); 1257 for (i = mIlluminationPasses.begin(); i != iend; ++i) 1258 { 1259 if ((*i)->destroyOnShutdown) 1260 { 1261 (*i)->pass->queueForDeletion(); 1262 } 1263 OGRE_DELETE *i; 1264 } 1265 mIlluminationPasses.clear(); 1266 } 1267 //----------------------------------------------------------------------- 1268 const Technique::IlluminationPassIterator getIlluminationPassIterator(void)1269 Technique::getIlluminationPassIterator(void) 1270 { 1271 IlluminationPassesState targetState = IPS_COMPILED; 1272 if (mIlluminationPassesCompilationPhase != targetState) 1273 { 1274 // prevents parent->_notifyNeedsRecompile() call during compile 1275 mIlluminationPassesCompilationPhase = IPS_COMPILE_DISABLED; 1276 // Splitting the passes into illumination passes 1277 _compileIlluminationPasses(); 1278 // Mark that illumination passes compilation finished 1279 mIlluminationPassesCompilationPhase = targetState; 1280 } 1281 1282 return IlluminationPassIterator(mIlluminationPasses.begin(), 1283 mIlluminationPasses.end()); 1284 } 1285 //----------------------------------------------------------------------- getResourceGroup(void) const1286 const String& Technique::getResourceGroup(void) const 1287 { 1288 return mParent->getGroup(); 1289 } 1290 1291 //----------------------------------------------------------------------- applyTextureAliases(const AliasTextureNamePairList & aliasList,const bool apply) const1292 bool Technique::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const 1293 { 1294 // iterate through passes and apply texture alias 1295 Passes::const_iterator i, iend; 1296 iend = mPasses.end(); 1297 bool testResult = false; 1298 1299 for(i = mPasses.begin(); i != iend; ++i) 1300 { 1301 if ((*i)->applyTextureAliases(aliasList, apply)) 1302 testResult = true; 1303 } 1304 1305 return testResult; 1306 } 1307 //----------------------------------------------------------------------- getShadowCasterMaterial() const1308 Ogre::MaterialPtr Technique::getShadowCasterMaterial() const 1309 { 1310 return mShadowCasterMaterial; 1311 } 1312 //----------------------------------------------------------------------- setShadowCasterMaterial(Ogre::MaterialPtr val)1313 void Technique::setShadowCasterMaterial(Ogre::MaterialPtr val) 1314 { 1315 if (val.isNull()) 1316 { 1317 mShadowCasterMaterial.setNull(); 1318 mShadowCasterMaterialName.clear(); 1319 } 1320 else 1321 { 1322 mShadowCasterMaterial = val; 1323 mShadowCasterMaterialName = val->getName(); 1324 } 1325 } 1326 //----------------------------------------------------------------------- setShadowCasterMaterial(const Ogre::String & name)1327 void Technique::setShadowCasterMaterial(const Ogre::String &name) 1328 { 1329 mShadowCasterMaterialName = name; 1330 mShadowCasterMaterial = MaterialManager::getSingleton().getByName(name); 1331 } 1332 //----------------------------------------------------------------------- getShadowReceiverMaterial() const1333 Ogre::MaterialPtr Technique::getShadowReceiverMaterial() const 1334 { 1335 return mShadowReceiverMaterial; 1336 } 1337 //----------------------------------------------------------------------- setShadowReceiverMaterial(Ogre::MaterialPtr val)1338 void Technique::setShadowReceiverMaterial(Ogre::MaterialPtr val) 1339 { 1340 if (val.isNull()) 1341 { 1342 mShadowReceiverMaterial.setNull(); 1343 mShadowReceiverMaterialName.clear(); 1344 } 1345 else 1346 { 1347 mShadowReceiverMaterial = val; 1348 mShadowReceiverMaterialName = val->getName(); 1349 } 1350 } 1351 //----------------------------------------------------------------------- setShadowReceiverMaterial(const Ogre::String & name)1352 void Technique::setShadowReceiverMaterial(const Ogre::String &name) 1353 { 1354 mShadowReceiverMaterialName = name; 1355 mShadowReceiverMaterial = MaterialManager::getSingleton().getByName(name); 1356 } 1357 //--------------------------------------------------------------------- addGPUVendorRule(GPUVendor vendor,Technique::IncludeOrExclude includeOrExclude)1358 void Technique::addGPUVendorRule(GPUVendor vendor, Technique::IncludeOrExclude includeOrExclude) 1359 { 1360 addGPUVendorRule(GPUVendorRule(vendor, includeOrExclude)); 1361 } 1362 //--------------------------------------------------------------------- addGPUVendorRule(const Technique::GPUVendorRule & rule)1363 void Technique::addGPUVendorRule(const Technique::GPUVendorRule& rule) 1364 { 1365 // remove duplicates 1366 removeGPUVendorRule(rule.vendor); 1367 mGPUVendorRules.push_back(rule); 1368 } 1369 //--------------------------------------------------------------------- removeGPUVendorRule(GPUVendor vendor)1370 void Technique::removeGPUVendorRule(GPUVendor vendor) 1371 { 1372 for (GPUVendorRuleList::iterator i = mGPUVendorRules.begin(); i != mGPUVendorRules.end(); ) 1373 { 1374 if (i->vendor == vendor) 1375 i = mGPUVendorRules.erase(i); 1376 else 1377 ++i; 1378 } 1379 } 1380 //--------------------------------------------------------------------- getGPUVendorRuleIterator() const1381 Technique::GPUVendorRuleIterator Technique::getGPUVendorRuleIterator() const 1382 { 1383 return GPUVendorRuleIterator(mGPUVendorRules.begin(), mGPUVendorRules.end()); 1384 } 1385 //--------------------------------------------------------------------- addGPUDeviceNameRule(const String & devicePattern,Technique::IncludeOrExclude includeOrExclude,bool caseSensitive)1386 void Technique::addGPUDeviceNameRule(const String& devicePattern, 1387 Technique::IncludeOrExclude includeOrExclude, bool caseSensitive) 1388 { 1389 addGPUDeviceNameRule(GPUDeviceNameRule(devicePattern, includeOrExclude, caseSensitive)); 1390 } 1391 //--------------------------------------------------------------------- addGPUDeviceNameRule(const Technique::GPUDeviceNameRule & rule)1392 void Technique::addGPUDeviceNameRule(const Technique::GPUDeviceNameRule& rule) 1393 { 1394 // remove duplicates 1395 removeGPUDeviceNameRule(rule.devicePattern); 1396 mGPUDeviceNameRules.push_back(rule); 1397 } 1398 //--------------------------------------------------------------------- removeGPUDeviceNameRule(const String & devicePattern)1399 void Technique::removeGPUDeviceNameRule(const String& devicePattern) 1400 { 1401 for (GPUDeviceNameRuleList::iterator i = mGPUDeviceNameRules.begin(); i != mGPUDeviceNameRules.end(); ) 1402 { 1403 if (i->devicePattern == devicePattern) 1404 i = mGPUDeviceNameRules.erase(i); 1405 else 1406 ++i; 1407 } 1408 } 1409 //--------------------------------------------------------------------- getGPUDeviceNameRuleIterator() const1410 Technique::GPUDeviceNameRuleIterator Technique::getGPUDeviceNameRuleIterator() const 1411 { 1412 return GPUDeviceNameRuleIterator(mGPUDeviceNameRules.begin(), mGPUDeviceNameRules.end()); 1413 } 1414 //--------------------------------------------------------------------- 1415 1416 1417 } 1418