CmMaterial.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. #include "CmMaterial.h"
  2. #include "CmException.h"
  3. #include "CmShader.h"
  4. #include "CmTechnique.h"
  5. #include "CmPass.h"
  6. #include "CmRenderSystem.h"
  7. #include "CmGpuProgramParams.h"
  8. #include "CmHardwareBufferManager.h"
  9. #include "CmGpuProgram.h"
  10. #include "CmGpuParamDesc.h"
  11. #include "CmMaterialRTTI.h"
  12. #include "CmDebug.h"
  13. namespace CamelotEngine
  14. {
  15. Material::Material()
  16. {
  17. // Material doesn't do anything render thread specific, so we can just initialize right away
  18. initialize_internal();
  19. }
  20. void Material::initialize_internal()
  21. {
  22. Resource::initialize_internal();
  23. }
  24. void Material::setShader(ShaderPtr shader)
  25. {
  26. mShader = shader;
  27. initBestTechnique();
  28. }
  29. void Material::initBestTechnique()
  30. {
  31. mBestTechnique = nullptr;
  32. mParametersPerPass.clear();
  33. if(mShader)
  34. {
  35. mBestTechnique = mShader->getBestTechnique();
  36. if(mBestTechnique == nullptr)
  37. return;
  38. mValidShareableParamBlocks.clear();
  39. mValidParams.clear();
  40. vector<const GpuParamDesc*>::type allParamDescs;
  41. // Make sure all gpu programs are fully loaded
  42. for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
  43. {
  44. PassPtr curPass = mBestTechnique->getPass(i);
  45. GpuProgramHandle vertProgram = curPass->getVertexProgram();
  46. if(vertProgram)
  47. {
  48. vertProgram.waitUntilLoaded();
  49. allParamDescs.push_back(&vertProgram->getParamDesc());
  50. }
  51. GpuProgramHandle fragProgram = curPass->getFragmentProgram();
  52. if(fragProgram)
  53. {
  54. fragProgram.waitUntilLoaded();
  55. allParamDescs.push_back(&fragProgram->getParamDesc());
  56. }
  57. GpuProgramHandle geomProgram = curPass->getGeometryProgram();
  58. if(geomProgram)
  59. {
  60. geomProgram.waitUntilLoaded();
  61. allParamDescs.push_back(&geomProgram->getParamDesc());
  62. }
  63. GpuProgramHandle hullProgram = curPass->getHullProgram();
  64. if(hullProgram)
  65. {
  66. hullProgram.waitUntilLoaded();
  67. allParamDescs.push_back(&hullProgram->getParamDesc());
  68. }
  69. GpuProgramHandle domainProgram = curPass->getDomainProgram();
  70. if(domainProgram)
  71. {
  72. domainProgram.waitUntilLoaded();
  73. allParamDescs.push_back(&domainProgram->getParamDesc());
  74. }
  75. GpuProgramHandle computeProgram = curPass->getComputeProgram();
  76. if(computeProgram)
  77. {
  78. computeProgram.waitUntilLoaded();
  79. allParamDescs.push_back(&computeProgram->getParamDesc());
  80. }
  81. }
  82. // Fill out various helper structures
  83. set<String>::type validParameters = determineValidParameters(allParamDescs);
  84. set<String>::type validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
  85. map<String, String>::type paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
  86. map<String, GpuParamBlockPtr>::type paramBlocks;
  87. // Create param blocks
  88. const map<String, SHADER_PARAM_BLOCK_DESC>::type& shaderDesc = mShader->getParamBlocks();
  89. for(auto iter = validShareableParamBlocks.begin(); iter != validShareableParamBlocks.end(); ++iter)
  90. {
  91. bool isShared = false;
  92. GpuParamBlockUsage usage = GPBU_STATIC;
  93. auto iterFind = shaderDesc.find(*iter);
  94. if(iterFind != shaderDesc.end())
  95. {
  96. isShared = iterFind->second.shared;
  97. usage = iterFind->second.usage;
  98. }
  99. GpuParamBlockDesc blockDesc;
  100. for(auto iter2 = allParamDescs.begin(); iter2 != allParamDescs.end(); ++iter2)
  101. {
  102. auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
  103. if(findParamBlockDesc != (*iter2)->paramBlocks.end())
  104. {
  105. blockDesc = findParamBlockDesc->second;
  106. break;
  107. }
  108. }
  109. GpuParamBlockPtr newParamBlockBuffer;
  110. if(!isShared)
  111. newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlock(blockDesc, usage);
  112. paramBlocks[*iter] = newParamBlockBuffer;
  113. mValidShareableParamBlocks.insert(*iter);
  114. }
  115. // Create data param mappings
  116. const map<String, SHADER_DATA_PARAM_DESC>::type& dataParamDesc = mShader->getDataParams();
  117. for(auto iter = dataParamDesc.begin(); iter != dataParamDesc.end(); ++iter)
  118. {
  119. auto findIter = validParameters.find(iter->first);
  120. // Not valid so we skip it
  121. if(findIter == validParameters.end())
  122. continue;
  123. auto findBlockIter = paramToParamBlockMap.find(iter->first);
  124. if(findBlockIter == paramToParamBlockMap.end())
  125. CM_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
  126. String& paramBlockName = findBlockIter->second;
  127. mValidParams.insert(iter->first);
  128. }
  129. // Create object param mappings
  130. const map<String, SHADER_OBJECT_PARAM_DESC>::type& objectParamDesc = mShader->getObjectParams();
  131. for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.end(); ++iter)
  132. {
  133. auto findIter = validParameters.find(iter->first);
  134. // Not valid so we skip it
  135. if(findIter == validParameters.end())
  136. continue;
  137. mValidParams.insert(iter->first);
  138. }
  139. for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
  140. {
  141. PassPtr curPass = mBestTechnique->getPass(i);
  142. PassParametersPtr params = PassParametersPtr(new PassParameters());
  143. GpuProgramHandle vertProgram = curPass->getVertexProgram();
  144. if(vertProgram)
  145. params->mVertParams = vertProgram->createParameters();
  146. GpuProgramHandle fragProgram = curPass->getFragmentProgram();
  147. if(fragProgram)
  148. params->mFragParams = fragProgram->createParameters();
  149. GpuProgramHandle geomProgram = curPass->getGeometryProgram();
  150. if(geomProgram)
  151. params->mGeomParams = geomProgram->createParameters();
  152. GpuProgramHandle hullProgram = curPass->getHullProgram();
  153. if(hullProgram)
  154. params->mHullParams = hullProgram->createParameters();
  155. GpuProgramHandle domainProgram = curPass->getDomainProgram();
  156. if(domainProgram)
  157. params->mDomainParams = domainProgram->createParameters();
  158. GpuProgramHandle computeProgram = curPass->getComputeProgram();
  159. if(computeProgram)
  160. params->mComputeParams = computeProgram->createParameters();
  161. mParametersPerPass.push_back(params);
  162. }
  163. // Assign param block buffers
  164. for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  165. {
  166. PassParametersPtr params = *iter;
  167. for(UINT32 i = 0; i < params->getNumParams(); i++)
  168. {
  169. GpuParamsPtr& paramPtr = params->getParamByIdx(i);
  170. if(paramPtr)
  171. {
  172. // Assign shareable buffers
  173. for(auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
  174. {
  175. const String& paramBlockName = *iterBlock;
  176. if(paramPtr->hasParamBlock(paramBlockName))
  177. {
  178. GpuParamBlockPtr blockBuffer = paramBlocks[paramBlockName];
  179. paramPtr->setParamBlock(paramBlockName, blockBuffer);
  180. }
  181. }
  182. // Create non-shareable ones
  183. const GpuParamDesc& desc = paramPtr->getParamDesc();
  184. for(auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
  185. {
  186. if(!iterBlockDesc->second.isShareable)
  187. {
  188. GpuParamBlockPtr newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlock(iterBlockDesc->second);
  189. paramPtr->setParamBlock(iterBlockDesc->first, newParamBlockBuffer);
  190. }
  191. }
  192. }
  193. }
  194. }
  195. }
  196. }
  197. set<String>::type Material::determineValidParameters(const vector<const GpuParamDesc*>::type& paramDescs) const
  198. {
  199. map<String, const GpuParamDataDesc*>::type foundDataParams;
  200. map<String, const GpuParamObjectDesc*>::type foundObjectParams;
  201. map<String, bool>::type validParameters;
  202. for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  203. {
  204. const GpuParamDesc& curDesc = **iter;
  205. // Check regular data params
  206. for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
  207. {
  208. bool isParameterValid = true;
  209. const GpuParamDataDesc& curParam = iter2->second;
  210. auto objectFindIter = foundObjectParams.find(iter2->first);
  211. if(objectFindIter != foundObjectParams.end())
  212. isParameterValid = false; // Data param but we found another as object param with the same name
  213. if(isParameterValid)
  214. {
  215. auto dataFindIter = foundDataParams.find(iter2->first);
  216. if(dataFindIter == foundDataParams.end())
  217. {
  218. validParameters[iter2->first] = true;
  219. foundDataParams[iter2->first] = &curParam;
  220. }
  221. else
  222. {
  223. const GpuParamDataDesc* otherParam = dataFindIter->second;
  224. if(!areParamsEqual(curParam, *otherParam, true))
  225. isParameterValid = false;
  226. }
  227. }
  228. if(!isParameterValid)
  229. {
  230. if(validParameters[iter2->first]) // Do this check so we only report this error once
  231. LOGWRN("Found two parameters with the same name but different contents: " + iter2->first);
  232. validParameters[iter2->first] = false;
  233. }
  234. }
  235. // Check sampler params
  236. for(auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
  237. {
  238. bool isParameterValid = true;
  239. const GpuParamObjectDesc& curParam = iter2->second;
  240. auto dataFindIter = foundDataParams.find(iter2->first);
  241. if(dataFindIter != foundDataParams.end())
  242. isParameterValid = false; // Object param but we found another as data param with the same name
  243. if(isParameterValid)
  244. {
  245. auto objectFindIter = foundObjectParams.find(iter2->first);
  246. if(objectFindIter == foundObjectParams.end())
  247. {
  248. validParameters[iter2->first] = true;
  249. foundObjectParams[iter2->first] = &curParam;
  250. }
  251. else
  252. {
  253. const GpuParamObjectDesc* otherParam = objectFindIter->second;
  254. if(!areParamsEqual(curParam, *otherParam))
  255. isParameterValid = false;
  256. }
  257. }
  258. if(!isParameterValid)
  259. {
  260. if(validParameters[iter2->first]) // Do this check so we only report this error once
  261. LOGWRN("Found two parameters with the same name but different contents: " + iter2->first);
  262. validParameters[iter2->first] = false;
  263. }
  264. }
  265. // Check texture params
  266. for(auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
  267. {
  268. bool isParameterValid = true;
  269. const GpuParamObjectDesc& curParam = iter2->second;
  270. auto dataFindIter = foundDataParams.find(iter2->first);
  271. if(dataFindIter != foundDataParams.end())
  272. isParameterValid = false; // Object param but we found another as data param with the same name
  273. if(isParameterValid)
  274. {
  275. auto objectFindIter = foundObjectParams.find(iter2->first);
  276. if(objectFindIter == foundObjectParams.end())
  277. {
  278. validParameters[iter2->first] = true;
  279. foundObjectParams[iter2->first] = &curParam;
  280. }
  281. else
  282. {
  283. const GpuParamObjectDesc* otherParam = objectFindIter->second;
  284. if(!areParamsEqual(curParam, *otherParam))
  285. isParameterValid = false;
  286. }
  287. }
  288. if(!isParameterValid)
  289. {
  290. if(validParameters[iter2->first]) // Do this check so we only report this error once
  291. LOGWRN("Found two parameters with the same name but different contents: " + iter2->first);
  292. validParameters[iter2->first] = false;
  293. }
  294. }
  295. // Check buffer params
  296. for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
  297. {
  298. bool isParameterValid = true;
  299. const GpuParamObjectDesc& curParam = iter2->second;
  300. auto dataFindIter = foundDataParams.find(iter2->first);
  301. if(dataFindIter != foundDataParams.end())
  302. isParameterValid = false; // Object param but we found another as data param with the same name
  303. if(isParameterValid)
  304. {
  305. auto objectFindIter = foundObjectParams.find(iter2->first);
  306. if(objectFindIter == foundObjectParams.end())
  307. {
  308. validParameters[iter2->first] = true;
  309. foundObjectParams[iter2->first] = &curParam;
  310. }
  311. else
  312. {
  313. const GpuParamObjectDesc* otherParam = objectFindIter->second;
  314. if(!areParamsEqual(curParam, *otherParam))
  315. isParameterValid = false;
  316. }
  317. }
  318. if(!isParameterValid)
  319. {
  320. if(validParameters[iter2->first]) // Do this check so we only report this error once
  321. LOGWRN("Found two parameters with the same name but different contents: " + iter2->first);
  322. validParameters[iter2->first] = false;
  323. }
  324. }
  325. }
  326. set<String>::type validParamsReturn;
  327. for(auto iter = validParameters.begin(); iter != validParameters.end(); ++iter)
  328. {
  329. if(iter->second)
  330. validParamsReturn.insert(iter->first);
  331. }
  332. return validParamsReturn;
  333. }
  334. set<String>::type Material::determineValidShareableParamBlocks(const vector<const GpuParamDesc*>::type& paramDescs) const
  335. {
  336. // Make sure param blocks with the same name actually are the same
  337. map<String, std::pair<String, const GpuParamDesc*>>::type uniqueParamBlocks;
  338. map<String, bool>::type validParamBlocks;
  339. for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  340. {
  341. const GpuParamDesc& curDesc = **iter;
  342. for(auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
  343. {
  344. bool isBlockValid = true;
  345. const GpuParamBlockDesc& curBlock = blockIter->second;
  346. if(!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
  347. continue;
  348. auto iterFind = uniqueParamBlocks.find(blockIter->first);
  349. if(iterFind == uniqueParamBlocks.end())
  350. {
  351. uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
  352. validParamBlocks[blockIter->first] = true;
  353. continue;
  354. }
  355. String otherBlockName = iterFind->second.first;
  356. const GpuParamDesc* otherDesc = iterFind->second.second;
  357. for(auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
  358. {
  359. const GpuParamDataDesc& myParam = myParamIter->second;
  360. if(myParam.paramBlockSlot != curBlock.slot)
  361. continue; // Param is in another block, so we will check it when its time for that block
  362. auto otherParamFind = otherDesc->params.find(myParamIter->first);
  363. // Cannot find other param, blocks aren't equal
  364. if(otherParamFind == otherDesc->params.end())
  365. {
  366. isBlockValid = false;
  367. break;
  368. }
  369. const GpuParamDataDesc& otherParam = otherParamFind->second;
  370. if(!areParamsEqual(myParam, otherParam) || curBlock.name != otherBlockName)
  371. {
  372. isBlockValid = false;
  373. break;
  374. }
  375. }
  376. if(!isBlockValid)
  377. {
  378. if(validParamBlocks[blockIter->first])
  379. {
  380. LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
  381. validParamBlocks[blockIter->first] = false;
  382. }
  383. }
  384. }
  385. }
  386. set<String>::type validParamBlocksReturn;
  387. for(auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
  388. {
  389. if(iter->second)
  390. validParamBlocksReturn.insert(iter->first);
  391. }
  392. return validParamBlocksReturn;
  393. }
  394. map<String, String>::type Material::determineParameterToBlockMapping(const vector<const GpuParamDesc*>::type& paramDescs)
  395. {
  396. map<String, String>::type paramToParamBlock;
  397. for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  398. {
  399. const GpuParamDesc& curDesc = **iter;
  400. for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
  401. {
  402. const GpuParamDataDesc& curParam = iter2->second;
  403. auto iterFind = paramToParamBlock.find(curParam.name);
  404. if(iterFind != paramToParamBlock.end())
  405. continue;
  406. for(auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
  407. {
  408. if(iterBlock->second.slot == curParam.paramBlockSlot)
  409. {
  410. paramToParamBlock[curParam.name] = iterBlock->second.name;
  411. break;
  412. }
  413. }
  414. }
  415. }
  416. return paramToParamBlock;
  417. }
  418. bool Material::areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets) const
  419. {
  420. bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize && paramA.type == paramB.type;
  421. if(!ignoreBufferOffsets)
  422. equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
  423. return equal;
  424. }
  425. bool Material::areParamsEqual(const GpuParamObjectDesc& paramA, const GpuParamObjectDesc& paramB) const
  426. {
  427. return paramA.type == paramB.type;
  428. }
  429. void Material::throwIfNotInitialized() const
  430. {
  431. if(mShader == nullptr)
  432. {
  433. CM_EXCEPT(InternalErrorException, "Material does not have shader set.");
  434. }
  435. if(mBestTechnique == nullptr)
  436. {
  437. CM_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
  438. }
  439. }
  440. void Material::setTexture(const String& name, TextureHandle& value)
  441. {
  442. throwIfNotInitialized();
  443. auto iterFind = mValidParams.find(name);
  444. if(iterFind == mValidParams.end())
  445. {
  446. LOGWRN("Material doesn't have a parameter named " + name);
  447. return;
  448. }
  449. for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  450. {
  451. PassParametersPtr params = *iter;
  452. for(UINT32 i = 0; i < params->getNumParams(); i++)
  453. {
  454. GpuParamsPtr& paramPtr = params->getParamByIdx(i);
  455. if(paramPtr)
  456. {
  457. if(paramPtr->hasTexture(name))
  458. paramPtr->setTexture(name, value);
  459. }
  460. }
  461. }
  462. }
  463. void Material::setSamplerState(const String& name, SamplerStatePtr samplerState)
  464. {
  465. throwIfNotInitialized();
  466. auto iterFind = mValidParams.find(name);
  467. if(iterFind == mValidParams.end())
  468. {
  469. LOGWRN("Material doesn't have a parameter named " + name);
  470. return;
  471. }
  472. for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  473. {
  474. PassParametersPtr params = *iter;
  475. for(UINT32 i = 0; i < params->getNumParams(); i++)
  476. {
  477. GpuParamsPtr& paramPtr = params->getParamByIdx(i);
  478. if(paramPtr)
  479. {
  480. if(paramPtr->hasSamplerState(name))
  481. paramPtr->setSamplerState(name, samplerState);
  482. }
  483. }
  484. }
  485. }
  486. void Material::setFloat(const String& name, float value)
  487. {
  488. throwIfNotInitialized();
  489. auto iterFind = mValidParams.find(name);
  490. if(iterFind == mValidParams.end())
  491. {
  492. LOGWRN("Material doesn't have a parameter named " + name);
  493. return;
  494. }
  495. setParam(name, value);
  496. }
  497. void Material::setColor(const String& name, const Color& value)
  498. {
  499. throwIfNotInitialized();
  500. auto iterFind = mValidParams.find(name);
  501. if(iterFind == mValidParams.end())
  502. {
  503. LOGWRN("Material doesn't have a parameter named " + name);
  504. return;
  505. }
  506. setParam(name, value);
  507. }
  508. void Material::setVec2(const String& name, const Vector2& value)
  509. {
  510. throwIfNotInitialized();
  511. auto iterFind = mValidParams.find(name);
  512. if(iterFind == mValidParams.end())
  513. {
  514. LOGWRN("Material doesn't have a parameter named " + name);
  515. return;
  516. }
  517. setParam(name, value);
  518. }
  519. void Material::setVec3(const String& name, const Vector3& value)
  520. {
  521. throwIfNotInitialized();
  522. auto iterFind = mValidParams.find(name);
  523. if(iterFind == mValidParams.end())
  524. {
  525. LOGWRN("Material doesn't have a parameter named " + name);
  526. return;
  527. }
  528. setParam(name, value);
  529. }
  530. void Material::setVec4(const String& name, const Vector4& value)
  531. {
  532. throwIfNotInitialized();
  533. auto iterFind = mValidParams.find(name);
  534. if(iterFind == mValidParams.end())
  535. {
  536. LOGWRN("Material doesn't have a parameter named " + name);
  537. return;
  538. }
  539. setParam(name, value);
  540. }
  541. void Material::setMat3(const String& name, const Matrix3& value)
  542. {
  543. throwIfNotInitialized();
  544. auto iterFind = mValidParams.find(name);
  545. if(iterFind == mValidParams.end())
  546. {
  547. LOGWRN("Material doesn't have a parameter named " + name);
  548. return;
  549. }
  550. setParam(name, value);
  551. }
  552. void Material::setMat4(const String& name, const Matrix4& value)
  553. {
  554. throwIfNotInitialized();
  555. auto iterFind = mValidParams.find(name);
  556. if(iterFind == mValidParams.end())
  557. {
  558. LOGWRN("Material doesn't have a parameter named " + name);
  559. return;
  560. }
  561. setParam(name, value);
  562. }
  563. void Material::setParamBlock(const String& name, GpuParamBlockPtr paramBlock)
  564. {
  565. auto iterFind = mValidShareableParamBlocks.find(name);
  566. if(iterFind == mValidShareableParamBlocks.end())
  567. {
  568. LOGWRN("Material doesn't have a parameter block named " + name);
  569. return;
  570. }
  571. for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  572. {
  573. PassParametersPtr params = *iter;
  574. for(UINT32 i = 0; i < params->getNumParams(); i++)
  575. {
  576. GpuParamsPtr& paramPtr = params->getParamByIdx(i);
  577. if(paramPtr)
  578. {
  579. if(paramPtr->hasParamBlock(name))
  580. paramPtr->setParam(name, paramBlock);
  581. }
  582. }
  583. }
  584. }
  585. UINT32 Material::getNumPasses() const
  586. {
  587. throwIfNotInitialized();
  588. return mShader->getBestTechnique()->getNumPasses();
  589. }
  590. PassPtr Material::getPass(UINT32 passIdx) const
  591. {
  592. if(passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
  593. CM_EXCEPT(InvalidParametersException, "Invalid pass index.");
  594. return mShader->getBestTechnique()->getPass(passIdx);
  595. }
  596. PassParametersPtr Material::getPassParameters(UINT32 passIdx) const
  597. {
  598. if(passIdx < 0 || passIdx >= mParametersPerPass.size())
  599. CM_EXCEPT(InvalidParametersException, "Invalid pass index.");
  600. return mParametersPerPass[passIdx];
  601. }
  602. RTTITypeBase* Material::getRTTIStatic()
  603. {
  604. return MaterialRTTI::instance();
  605. }
  606. RTTITypeBase* Material::getRTTI() const
  607. {
  608. return Material::getRTTIStatic();
  609. }
  610. }