Material.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #include <cstring>
  2. #include "Material.h"
  3. #include "Resource.h"
  4. #include "Scanner.h"
  5. #include "Parser.h"
  6. #include "Texture.h"
  7. #include "ShaderProg.h"
  8. #include "App.h"
  9. #include "MainRenderer.h"
  10. /// Customized THROW_EXCEPTION
  11. #define MTL_EXCEPTION(x) EXCEPTION("Material \"" + getRsrcPath() + getRsrcName() + "\": " + x)
  12. //======================================================================================================================
  13. // Statics =
  14. //======================================================================================================================
  15. Material::StdVarNameAndGlDataTypePair Material::stdAttribVarInfos[SAV_NUM] =
  16. {
  17. {"position", GL_FLOAT_VEC3},
  18. {"tangent", GL_FLOAT_VEC4},
  19. {"normal", GL_FLOAT_VEC3},
  20. {"texCoords", GL_FLOAT_VEC2},
  21. {"vertWeightBonesNum", GL_FLOAT},
  22. {"vertWeightBoneIds", GL_FLOAT_VEC4},
  23. {"vertWeightWeights", GL_FLOAT_VEC4}
  24. };
  25. Material::StdVarNameAndGlDataTypePair Material::stdUniVarInfos[SUV_NUM] =
  26. {
  27. {"skinningRotations", GL_FLOAT_MAT3},
  28. {"skinningTranslations", GL_FLOAT_VEC3},
  29. {"modelMat", GL_FLOAT_MAT4},
  30. {"viewMat", GL_FLOAT_MAT4},
  31. {"projectionMat", GL_FLOAT_MAT4},
  32. {"modelViewMat", GL_FLOAT_MAT4},
  33. {"ViewProjectionMat", GL_FLOAT_MAT4},
  34. {"normalMat", GL_FLOAT_MAT3},
  35. {"modelViewProjectionMat", GL_FLOAT_MAT4},
  36. {"msNormalFai", GL_SAMPLER_2D},
  37. {"msDiffuseFai", GL_SAMPLER_2D},
  38. {"msSpecularFai", GL_SAMPLER_2D},
  39. {"msDepthFai", GL_SAMPLER_2D},
  40. {"isFai", GL_SAMPLER_2D},
  41. {"ppsPrePassFai", GL_SAMPLER_2D},
  42. {"ppsPostPassFai", GL_SAMPLER_2D},
  43. {"rendererSize", GL_FLOAT_VEC2},
  44. {"sceneAmbientColor", GL_FLOAT_VEC3}
  45. };
  46. Material::PreprocDefines Material::msGenericDefines [] =
  47. {
  48. {"DIFFUSE_MAPPING", 'd'},
  49. {"NORMAL_MAPPING", 'n'},
  50. {"SPECULAR_MAPPING", 's'},
  51. {"PARALLAX_MAPPING", 'p'},
  52. {"ENVIRONMENT_MAPPING", 'e'},
  53. {"ALPHA_TESTING", 'a'},
  54. {"HARDWARE_SKINNING", 'h'},
  55. {NULL, NULL}
  56. };
  57. Material::PreprocDefines Material::dpGenericDefines [] =
  58. {
  59. {"ALPHA_TESTING", 'a'},
  60. {"HARDWARE_SKINNING", 'h'},
  61. {NULL, NULL}
  62. };
  63. //======================================================================================================================
  64. // Blending stuff =
  65. //======================================================================================================================
  66. struct BlendParam
  67. {
  68. int glEnum;
  69. const char* str;
  70. };
  71. static BlendParam blendingParams[] =
  72. {
  73. {GL_ZERO, "GL_ZERO"},
  74. {GL_ONE, "GL_ONE"},
  75. {GL_DST_COLOR, "GL_DST_COLOR"},
  76. {GL_ONE_MINUS_DST_COLOR, "GL_ONE_MINUS_DST_COLOR"},
  77. {GL_SRC_ALPHA, "GL_SRC_ALPHA"},
  78. {GL_ONE_MINUS_SRC_ALPHA, "GL_ONE_MINUS_SRC_ALPHA"},
  79. {GL_DST_ALPHA, "GL_DST_ALPHA"},
  80. {GL_ONE_MINUS_DST_ALPHA, "GL_ONE_MINUS_DST_ALPHA"},
  81. {GL_SRC_ALPHA_SATURATE, "GL_SRC_ALPHA_SATURATE"},
  82. {GL_SRC_COLOR, "GL_SRC_COLOR"},
  83. {GL_ONE_MINUS_SRC_COLOR, "GL_ONE_MINUS_SRC_COLOR"},
  84. {0, NULL}
  85. };
  86. static bool searchBlendEnum(const char* str, int& gl_enum)
  87. {
  88. BlendParam* ptr = &blendingParams[0];
  89. while(true)
  90. {
  91. if(ptr->str == NULL)
  92. {
  93. break;
  94. }
  95. if(!strcmp(ptr->str, str))
  96. {
  97. gl_enum = ptr->glEnum;
  98. return true;
  99. }
  100. }
  101. return false;
  102. }
  103. //======================================================================================================================
  104. // Constructor =
  105. //======================================================================================================================
  106. Material::Material():
  107. Resource(RT_MATERIAL)
  108. {
  109. blendingStage = false;
  110. blendingSfactor = GL_ONE;
  111. blendingDfactor = GL_ZERO;
  112. depthTesting = true;
  113. wireframe = false;
  114. castsShadow = true;
  115. }
  116. //======================================================================================================================
  117. // load =
  118. //======================================================================================================================
  119. void Material::load(const char* filename)
  120. {
  121. Scanner scanner(filename);
  122. const Scanner::Token* token;
  123. while(true)
  124. {
  125. token = &scanner.getNextToken();
  126. //
  127. // Shader program
  128. //
  129. if(Parser::isIdentifier(token, "shaderProg"))
  130. {
  131. if(shaderProg.get())
  132. {
  133. throw PARSER_EXCEPTION("Shader program already loaded");
  134. }
  135. token = &scanner.getNextToken();
  136. std::string shaderFilename;
  137. // Just a string
  138. if(token->getCode() == Scanner::TC_STRING)
  139. {
  140. shaderFilename = token->getValue().getString();
  141. }
  142. // Its { so... build custom shader
  143. else if(token->getCode() == Scanner::TC_LBRACKET)
  144. {
  145. std::string sProgFilename;
  146. std::string source;
  147. std::string prefix;
  148. std::string op = Parser::parseIdentifier(scanner);
  149. if(op == "customMsSProg")
  150. {
  151. parseCustomShader(msGenericDefines, scanner, sProgFilename, source, prefix);
  152. }
  153. else if(op == "customDpSProg")
  154. {
  155. parseCustomShader(dpGenericDefines, scanner, sProgFilename, source, prefix);
  156. }
  157. else
  158. {
  159. throw PARSER_EXCEPTION_EXPECTED("identifier customMsSProg or customDpSProg");
  160. }
  161. shaderFilename = ShaderProg::createSrcCodeToCache(sProgFilename.c_str(), source.c_str(), prefix.c_str());
  162. // }
  163. token = &scanner.getNextToken();
  164. if(token->getCode() != Scanner::TC_RBRACKET)
  165. {
  166. throw PARSER_EXCEPTION_EXPECTED("}");
  167. }
  168. }
  169. else
  170. {
  171. throw PARSER_EXCEPTION_EXPECTED("string or {");
  172. }
  173. shaderProg.loadRsrc(shaderFilename.c_str());
  174. }
  175. //
  176. // dpMtl
  177. //
  178. else if(Parser::isIdentifier(token, "dpMtl"))
  179. {
  180. if(dpMtl.get())
  181. {
  182. throw PARSER_EXCEPTION("Depth material already loaded");
  183. }
  184. dpMtl.loadRsrc(Parser::parseString(scanner).c_str());
  185. }
  186. //
  187. // blendingStage
  188. //
  189. else if(Parser::isIdentifier(token, "blendingStage"))
  190. {
  191. blendingStage = Parser::parseBool(scanner);
  192. }
  193. //
  194. // blendFuncs
  195. //
  196. else if(Parser::isIdentifier(token, "blendFuncs"))
  197. {
  198. // {
  199. token = &scanner.getNextToken();
  200. if(token->getCode() != Scanner::TC_LBRACKET)
  201. {
  202. throw PARSER_EXCEPTION_EXPECTED("{");
  203. }
  204. // sFactor
  205. Parser::parseIdentifier(scanner, "sFactor");
  206. int gl_enum;
  207. if(!searchBlendEnum(Parser::parseIdentifier(scanner).c_str(), gl_enum))
  208. {
  209. throw PARSER_EXCEPTION("Incorrect blending factor \"" + token->getValue().getString() + "\"");
  210. }
  211. blendingSfactor = gl_enum;
  212. // dFactor
  213. Parser::parseIdentifier(scanner, "dFactor");
  214. if(!searchBlendEnum(Parser::parseIdentifier(scanner).c_str(), gl_enum))
  215. {
  216. throw PARSER_EXCEPTION("Incorrect blending factor \"" + token->getValue().getString() + "\"");
  217. }
  218. blendingDfactor = gl_enum;
  219. }
  220. //
  221. // depthTesting
  222. //
  223. else if(Parser::isIdentifier(token, "depthTesting"))
  224. {
  225. depthTesting = Parser::parseBool(scanner);
  226. }
  227. //
  228. // wireframe
  229. //
  230. else if(Parser::isIdentifier(token, "wireframe"))
  231. {
  232. wireframe = Parser::parseBool(scanner);
  233. }
  234. //
  235. // castsShadow
  236. //
  237. else if(Parser::isIdentifier(token, "castsShadow"))
  238. {
  239. castsShadow = Parser::parseBool(scanner);
  240. }
  241. //
  242. // userDefinedVars
  243. //
  244. else if(Parser::isIdentifier(token, "userDefinedVars"))
  245. {
  246. // first check if the shader is defined
  247. if(shaderProg.get() == NULL)
  248. {
  249. throw PARSER_EXCEPTION("You have to define the shader program before the user defined vars");
  250. }
  251. // {
  252. token = &scanner.getNextToken();
  253. if(token->getCode() != Scanner::TC_LBRACKET)
  254. {
  255. throw PARSER_EXCEPTION_EXPECTED("{");
  256. }
  257. // loop all the vars
  258. do
  259. {
  260. // read the name
  261. token = &scanner.getNextToken();
  262. if(token->getCode() == Scanner::TC_RBRACKET)
  263. {
  264. break;
  265. }
  266. if(token->getCode() != Scanner::TC_IDENTIFIER)
  267. {
  268. throw PARSER_EXCEPTION_EXPECTED("identifier");
  269. }
  270. std::string varName;
  271. varName = token->getValue().getString();
  272. userDefinedVars.push_back(new UserDefinedUniVar); // create new var
  273. UserDefinedUniVar& var = userDefinedVars.back();
  274. // check if the uniform exists
  275. if(!shaderProg->uniVarExists(varName.c_str()))
  276. {
  277. throw PARSER_EXCEPTION("The variable \"" + varName + "\" is not an active uniform");
  278. }
  279. var.sProgVar = shaderProg->findUniVar(varName.c_str());
  280. // read the values
  281. switch(var.sProgVar->getGlDataType())
  282. {
  283. // texture
  284. case GL_SAMPLER_2D:
  285. var.value.texture.loadRsrc(Parser::parseString(scanner).c_str());
  286. break;
  287. // float
  288. case GL_FLOAT:
  289. token = &scanner.getNextToken();
  290. if(token->getCode() == Scanner::TC_NUMBER && token->getDataType() == Scanner::DT_FLOAT)
  291. {
  292. var.value.float_ = token->getValue().getFloat();
  293. }
  294. else
  295. {
  296. throw PARSER_EXCEPTION_EXPECTED("float");
  297. }
  298. break;
  299. // vec2
  300. case GL_FLOAT_VEC2:
  301. Parser::parseMathVector(scanner, var.value.vec2);
  302. break;
  303. // vec3
  304. case GL_FLOAT_VEC3:
  305. Parser::parseMathVector(scanner, var.value.vec3);
  306. break;
  307. // vec4
  308. case GL_FLOAT_VEC4:
  309. Parser::parseMathVector(scanner, var.value.vec4);
  310. break;
  311. };
  312. }while(true); // end loop for all the vars
  313. }
  314. //
  315. // EOF
  316. //
  317. else if(token->getCode() == Scanner::TC_EOF)
  318. {
  319. break;
  320. }
  321. //
  322. // other crap
  323. //
  324. else
  325. {
  326. throw PARSER_EXCEPTION_UNEXPECTED();
  327. }
  328. } // end while
  329. initStdShaderVars();
  330. }
  331. //======================================================================================================================
  332. // initStdShaderVars =
  333. //======================================================================================================================
  334. void Material::initStdShaderVars()
  335. {
  336. // sanity checks
  337. if(!shaderProg.get())
  338. {
  339. throw MTL_EXCEPTION("Without shader is like cake without sugar (missing SHADER_PROG)");
  340. }
  341. // the attributes
  342. for(uint i=0; i<SAV_NUM; i++)
  343. {
  344. // if the var is not in the sProg then... bye
  345. if(!shaderProg->attribVarExists(stdAttribVarInfos[i].varName))
  346. {
  347. stdAttribVars[i] = NULL;
  348. continue;
  349. }
  350. // set the std var
  351. stdAttribVars[i] = shaderProg->findAttribVar(stdAttribVarInfos[i].varName);
  352. // check if the shader has different GL data type from that it suppose to have
  353. if(stdAttribVars[i]->getGlDataType() != stdAttribVarInfos[i].dataType)
  354. {
  355. throw MTL_EXCEPTION("The \"" + stdAttribVarInfos[i].varName +
  356. "\" attribute var has incorrect GL data type from the expected");
  357. }
  358. }
  359. // the uniforms
  360. for(uint i=0; i<SUV_NUM; i++)
  361. {
  362. // if the var is not in the sProg then... bye
  363. if(!shaderProg->uniVarExists(stdUniVarInfos[i].varName))
  364. {
  365. stdUniVars[i] = NULL;
  366. continue;
  367. }
  368. // set the std var
  369. stdUniVars[i] = shaderProg->findUniVar(stdUniVarInfos[i].varName);
  370. // check if the shader has different GL data type from that it suppose to have
  371. if(stdUniVars[i]->getGlDataType() != stdUniVarInfos[i].dataType)
  372. {
  373. throw MTL_EXCEPTION("The \"" + stdUniVarInfos[i].varName +
  374. "\" uniform var has incorrect GL data type from the expected");
  375. }
  376. }
  377. }
  378. //======================================================================================================================
  379. // parseCustomShader =
  380. //======================================================================================================================
  381. void Material::parseCustomShader(const PreprocDefines defines[], Scanner& scanner,
  382. std::string& shaderFilename, std::string& source, std::string& prefix)
  383. {
  384. const Scanner::Token* token;
  385. // {
  386. token = &scanner.getNextToken();
  387. if(token->getCode() != Scanner::TC_LBRACKET)
  388. {
  389. throw PARSER_EXCEPTION_EXPECTED("{");
  390. }
  391. // file
  392. Parser::parseIdentifier(scanner, "file");
  393. // the shader prog
  394. shaderFilename = Parser::parseString(scanner);
  395. // defines
  396. Parser::parseIdentifier(scanner, "defines");
  397. // {
  398. token = &scanner.getNextToken();
  399. if(token->getCode() != Scanner::TC_LBRACKET)
  400. {
  401. throw PARSER_EXCEPTION_EXPECTED("{");
  402. }
  403. // Get the defines
  404. while(true)
  405. {
  406. token = &scanner.getNextToken();
  407. // }
  408. if(token->getCode() == Scanner::TC_RBRACKET)
  409. {
  410. break;
  411. }
  412. else if(token->getCode() != Scanner::TC_IDENTIFIER)
  413. {
  414. throw PARSER_EXCEPTION_EXPECTED("identifier");
  415. }
  416. // Check if acceptable value. Loop the switches array
  417. const PreprocDefines* def = defines;
  418. while(def->switchName != NULL)
  419. {
  420. if(!strcmp(def->switchName, token->getString()))
  421. {
  422. break;
  423. }
  424. ++def;
  425. }
  426. if(def->switchName == NULL)
  427. {
  428. throw PARSER_EXCEPTION("Not acceptable define " + token->getString());
  429. }
  430. source += std::string("#define ") + token->getString() + "\n";
  431. prefix.push_back(def->prefix);
  432. } // end get the switches
  433. // }
  434. token = &scanner.getNextToken();
  435. if(token->getCode() != Scanner::TC_RBRACKET)
  436. {
  437. throw PARSER_EXCEPTION_EXPECTED("}");
  438. }
  439. std::sort(prefix.begin(), prefix.end());
  440. }