CmMaterial.cpp 21 KB

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