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/processedFFMaterial.h" 31#include "materials/processedShaderMaterial.h" 32#include "materials/processedCustomMaterial.h" 33#include "materials/materialFeatureTypes.h" 34#include "shaderGen/featureMgr.h" 35#include "gfx/gfxDevice.h" 36#include "gfx/sim/cubemapData.h" 37#include "gfx/gfxCubemap.h" 38#include "core/util/safeDelete.h" 39#include "ts/tsShape.h" 40 41class MatInstParameters; 42 43class MatInstanceParameterHandle : public MaterialParameterHandle 44{ 45public: 46 virtual ~MatInstanceParameterHandle() {} 47 MatInstanceParameterHandle(const String& name); 48 49 void loadHandle(ProcessedMaterial* pmat); 50 51 // MaterialParameterHandle interface 52 const String& getName() const { return mName; } 53 virtual bool isValid() const; 54 virtual S32 getSamplerRegister( U32 pass ) const; 55private: 56 friend class MatInstParameters; 57 String mName; 58 MaterialParameterHandle* mProcessedHandle; 59}; 60 61MatInstanceParameterHandle::MatInstanceParameterHandle(const String& name) 62{ 63 mName = name; 64 mProcessedHandle = NULL; 65} 66 67bool MatInstanceParameterHandle::isValid() const 68{ 69 return mProcessedHandle && mProcessedHandle->isValid(); 70} 71 72S32 MatInstanceParameterHandle::getSamplerRegister( U32 pass ) const 73{ 74 if ( !mProcessedHandle ) 75 return -1; 76 return mProcessedHandle->getSamplerRegister( pass ); 77} 78 79void MatInstanceParameterHandle::loadHandle(ProcessedMaterial* pmat) 80{ 81 mProcessedHandle = pmat->getMaterialParameterHandle(mName); 82} 83 84MatInstParameters::MatInstParameters() 85{ 86 mOwnParameters = false; 87 mParameters = NULL; 88} 89 90MatInstParameters::MatInstParameters(MaterialParameters* matParams) 91{ 92 mOwnParameters = false; 93 mParameters = matParams; 94} 95 96void MatInstParameters::loadParameters(ProcessedMaterial* pmat) 97{ 98 mOwnParameters = true; 99 mParameters = pmat->allocMaterialParameters(); 100} 101 102MatInstParameters::~MatInstParameters() 103{ 104 if (mOwnParameters) 105 SAFE_DELETE(mParameters); 106} 107 108const Vector<GFXShaderConstDesc>& MatInstParameters::getShaderConstDesc() const 109{ 110 return mParameters->getShaderConstDesc(); 111} 112 113U32 MatInstParameters::getAlignmentValue(const GFXShaderConstType constType) 114{ 115 return mParameters->getAlignmentValue(constType); 116} 117 118#define MATINSTPARAMSET(handle, f) \ 119 if (!mParameters) \ 120 return; \ 121 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); \ 122 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); \ 123 mParameters->set(mph->mProcessedHandle, f); \ 124 125void MatInstParameters::set(MaterialParameterHandle* handle, const F32 f) 126{ 127 MATINSTPARAMSET(handle, f); 128} 129 130void MatInstParameters::set(MaterialParameterHandle* handle, const Point2F& fv) 131{ 132 MATINSTPARAMSET(handle, fv); 133} 134 135void MatInstParameters::set(MaterialParameterHandle* handle, const Point3F& fv) 136{ 137 MATINSTPARAMSET(handle, fv); 138} 139 140void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv) 141{ 142 MATINSTPARAMSET(handle, fv); 143} 144 145void MatInstParameters::set(MaterialParameterHandle* handle, const ColorF& fv) 146{ 147 MATINSTPARAMSET(handle, fv); 148} 149 150void MatInstParameters::set(MaterialParameterHandle* handle, const S32 f) 151{ 152 MATINSTPARAMSET(handle, f); 153} 154 155void MatInstParameters::set(MaterialParameterHandle* handle, const Point2I& fv) 156{ 157 MATINSTPARAMSET(handle, fv); 158} 159 160void MatInstParameters::set(MaterialParameterHandle* handle, const Point3I& fv) 161{ 162 MATINSTPARAMSET(handle, fv); 163} 164 165void MatInstParameters::set(MaterialParameterHandle* handle, const Point4I& fv) 166{ 167 MATINSTPARAMSET(handle, fv); 168} 169 170void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv) 171{ 172 MATINSTPARAMSET(handle, fv); 173} 174 175void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv) 176{ 177 MATINSTPARAMSET(handle, fv); 178} 179 180void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv) 181{ 182 MATINSTPARAMSET(handle, fv); 183} 184 185void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv) 186{ 187 MATINSTPARAMSET(handle, fv); 188} 189 190void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv) 191{ 192 MATINSTPARAMSET(handle, fv); 193} 194 195void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv) 196{ 197 MATINSTPARAMSET(handle, fv); 198} 199 200void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv) 201{ 202 MATINSTPARAMSET(handle, fv); 203} 204 205void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv) 206{ 207 MATINSTPARAMSET(handle, fv); 208} 209 210void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) 211{ 212 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 213 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 214 mParameters->set(mph->mProcessedHandle, mat, matrixType); 215} 216 217void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) 218{ 219 AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 220 MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 221 mParameters->set(mph->mProcessedHandle, mat, arraySize, matrixType); 222} 223#undef MATINSTPARAMSET 224 225//**************************************************************************** 226// Material Instance 227//**************************************************************************** 228MatInstance::MatInstance( Material &mat ) 229{ 230 VECTOR_SET_ASSOCIATION( mCurrentHandles ); 231 VECTOR_SET_ASSOCIATION( mCurrentParameters ); 232 233 mMaterial = &mat; 234 235 mCreatedFromCustomMaterial = (dynamic_cast<CustomMaterial *>(&mat) != NULL); 236 237 construct(); 238} 239 240//---------------------------------------------------------------------------- 241// Construct 242//---------------------------------------------------------------------------- 243void MatInstance::construct() 244{ 245 mUserObject = NULL; 246 mCurPass = -1; 247 mProcessedMaterial = NULL; 248 mVertexFormat = NULL; 249 mMaxStages = 1; 250 mActiveParameters = NULL; 251 mDefaultParameters = NULL; 252 mHasNormalMaps = false; 253 mUsesHardwareSkinning = false; 254 mIsForwardLit = false; 255 mIsValid = false; 256 mIsHardwareSkinned = false; 257 258 MATMGR->_track(this); 259} 260 261//---------------------------------------------------------------------------- 262// Destructor 263//---------------------------------------------------------------------------- 264MatInstance::~MatInstance() 265{ 266 SAFE_DELETE(mProcessedMaterial); 267 SAFE_DELETE(mDefaultParameters); 268 for (U32 i = 0; i < mCurrentHandles.size(); i++) 269 SAFE_DELETE(mCurrentHandles[i]); 270 271 MATMGR->_untrack(this); 272} 273 274//---------------------------------------------------------------------------- 275// Init 276//---------------------------------------------------------------------------- 277bool MatInstance::init( const FeatureSet &features, 278 const GFXVertexFormat *vertexFormat ) 279{ 280 AssertFatal( vertexFormat, "MatInstance::init - Got null vertex format!" ); 281 282 mFeatureList = features; 283 mVertexFormat = vertexFormat; 284 285 SAFE_DELETE(mProcessedMaterial); 286 mIsValid = processMaterial(); 287 288 return mIsValid; 289} 290 291 292//---------------------------------------------------------------------------- 293// reInitialize 294//---------------------------------------------------------------------------- 295bool MatInstance::reInit() 296{ 297 if (!mVertexFormat) 298 { 299 mIsValid = false; 300 return mIsValid; 301 } 302 303 SAFE_DELETE(mProcessedMaterial); 304 deleteAllHooks(); 305 mIsValid = processMaterial(); 306 307 if ( mIsValid ) 308 { 309 for (U32 i = 0; i < mCurrentHandles.size(); i++) 310 mCurrentHandles[i]->loadHandle(mProcessedMaterial); 311 312 for (U32 i = 0; i < mCurrentParameters.size(); i++) 313 mCurrentParameters[i]->loadParameters(mProcessedMaterial); 314 } 315 316 return mIsValid; 317} 318 319//---------------------------------------------------------------------------- 320// Process stages 321//---------------------------------------------------------------------------- 322bool MatInstance::processMaterial() 323{ 324 AssertFatal( mMaterial, "MatInstance::processMaterial - Got null material!" ); 325 //AssertFatal( mVertexFormat, "MatInstance::processMaterial - Got null vertex format!" ); 326 if ( !mMaterial || !mVertexFormat ) 327 return false; 328 329 SAFE_DELETE(mDefaultParameters); 330 331 CustomMaterial *custMat = NULL; 332 333 if( dynamic_cast<CustomMaterial*>(mMaterial) ) 334 { 335 F32 pixVersion = GFX->getPixelShaderVersion(); 336 custMat = static_cast<CustomMaterial*>(mMaterial); 337 if ((custMat->mVersion > pixVersion) || (custMat->mVersion == 0.0)) 338 { 339 if(custMat->mFallback) 340 { 341 mMaterial = custMat->mFallback; 342 return processMaterial(); 343 } 344 else 345 { 346 AssertWarn(custMat->mVersion == 0.0f, avar("Can't load CustomMaterial %s for %s, using generic FF fallback", 347 String(mMaterial->getName()).isEmpty() ? "Unknown" : mMaterial->getName(), custMat->mMapTo.c_str())); 348 mProcessedMaterial = new ProcessedFFMaterial(*mMaterial); 349 } 350 } 351 else 352 mProcessedMaterial = new ProcessedCustomMaterial(*mMaterial); 353 } 354 else if(GFX->getPixelShaderVersion() > 0.001) 355 mProcessedMaterial = getShaderMaterial(); 356 else 357 mProcessedMaterial = new ProcessedFFMaterial(*mMaterial); 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::setSceneInfo(SceneRenderState * state, const SceneData& sgData) 477{ 478 PROFILE_SCOPE(MatInstance_setSceneInfo); 479 mProcessedMaterial->setSceneInfo(state, sgData, getCurPass()); 480} 481 482void MatInstance::setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer) 483{ 484 mProcessedMaterial->setBuffers(vertBuffer, primBuffer); 485} 486 487void MatInstance::setTextureStages(SceneRenderState * state, const SceneData &sgData ) 488{ 489 PROFILE_SCOPE(MatInstance_setTextureStages); 490 mProcessedMaterial->setTextureStages(state, sgData, getCurPass()); 491} 492 493bool MatInstance::isInstanced() const 494{ 495 return mProcessedMaterial->getFeatures().hasFeature( MFT_UseInstancing ); 496} 497 498bool MatInstance::stepInstance() 499{ 500 AssertFatal( isInstanced(), "MatInstance::stepInstance - This material isn't instanced!" ); 501 AssertFatal( mCurPass >= 0, "MatInstance::stepInstance - Must be within material setup pass!" ); 502 503 return mProcessedMaterial->stepInstance(); 504} 505 506U32 MatInstance::getCurStageNum() 507{ 508 return mProcessedMaterial->getStageFromPass(getCurPass()); 509} 510 511RenderPassData* MatInstance::getPass(U32 pass) 512{ 513 return mProcessedMaterial->getPass(pass); 514} 515 516bool MatInstance::hasGlow() 517{ 518 if( mProcessedMaterial ) 519 return mProcessedMaterial->hasGlow(); 520 else 521 return false; 522} 523 524bool MatInstance::hasAccumulation() 525{ 526 if( mProcessedMaterial ) 527 return mProcessedMaterial->hasAccumulation(); 528 else 529 return false; 530} 531 532const FeatureSet& MatInstance::getFeatures() const 533{ 534 return mProcessedMaterial->getFeatures(); 535} 536 537MaterialParameterHandle* MatInstance::getMaterialParameterHandle(const String& name) 538{ 539 AssertFatal(mProcessedMaterial, "Not init'ed!"); 540 for (U32 i = 0; i < mCurrentHandles.size(); i++) 541 { 542 if (mCurrentHandles[i]->getName().equal(name)) 543 { 544 return mCurrentHandles[i]; 545 } 546 } 547 MatInstanceParameterHandle* mph = new MatInstanceParameterHandle(name); 548 mph->loadHandle(mProcessedMaterial); 549 mCurrentHandles.push_back(mph); 550 return mph; 551} 552 553MaterialParameters* MatInstance::allocMaterialParameters() 554{ 555 AssertFatal(mProcessedMaterial, "Not init'ed!"); 556 MatInstParameters* mip = new MatInstParameters(); 557 mip->loadParameters(mProcessedMaterial); 558 mCurrentParameters.push_back(mip); 559 return mip; 560} 561 562void MatInstance::setMaterialParameters(MaterialParameters* param) 563{ 564 AssertFatal(mProcessedMaterial, "Not init'ed!"); 565 mProcessedMaterial->setMaterialParameters(param, mCurPass); 566 AssertFatal(dynamic_cast<MatInstParameters*>(param), "Incorrect param type!"); 567 mActiveParameters = static_cast<MatInstParameters*>(param); 568} 569 570MaterialParameters* MatInstance::getMaterialParameters() 571{ 572 AssertFatal(mProcessedMaterial, "Not init'ed!"); 573 return mActiveParameters; 574} 575 576void MatInstance::dumpShaderInfo() const 577{ 578 if ( mMaterial == NULL ) 579 { 580 Con::errorf( "Trying to get Material information on an invalid MatInstance" ); 581 return; 582 } 583 584 Con::printf( "Material Info for object %s - %s", mMaterial->getName(), mMaterial->mMapTo.c_str() ); 585 586 if ( mProcessedMaterial == NULL ) 587 { 588 Con::printf( " [no processed material!]" ); 589 return; 590 } 591 592 mProcessedMaterial->dumpMaterialInfo(); 593} 594
