matInstance.cpp 18 KB

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