CmMaterial.cpp 24 KB

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