matInstance.cpp 18 KB

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