matInstance.cpp
Engine/source/materials/matInstance.cpp
Classes:
Public Defines
define
MATINSTPARAMSET(handle, f) (!mParameters) \ return; \ (dynamic_cast<*>(handle), "Invalid handle type!"); \ MatInstanceParameterHandle* mph = static_cast<*>(handle); \ mParameters->set(mph->mProcessedHandle, f); \
Detailed Description
Public Defines
MATINSTPARAMSET(handle, f) (!mParameters) \ return; \ (dynamic_cast<*>(handle), "Invalid handle type!"); \ MatInstanceParameterHandle* mph = static_cast<*>(handle); \ mParameters->set(mph->mProcessedHandle, f); \
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "materials/matInstance.h" 26 27#include "materials/materialManager.h" 28#include "materials/customMaterialDefinition.h" 29#include "materials/processedMaterial.h" 30#include "materials/processedShaderMaterial.h" 31#include "materials/processedCustomMaterial.h" 32#include "materials/materialFeatureTypes.h" 33#include "shaderGen/featureMgr.h" 34#include "gfx/gfxDevice.h" 35#include "gfx/sim/cubemapData.h" 36#include "gfx/gfxCubemap.h" 37#include "core/util/safeDelete.h" 38#include "ts/tsShape.h" 39 40#include "gui/controls/guiTreeViewCtrl.h" 41 42class MatInstParameters; 43 44class MatInstanceParameterHandle : public MaterialParameterHandle 45{ 46public: 47 virtual ~MatInstanceParameterHandle() {} 48 MatInstanceParameterHandle(const String& name); 49 50 void loadHandle(ProcessedMaterial* pmat); 51 52 // MaterialParameterHandle interface 53 const String& getName() const { return mName; } 54 virtual bool isValid() const; 55 virtual S32 getSamplerRegister( U32 pass ) const; 56private: 57 friend class MatInstParameters; 58 String mName; 59 MaterialParameterHandle* mProcessedHandle; 60}; 61 62MatInstanceParameterHandle::MatInstanceParameterHandle(const String& name) 63{ 64 mName = name; 65 mProcessedHandle = NULL; 66} 67 68bool MatInstanceParameterHandle::isValid() const 69{ 70 return mProcessedHandle && mProcessedHandle->isValid(); 71} 72 73S32 MatInstanceParameterHandle::getSamplerRegister( U32 pass ) const 74{ 75 if ( !mProcessedHandle ) 76 return -1; 77 return mProcessedHandle->getSamplerRegister( pass ); 78} 79 80void MatInstanceParameterHandle::loadHandle(ProcessedMaterial* pmat) 81{ 82 mProcessedHandle = pmat->getMaterialParameterHandle(mName); 83} 84 85MatInstParameters::MatInstParameters() 86{ 87 mOwnParameters = false; 88 mParameters = NULL; 89} 90 91MatInstParameters::MatInstParameters(MaterialParameters* matParams) 92{ 93 mOwnParameters = false; 94 mParameters = matParams; 95} 96 97void MatInstParameters::loadParameters(ProcessedMaterial* pmat) 98{ 99 mOwnParameters = true; 100 mParameters = pmat->allocMaterialParameters(); 101} 102 103MatInstParameters::~MatInstParameters() 104{ 105 if (mOwnParameters) 106 SAFE_DELETE(mParameters); 107} 108 109const Vector<GFXShaderConstDesc>& MatInstParameters::getShaderConstDesc() const 110{ 111 return mParameters->getShaderConstDesc(); 112} 113 114U32 MatInstParameters::getAlignmentValue(const GFXShaderConstType constType) 115{ 116 return mParameters->getAlignmentValue(constType); 117} 118 119#define MATINSTPARAMSET(handle, f) \ 120 if (!mParameters) \ 121 return; \ 122 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); \ 123 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); \ 124 mParameters->set(mph->mProcessedHandle, f); \ 125 126void MatInstParameters::set(MaterialParameterHandle* handle, const F32 f) 127{ 128 MATINSTPARAMSET(handle, f); 129} 130 131void MatInstParameters::set(MaterialParameterHandle* handle, const Point2F& fv) 132{ 133 MATINSTPARAMSET(handle, fv); 134} 135 136void MatInstParameters::set(MaterialParameterHandle* handle, const Point3F& fv) 137{ 138 MATINSTPARAMSET(handle, fv); 139} 140 141void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv) 142{ 143 MATINSTPARAMSET(handle, fv); 144} 145 146void MatInstParameters::set(MaterialParameterHandle* handle, const LinearColorF& fv) 147{ 148 MATINSTPARAMSET(handle, fv); 149} 150 151void MatInstParameters::set(MaterialParameterHandle* handle, const S32 f) 152{ 153 MATINSTPARAMSET(handle, f); 154} 155 156void MatInstParameters::set(MaterialParameterHandle* handle, const Point2I& fv) 157{ 158 MATINSTPARAMSET(handle, fv); 159} 160 161void MatInstParameters::set(MaterialParameterHandle* handle, const Point3I& fv) 162{ 163 MATINSTPARAMSET(handle, fv); 164} 165 166void MatInstParameters::set(MaterialParameterHandle* handle, const Point4I& fv) 167{ 168 MATINSTPARAMSET(handle, fv); 169} 170 171void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv) 172{ 173 MATINSTPARAMSET(handle, fv); 174} 175 176void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv) 177{ 178 MATINSTPARAMSET(handle, fv); 179} 180 181void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv) 182{ 183 MATINSTPARAMSET(handle, fv); 184} 185 186void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv) 187{ 188 MATINSTPARAMSET(handle, fv); 189} 190 191void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv) 192{ 193 MATINSTPARAMSET(handle, fv); 194} 195 196void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv) 197{ 198 MATINSTPARAMSET(handle, fv); 199} 200 201void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv) 202{ 203 MATINSTPARAMSET(handle, fv); 204} 205 206void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv) 207{ 208 MATINSTPARAMSET(handle, fv); 209} 210 211void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) 212{ 213 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 214 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 215 mParameters->set(mph->mProcessedHandle, mat, matrixType); 216} 217 218void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) 219{ 220 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 221 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 222 mParameters->set(mph->mProcessedHandle, mat, arraySize, matrixType); 223} 224#undef MATINSTPARAMSET 225 226//**************************************************************************** 227// Material Instance 228//**************************************************************************** 229MatInstance::MatInstance( Material &mat ) 230{ 231 VECTOR_SET_ASSOCIATION( mCurrentHandles ); 232 VECTOR_SET_ASSOCIATION( mCurrentParameters ); 233 234 mMaterial = &mat; 235 236 mCreatedFromCustomMaterial = (dynamic_cast<CustomMaterial *>(&mat) != NULL); 237 238 construct(); 239} 240 241//---------------------------------------------------------------------------- 242// Construct 243//---------------------------------------------------------------------------- 244void MatInstance::construct() 245{ 246 mUserObject = NULL; 247 mCurPass = -1; 248 mProcessedMaterial = NULL; 249 mVertexFormat = NULL; 250 mMaxStages = 1; 251 mActiveParameters = NULL; 252 mDefaultParameters = NULL; 253 mHasNormalMaps = false; 254 mUsesHardwareSkinning = false; 255 mIsForwardLit = false; 256 mIsValid = false; 257 mIsHardwareSkinned = false; 258 needsHighlighting = false; 259 260 MATMGR->_track(this); 261} 262 263//---------------------------------------------------------------------------- 264// Destructor 265//---------------------------------------------------------------------------- 266MatInstance::~MatInstance() 267{ 268 SAFE_DELETE(mProcessedMaterial); 269 SAFE_DELETE(mDefaultParameters); 270 for (U32 i = 0; i < mCurrentHandles.size(); i++) 271 SAFE_DELETE(mCurrentHandles[i]); 272 273 MATMGR->_untrack(this); 274} 275 276//---------------------------------------------------------------------------- 277// Init 278//---------------------------------------------------------------------------- 279bool MatInstance::init( const FeatureSet &features, 280 const GFXVertexFormat *vertexFormat ) 281{ 282 AssertFatal( vertexFormat, "MatInstance::init - Got null vertex format!" ); 283 284 mFeatureList = features; 285 mVertexFormat = vertexFormat; 286 287 SAFE_DELETE(mProcessedMaterial); 288 mIsValid = processMaterial(); 289 290 return mIsValid; 291} 292 293 294//---------------------------------------------------------------------------- 295// reInitialize 296//---------------------------------------------------------------------------- 297bool MatInstance::reInit() 298{ 299 if (!mVertexFormat) 300 { 301 mIsValid = false; 302 return mIsValid; 303 } 304 305 SAFE_DELETE(mProcessedMaterial); 306 deleteAllHooks(); 307 mIsValid = processMaterial(); 308 309 if ( mIsValid ) 310 { 311 for (U32 i = 0; i < mCurrentHandles.size(); i++) 312 mCurrentHandles[i]->loadHandle(mProcessedMaterial); 313 314 for (U32 i = 0; i < mCurrentParameters.size(); i++) 315 mCurrentParameters[i]->loadParameters(mProcessedMaterial); 316 } 317 318 return mIsValid; 319} 320 321//---------------------------------------------------------------------------- 322// Process stages 323//---------------------------------------------------------------------------- 324bool MatInstance::processMaterial() 325{ 326 AssertFatal( mMaterial, "MatInstance::processMaterial - Got null material!" ); 327 //AssertFatal( mVertexFormat, "MatInstance::processMaterial - Got null vertex format!" ); 328 if ( !mMaterial || !mVertexFormat ) 329 return false; 330 331 SAFE_DELETE(mDefaultParameters); 332 333 CustomMaterial *custMat = NULL; 334 335 if( dynamic_cast<CustomMaterial*>(mMaterial) ) 336 { 337 F32 pixVersion = GFX->getPixelShaderVersion(); 338 custMat = static_cast<CustomMaterial*>(mMaterial); 339 if ((custMat->mVersion > pixVersion) || (custMat->mVersion == 0.0)) 340 { 341 if(custMat->mFallback) 342 { 343 mMaterial = custMat->mFallback; 344 return processMaterial(); 345 } 346 else 347 { 348 AssertWarn(custMat->mVersion == 0.0f, avar("Can't load CustomMaterial %s for %s, using generic FF fallback", 349 String(mMaterial->getName()).isEmpty() ? "Unknown" : mMaterial->getName(), custMat->mMapTo.c_str())); 350 } 351 } 352 else 353 mProcessedMaterial = new ProcessedCustomMaterial(*mMaterial); 354 } 355 else 356 mProcessedMaterial = getShaderMaterial(); 357 358 359 if (mProcessedMaterial) 360 { 361 mProcessedMaterial->addStateBlockDesc( mUserDefinedState ); 362 mProcessedMaterial->setShaderMacros( mUserMacros ); 363 mProcessedMaterial->setUserObject( mUserObject ); 364 365 FeatureSet features( mFeatureList ); 366 features.exclude( MATMGR->getExclusionFeatures() ); 367 368 if (mVertexFormat->hasBlendIndices() && TSShape::smUseHardwareSkinning) 369 { 370 features.addFeature( MFT_HardwareSkinning ); 371 } 372 373 if( !mProcessedMaterial->init(features, mVertexFormat, mFeaturesDelegate) ) 374 { 375 Con::errorf( "Failed to initialize material '%s'", getMaterial()->getName() ); 376 SAFE_DELETE( mProcessedMaterial ); 377 return false; 378 } 379 380 mDefaultParameters = new MatInstParameters(mProcessedMaterial->getDefaultMaterialParameters()); 381 mActiveParameters = mDefaultParameters; 382 383 const FeatureSet &finalFeatures = mProcessedMaterial->getFeatures(); 384 mHasNormalMaps = finalFeatures.hasFeature( MFT_NormalMap ); 385 mUsesHardwareSkinning = finalFeatures.hasFeature( MFT_HardwareSkinning ); 386 387 mIsForwardLit = ( custMat && custMat->mForwardLit ) || 388 ( !finalFeatures.hasFeature( MFT_IsEmissive ) && 389 finalFeatures.hasFeature( MFT_ForwardShading ) ); 390 391 mIsHardwareSkinned = finalFeatures.hasFeature( MFT_HardwareSkinning ); 392 393 return true; 394 } 395 396 return false; 397} 398 399const MatStateHint& MatInstance::getStateHint() const 400{ 401 if ( mProcessedMaterial ) 402 return mProcessedMaterial->getStateHint(); 403 else 404 return MatStateHint::Default; 405} 406 407ProcessedMaterial* MatInstance::getShaderMaterial() 408{ 409 return new ProcessedShaderMaterial(*mMaterial); 410} 411 412void MatInstance::addStateBlockDesc(const GFXStateBlockDesc& desc) 413{ 414 mUserDefinedState = desc; 415} 416 417void MatInstance::updateStateBlocks() 418{ 419 if ( mProcessedMaterial ) 420 mProcessedMaterial->updateStateBlocks(); 421} 422 423void MatInstance::addShaderMacro( const String &name, const String &value ) 424{ 425 // Check to see if we already have this macro. 426 Vector<GFXShaderMacro>::iterator iter = mUserMacros.begin(); 427 for ( ; iter != mUserMacros.end(); iter++ ) 428 { 429 if ( iter->name == name ) 430 { 431 iter->value = value; 432 return; 433 } 434 } 435 436 // Add a new macro. 437 mUserMacros.increment(); 438 mUserMacros.last().name = name; 439 mUserMacros.last().value = value; 440} 441 442//---------------------------------------------------------------------------- 443// Setup pass - needs scenegraph data because the lightmap will change across 444// several materials. 445//---------------------------------------------------------------------------- 446bool MatInstance::setupPass(SceneRenderState * state, const SceneData &sgData ) 447{ 448 PROFILE_SCOPE( MatInstance_SetupPass ); 449 450 if( !mProcessedMaterial ) 451 return false; 452 453 ++mCurPass; 454 455 if ( !mProcessedMaterial->setupPass( state, sgData, mCurPass ) ) 456 { 457 mCurPass = -1; 458 return false; 459 } 460 461 return true; 462} 463 464void MatInstance::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state) 465{ 466 PROFILE_SCOPE(MatInstance_setTransforms); 467 mProcessedMaterial->setTransforms(matrixSet, state, getCurPass()); 468} 469 470void MatInstance::setNodeTransforms(const MatrixF *address, const U32 numTransforms) 471{ 472 PROFILE_SCOPE(MatInstance_setNodeTransforms); 473 mProcessedMaterial->setNodeTransforms(address, numTransforms, getCurPass()); 474} 475 476void MatInstance::setCustomShaderData(Vector<CustomShaderBindingData> &shaderData) 477{ 478 PROFILE_SCOPE(MatInstance_setCustomShaderData); 479 mProcessedMaterial->setCustomShaderData(shaderData, getCurPass()); 480} 481 482void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData) 483{ 484 PROFILE_SCOPE(MatInstance_setSceneInfo); 485 mProcessedMaterial->setSceneInfo(state, sgData, getCurPass()); 486} 487 488void MatInstance::setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer) 489{ 490 mProcessedMaterial->setBuffers(vertBuffer, primBuffer); 491} 492 493void MatInstance::setTextureStages(SceneRenderState * state, const SceneData &sgData ) 494{ 495 PROFILE_SCOPE(MatInstance_setTextureStages); 496 mProcessedMaterial->setTextureStages(state, sgData, getCurPass()); 497} 498 499bool MatInstance::isInstanced() const 500{ 501 return mProcessedMaterial->getFeatures().hasFeature( MFT_UseInstancing ); 502} 503 504bool MatInstance::stepInstance() 505{ 506 AssertFatal( isInstanced(), "MatInstance::stepInstance - This material isn't instanced!" ); 507 AssertFatal( mCurPass >= 0, "MatInstance::stepInstance - Must be within material setup pass!" ); 508 509 return mProcessedMaterial->stepInstance(); 510} 511 512U32 MatInstance::getCurStageNum() 513{ 514 return mProcessedMaterial->getStageFromPass(getCurPass()); 515} 516 517RenderPassData* MatInstance::getPass(U32 pass) 518{ 519 return mProcessedMaterial->getPass(pass); 520} 521 522bool MatInstance::hasGlow() 523{ 524 if( mProcessedMaterial ) 525 return mProcessedMaterial->hasGlow(); 526 else 527 return false; 528} 529 530bool MatInstance::hasAccumulation() 531{ 532 if( mProcessedMaterial ) 533 return mProcessedMaterial->hasAccumulation(); 534 else 535 return false; 536} 537 538const FeatureSet& MatInstance::getFeatures() const 539{ 540 return mProcessedMaterial->getFeatures(); 541} 542 543MaterialParameterHandle* MatInstance::getMaterialParameterHandle(const String& name) 544{ 545 AssertFatal(mProcessedMaterial, "Not init'ed!"); 546 for (U32 i = 0; i < mCurrentHandles.size(); i++) 547 { 548 if (mCurrentHandles[i]->getName().equal(name)) 549 { 550 return mCurrentHandles[i]; 551 } 552 } 553 MatInstanceParameterHandle* mph = new MatInstanceParameterHandle(name); 554 mph->loadHandle(mProcessedMaterial); 555 mCurrentHandles.push_back(mph); 556 return mph; 557} 558 559MaterialParameters* MatInstance::allocMaterialParameters() 560{ 561 AssertFatal(mProcessedMaterial, "Not init'ed!"); 562 MatInstParameters* mip = new MatInstParameters(); 563 mip->loadParameters(mProcessedMaterial); 564 mCurrentParameters.push_back(mip); 565 return mip; 566} 567 568void MatInstance::setMaterialParameters(MaterialParameters* param) 569{ 570 AssertFatal(mProcessedMaterial, "Not init'ed!"); 571 mProcessedMaterial->setMaterialParameters(param, mCurPass); 572 AssertFatal(dynamic_cast<MatInstParameters*>(param), "Incorrect param type!"); 573 mActiveParameters = static_cast<MatInstParameters*>(param); 574} 575 576MaterialParameters* MatInstance::getMaterialParameters() 577{ 578 AssertFatal(mProcessedMaterial, "Not init'ed!"); 579 return mActiveParameters; 580} 581 582void MatInstance::dumpShaderInfo() const 583{ 584 if ( mMaterial == NULL ) 585 { 586 Con::errorf( "Trying to get Material information on an invalid MatInstance" ); 587 return; 588 } 589 590 Con::printf( "Material Info for object %s - %s", mMaterial->getName(), mMaterial->mMapTo.c_str() ); 591 592 593 if ( mProcessedMaterial == NULL ) 594 { 595 Con::printf( " [no processed material!]" ); 596 return; 597 } 598 599 mProcessedMaterial->dumpMaterialInfo(); 600} 601 602void MatInstance::getShaderInfo(GuiTreeViewCtrl* tree, U32 item) const 603{ 604 if (mMaterial == NULL) 605 { 606 Con::errorf("Trying to get Material information on an invalid MatInstance"); 607 return; 608 } 609 610 if (mProcessedMaterial == NULL) 611 { 612 Con::printf(" [no processed material!]"); 613 return; 614 } 615 616 const FeatureSet features = mProcessedMaterial->getFeatures(); 617 618 String featureDesc = ""; 619 for (U32 i = 0; i < features.getCount(); i++) 620 { 621 const FeatureType& ft = features.getAt(i); 622 623 featureDesc += ft.getName(); 624 625 if(i+1 < features.getCount()) 626 featureDesc += ", "; 627 } 628 629 U32 newItem = tree->insertItem(item, featureDesc); 630 631 mProcessedMaterial->getMaterialInfo(tree, newItem); 632} 633