Compiler.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <utility>
  5. // filesystem
  6. #include <WallpaperEngine/FileSystem/FileSystem.h>
  7. // shader compiler
  8. #include <WallpaperEngine/Render/Shaders/Compiler.h>
  9. #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h>
  10. #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
  11. #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h>
  12. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
  13. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
  14. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
  15. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector2.h"
  16. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector3.h"
  17. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h"
  18. using namespace WallpaperEngine::Core;
  19. using namespace WallpaperEngine::Assets;
  20. namespace WallpaperEngine::Render::Shaders
  21. {
  22. Compiler::Compiler (
  23. CContainer* container,
  24. std::string filename,
  25. Type type,
  26. std::map<std::string, int>* combos,
  27. const std::map<std::string, CShaderConstant*>& constants,
  28. bool recursive) :
  29. m_combos (combos),
  30. m_recursive (recursive),
  31. m_type (type),
  32. m_file (std::move(filename)),
  33. m_error (""),
  34. m_errorInfo (""),
  35. m_constants (constants),
  36. m_container (container)
  37. {
  38. if (type == Type_Vertex)
  39. this->m_content = this->m_container->readVertexShader (this->m_file);
  40. else if (type == Type_Pixel)
  41. this->m_content = this->m_container->readFragmentShader (this->m_file);
  42. else if (type == Type_Include)
  43. this->m_content = this->m_container->readIncludeShader (this->m_file);
  44. }
  45. bool Compiler::peekString(std::string str, std::string::const_iterator& it)
  46. {
  47. std::string::const_iterator check = str.begin();
  48. std::string::const_iterator cur = it;
  49. while (cur != this->m_content.end () && check != str.end ())
  50. {
  51. if (*cur != *check) return false;
  52. cur ++; check ++;
  53. }
  54. if (cur == this->m_content.end ())
  55. {
  56. return false;
  57. }
  58. if (check != str.end ())
  59. {
  60. return false;
  61. }
  62. it = cur;
  63. return true;
  64. }
  65. bool Compiler::expectSemicolon (std::string::const_iterator& it)
  66. {
  67. if (*it != ';')
  68. {
  69. this->m_error = true;
  70. this->m_errorInfo = "Expected semicolon but got " + *it;
  71. return false;
  72. }
  73. it ++;
  74. return true;
  75. }
  76. void Compiler::ignoreSpaces(std::string::const_iterator &it)
  77. {
  78. while (it != this->m_content.end() && (*it == ' ' || *it == '\t')) it ++;
  79. }
  80. void Compiler::ignoreUpToNextLineFeed (std::string::const_iterator& it)
  81. {
  82. while (it != this->m_content.end() && *it != '\n') it ++;
  83. }
  84. void Compiler::ignoreUpToBlockCommentEnd (std::string::const_iterator& it)
  85. {
  86. while (it != this->m_content.end() && this->peekString ("*/", it) == false) it ++;
  87. }
  88. std::string Compiler::extractType (std::string::const_iterator& it)
  89. {
  90. // first of all check for highp/mediump/lowp as these operators have to be ignored
  91. this->peekString ("highp", it);
  92. this->peekString ("mediump", it);
  93. this->peekString ("lowp", it);
  94. this->ignoreSpaces (it);
  95. auto cur = sTypes.begin ();
  96. auto end = sTypes.end ();
  97. while (cur != end)
  98. {
  99. if (this->peekString (*cur + " ", it) == true)
  100. {
  101. return *cur;
  102. }
  103. cur ++;
  104. }
  105. this->m_error = true;
  106. this->m_errorInfo = "Expected type";
  107. return "";
  108. }
  109. std::string Compiler::extractName (std::string::const_iterator& it)
  110. {
  111. std::string::const_iterator cur = it;
  112. std::string::const_iterator begin = cur;
  113. // first character has to be a valid alphabetic characer
  114. if (this->isChar (cur) == false && *cur != '_')
  115. {
  116. this->m_error = true;
  117. this->m_errorInfo = "Expected name doesn't start with a valid character";
  118. return "";
  119. }
  120. cur ++;
  121. while (cur != this->m_content.end () && (this->isChar (cur) == true || *cur == '_' || this->isNumeric (cur) == true)) cur ++;
  122. it = cur;
  123. return std::string (begin, cur);
  124. }
  125. std::string Compiler::extractArray(std::string::const_iterator &it, bool mustExists)
  126. {
  127. std::string::const_iterator cur = it;
  128. std::string::const_iterator begin = cur;
  129. if (*cur != '[')
  130. {
  131. if (mustExists == false)
  132. return "";
  133. this->m_error = true;
  134. this->m_errorInfo = "Expected an array but found nothing";
  135. return "";
  136. }
  137. cur ++;
  138. while (cur != this->m_content.end () && *cur != ']') cur ++;
  139. it = ++cur;
  140. return std::string (begin, cur);
  141. }
  142. bool Compiler::isChar (std::string::const_iterator& it)
  143. {
  144. return ((*it) >= 'A' && (*it) <= 'Z') || ((*it) >= 'a' && (*it) <= 'z');
  145. }
  146. bool Compiler::isNumeric (std::string::const_iterator& it)
  147. {
  148. return (*it) >= '0' && (*it) <= '9';
  149. }
  150. std::string Compiler::extractQuotedValue(std::string::const_iterator& it)
  151. {
  152. std::string::const_iterator cur = it;
  153. if (*cur != '"')
  154. {
  155. m_error = true;
  156. m_errorInfo = "Expected opening \" but got " + (*cur);
  157. return "";
  158. }
  159. cur ++;
  160. while (cur != this->m_content.end () && *cur != '\n' && *cur != '"') cur ++;
  161. if (cur == this->m_content.end ())
  162. {
  163. m_error = true;
  164. m_errorInfo = "Expected closing \" not found";
  165. it = cur;
  166. return "";
  167. }
  168. std::string filename = std::string (++it, cur);
  169. it = ++cur;
  170. return filename;
  171. }
  172. std::string Compiler::lookupShaderFile (std::string filename)
  173. {
  174. // now compile the new shader
  175. // do not include the default header (as it's already included in the parent)
  176. Compiler loader (this->m_container, std::move (filename), Type_Include, this->m_combos, this->m_constants, true);
  177. loader.precompile ();
  178. return loader.getCompiled ();
  179. }
  180. std::string& Compiler::getCompiled ()
  181. {
  182. return this->m_compiledContent;
  183. }
  184. void Compiler::precompile()
  185. {
  186. // TODO: SEPARATE THIS IN TWO SO THE COMBOS ARE DETECTED FIRST AND WE DO NOT REQUIRE DOUBLE COMPILATION OF THE SHADER'S SOURCE
  187. #define BREAK_IF_ERROR if (this->m_error == true) { throw std::runtime_error ("ERROR PRE-COMPILING SHADER" + this->m_errorInfo); }
  188. // parse the shader and find #includes and such things and translate them to the correct name
  189. // also remove any #version definition to prevent errors
  190. std::string::const_iterator it = this->m_content.begin ();
  191. // reset error indicator
  192. this->m_error = false;
  193. this->m_errorInfo = "";
  194. this->m_compiledContent = "";
  195. this->m_includesContent = "";
  196. // search preprocessor macros and parse them
  197. while (it != this->m_content.end () && this->m_error == false)
  198. {
  199. if (*it == ' ' || *it == '\t' || *it == '\n' || *it == '\r' || *it == '\0' || *it == '{' || *it == '}' || *it == '[' || *it == ']' || *it == '.')
  200. {
  201. this->m_compiledContent += *it;
  202. it ++;
  203. }
  204. else if (*it == '#')
  205. {
  206. if (this->peekString ("#include ", it) == true)
  207. {
  208. std::string filename = "";
  209. // ignore whitespaces
  210. this->ignoreSpaces (it); BREAK_IF_ERROR
  211. // extract value between quotes
  212. filename = this->extractQuotedValue (it); BREAK_IF_ERROR
  213. if (this->m_content.find (" main(") == std::string::npos && this->m_content.find (" main (") == std::string::npos)
  214. {
  215. this->m_compiledContent += "// begin of include from file " + filename + "\r\n";
  216. this->m_compiledContent += this->lookupShaderFile (filename);
  217. this->m_compiledContent += "\r\n// end of included from file " + filename + "\r\n";
  218. }
  219. else
  220. {
  221. // load the content to the includes contents and continue with the next one
  222. // try to find the file first
  223. this->m_includesContent += "// begin of included from file " + filename + "\r\n";
  224. this->m_includesContent += this->lookupShaderFile (filename);
  225. this->m_includesContent += "\r\n// end of included from file " + filename + "\r\n";
  226. }
  227. }
  228. else
  229. {
  230. this->m_compiledContent += '#';
  231. it ++;
  232. }
  233. }
  234. else if (*it == 'u')
  235. {
  236. // uniforms might have extra information for their values
  237. if (this->peekString ("uniform ", it) == true)
  238. {
  239. this->ignoreSpaces (it);
  240. std::string type = this->extractType (it); BREAK_IF_ERROR
  241. this->ignoreSpaces (it);
  242. std::string name = this->extractName (it); BREAK_IF_ERROR
  243. this->ignoreSpaces (it);
  244. std::string array = this->extractArray (it, false); BREAK_IF_ERROR
  245. this->ignoreSpaces (it);
  246. this->expectSemicolon (it); BREAK_IF_ERROR
  247. this->ignoreSpaces (it);
  248. // check if there is any actual extra information and parse it
  249. if (this->peekString ("//", it) == true)
  250. {
  251. this->ignoreSpaces (it);
  252. std::string::const_iterator begin = it;
  253. this->ignoreUpToNextLineFeed (it);
  254. std::string configuration; configuration.append (begin, it);
  255. // parse the parameter information
  256. this->parseParameterConfiguration (type, name, configuration); BREAK_IF_ERROR
  257. this->m_compiledContent += "uniform " + type + " " + name + array + "; // " + configuration;
  258. }
  259. else
  260. {
  261. this->m_compiledContent += "uniform " + type + " " + name + array + ";";
  262. }
  263. }
  264. else
  265. {
  266. // continue reading the original shader as this most likely is a variable name or something
  267. // that is not really interesting for the compiler
  268. this->m_compiledContent += *it;
  269. it ++;
  270. }
  271. }
  272. else if (*it == 'a')
  273. {
  274. // find attribute definitions
  275. if (this->peekString ("attribute ", it) == true)
  276. {
  277. this->ignoreSpaces (it);
  278. std::string type = this->extractType (it); BREAK_IF_ERROR
  279. this->ignoreSpaces (it);
  280. std::string name = this->extractName (it); BREAK_IF_ERROR
  281. this->ignoreSpaces (it);
  282. std::string array = this->extractArray (it, false); BREAK_IF_ERROR
  283. this->ignoreSpaces (it);
  284. this->expectSemicolon (it); BREAK_IF_ERROR
  285. this->m_compiledContent += "attribute " + type + " " + name + array + ";";
  286. }
  287. else
  288. {
  289. // check for types first
  290. std::string type = this->extractType (it);
  291. // types not found, try names
  292. if (this->m_error == false)
  293. {
  294. this->m_compiledContent += type;
  295. }
  296. else
  297. {
  298. this->m_error = false;
  299. std::string name = this->extractName (it);
  300. if (this->m_error == false)
  301. {
  302. // check if the name is a translated one or not
  303. this->m_compiledContent += name;
  304. }
  305. else
  306. {
  307. this->m_error = false;
  308. this->m_compiledContent += *it;
  309. it ++;
  310. }
  311. }
  312. }
  313. }
  314. else if (*it == '/')
  315. {
  316. if (this->peekString ("//", it) == true)
  317. {
  318. std::string::const_iterator begin = it - 2;
  319. // is there a COMBO mark to take care of?
  320. this->ignoreSpaces (it);
  321. if (this->peekString ("[COMBO]", it) == true)
  322. {
  323. // parse combo json data to define the proper variables
  324. this->ignoreSpaces (it);
  325. begin = it;
  326. this->ignoreUpToNextLineFeed (it);
  327. std::string configuration; configuration.append (begin, it);
  328. this->m_compiledContent += "// [COMBO] " + configuration;
  329. this->parseComboConfiguration (configuration, 1); BREAK_IF_ERROR;
  330. }
  331. else if (this->peekString ("[COMBO_OFF]", it) == true)
  332. {
  333. // parse combo json data to define the proper variables
  334. this->ignoreSpaces (it);
  335. begin = it;
  336. this->ignoreUpToNextLineFeed (it);
  337. std::string configuration; configuration.append (begin, it);
  338. this->m_compiledContent += "// [COMBO_OFF] " + configuration;
  339. this->parseComboConfiguration (configuration, 0); BREAK_IF_ERROR;
  340. }
  341. else
  342. {
  343. // the comment can be ignored and put back as is
  344. this->ignoreUpToNextLineFeed(it);
  345. this->m_compiledContent.append (begin, it);
  346. }
  347. }
  348. else if (this->peekString ("/*", it) == true)
  349. {
  350. std::string::const_iterator begin = it - 2;
  351. this->ignoreUpToBlockCommentEnd (it);
  352. this->m_compiledContent.append (begin, it);
  353. }
  354. else
  355. {
  356. this->m_compiledContent += *it;
  357. it ++;
  358. }
  359. }
  360. else
  361. {
  362. // check for types first
  363. std::string type = this->extractType (it);
  364. // types not found, try names
  365. if (this->m_error == false)
  366. {
  367. // check for main, and take it into account, this also helps adding the includes
  368. if (type == "void")
  369. {
  370. std::string name = this->extractName (it);
  371. if (name == "main")
  372. {
  373. this->m_compiledContent += "\n\n" + this->m_includesContent + "\n\n";
  374. this->m_compiledContent += type + " " + name;
  375. }
  376. else
  377. {
  378. this->m_compiledContent += name;
  379. }
  380. }
  381. else
  382. {
  383. this->m_compiledContent += type + " ";
  384. }
  385. }
  386. else
  387. {
  388. this->m_error = false;
  389. std::string name = this->extractName (it);
  390. if (this->m_error == false)
  391. {
  392. // check if the name is a translated one or not
  393. this->m_compiledContent += name;
  394. }
  395. else
  396. {
  397. this->m_error = false;
  398. this->m_compiledContent += *it++;
  399. }
  400. }
  401. }
  402. }
  403. std::string finalCode;
  404. if (this->m_recursive == false)
  405. {
  406. // add the opengl compatibility at the top
  407. finalCode = "#version 120\n"
  408. "#define highp\n"
  409. "#define mediump\n"
  410. "#define lowp\n"
  411. "#define mul(x, y) (y * x)\n"
  412. "#define max(x, y) max (y, x)\n"
  413. "#define frac fract\n"
  414. "#define CAST2(x) (vec2(x))\n"
  415. "#define CAST3(x) (vec3(x))\n"
  416. "#define CAST4(x) (vec4(x))\n"
  417. "#define CAST3X3(x) (mat3(x))\n"
  418. "#define saturate(x) (clamp(x, 0.0, 1.0))\n"
  419. "#define texSample2D texture2D\n"
  420. "#define texSample2DLod texture2D\n"
  421. "#define atan2 atan\n"
  422. "#define ddx dFdx\n"
  423. "#define ddy(x) dFdy(-(x))\n"
  424. "#define GLSL 1\n"
  425. "#define HLSL 1\n";
  426. // add combo values
  427. auto cur = this->m_combos->begin ();
  428. auto end = this->m_combos->end ();
  429. for (; cur != end; cur ++)
  430. {
  431. finalCode += "#define " + (*cur).first + " " + std::to_string ((*cur).second) + "\n";
  432. }
  433. }
  434. finalCode += this->m_compiledContent;
  435. if (DEBUG && this->m_recursive == false)
  436. {
  437. if (this->m_type == Type_Vertex)
  438. std::cout << "======================== COMPILED VERTEX SHADER " << this->m_file.c_str () << " ========================" << std::endl;
  439. else
  440. std::cout << "======================== COMPILED FRAGMENT SHADER " << this->m_file.c_str () << " ========================" << std::endl;
  441. std::cout << finalCode << std::endl;
  442. }
  443. // store the final final code here
  444. this->m_compiledContent = finalCode;
  445. #undef BREAK_IF_ERROR
  446. }
  447. void Compiler::parseComboConfiguration (const std::string& content, int defaultValue)
  448. {
  449. json data = json::parse (content);
  450. auto combo = jsonFindRequired (data, "combo", "cannot parse combo information");
  451. auto defvalue = data.find ("default");
  452. // add line feed just in case
  453. this->m_compiledContent += "\n";
  454. // check the combos
  455. std::map<std::string, int>::const_iterator entry = this->m_combos->find ((*combo).get <std::string> ());
  456. // if the combo was not found in the predefined values this means that the default value in the JSON data can be used
  457. // so only define the ones that are not already defined
  458. if (entry == this->m_combos->end ())
  459. {
  460. // if no combo is defined just load the default settings
  461. if (defvalue == data.end ())
  462. {
  463. // TODO: PROPERLY SUPPORT EMPTY COMBOS
  464. this->m_combos->insert (std::make_pair <std::string, int> (*combo, (int) defaultValue));
  465. }
  466. else if ((*defvalue).is_number_float ())
  467. {
  468. throw std::runtime_error ("float combos not supported");
  469. }
  470. else if ((*defvalue).is_number_integer ())
  471. {
  472. this->m_combos->insert (std::make_pair <std::string, int> (*combo, (*defvalue).get <int> ()));
  473. }
  474. else if ((*defvalue).is_string ())
  475. {
  476. throw std::runtime_error ("string combos not supported");
  477. }
  478. else
  479. {
  480. throw std::runtime_error ("cannot parse combo information, unknown type");
  481. }
  482. }
  483. }
  484. void Compiler::parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content)
  485. {
  486. json data = json::parse (content);
  487. auto material = data.find ("material");
  488. auto defvalue = data.find ("default");
  489. auto range = data.find ("range");
  490. auto combo = data.find ("combo");
  491. // this is not a real parameter
  492. auto constant = this->m_constants.end ();
  493. if (material != data.end ())
  494. constant = this->m_constants.find (*material);
  495. if (constant == this->m_constants.end () && defvalue == data.end ())
  496. {
  497. if (type != "sampler2D")
  498. throw std::runtime_error ("cannot parse parameter data");
  499. }
  500. Variables::CShaderVariable* parameter = nullptr;
  501. // TODO: SUPPORT VALUES FOR ALL THESE TYPES
  502. if (type == "vec4")
  503. {
  504. parameter = new Variables::CShaderVariableVector4 (
  505. constant == this->m_constants.end ()
  506. ? WallpaperEngine::Core::aToVector4 (*defvalue)
  507. : *(*constant).second->as <CShaderConstantVector4> ()->getValue ()
  508. );
  509. }
  510. else if (type == "vec3")
  511. {
  512. parameter = new Variables::CShaderVariableVector3 (
  513. constant == this->m_constants.end ()
  514. ? WallpaperEngine::Core::aToVector3 (*defvalue)
  515. : *(*constant).second->as <CShaderConstantVector4> ()->getValue ()
  516. );
  517. }
  518. else if (type == "vec2")
  519. {
  520. parameter = new Variables::CShaderVariableVector2 (
  521. WallpaperEngine::Core::aToVector2 (*defvalue)
  522. );
  523. }
  524. else if (type == "float")
  525. {
  526. float value = 0;
  527. if (constant == this->m_constants.end ())
  528. value = (*defvalue).get <float> ();
  529. else if ((*constant).second->is <CShaderConstantFloat> () == true)
  530. value = *(*constant).second->as <CShaderConstantFloat> ()->getValue ();
  531. else if ((*constant).second->is <CShaderConstantInteger> () == true)
  532. value = *(*constant).second->as <CShaderConstantInteger> ()->getValue ();
  533. parameter = new Variables::CShaderVariableFloat (value);
  534. }
  535. else if (type == "int")
  536. {
  537. int value = 0;
  538. if (constant == this->m_constants.end ())
  539. value = (*defvalue).get <int> ();
  540. else if ((*constant).second->is <CShaderConstantFloat> () == true)
  541. value = *(*constant).second->as <CShaderConstantFloat> ()->getValue ();
  542. else if ((*constant).second->is <CShaderConstantInteger> () == true)
  543. value = *(*constant).second->as <CShaderConstantInteger> ()->getValue ();
  544. parameter = new Variables::CShaderVariableInteger (value);
  545. }
  546. else if (type == "sampler2D")
  547. {
  548. // samplers can have special requirements, check what sampler we're working with and create definitions
  549. // if needed
  550. auto combo = data.find ("combo");
  551. auto textureName = data.find ("default");
  552. if (combo != data.end ())
  553. {
  554. // add the new combo to the list
  555. this->m_combos->insert (std::make_pair <std::string, int> (*combo, 1));
  556. if (textureName != data.end ())
  557. {
  558. // also ensure that the textureName is loaded and we know about it
  559. ITexture* texture = this->m_container->readTexture ((*textureName).get <std::string> ());
  560. // extract the texture number from the name
  561. char value = name.at (std::string("g_Texture").length ());
  562. // now convert it to integer
  563. int index = value - '0';
  564. this->m_textures.insert (
  565. std::make_pair (index, texture)
  566. );
  567. }
  568. }
  569. // samplers are not saved, we can ignore them for now
  570. return;
  571. }
  572. else
  573. {
  574. this->m_error = true;
  575. this->m_errorInfo = "Unknown parameter type: " + type + " for " + name;
  576. return;
  577. }
  578. if (material != data.end ())
  579. {
  580. parameter->setIdentifierName (*material);
  581. parameter->setName (name);
  582. this->m_parameters.push_back (parameter);
  583. }
  584. }
  585. Variables::CShaderVariable* Compiler::findParameter (const std::string& identifier)
  586. {
  587. auto cur = this->m_parameters.begin ();
  588. auto end = this->m_parameters.end ();
  589. for (; cur != end; cur ++)
  590. {
  591. if ((*cur)->getIdentifierName () == identifier)
  592. {
  593. return (*cur);
  594. }
  595. }
  596. return nullptr;
  597. }
  598. const std::vector <Variables::CShaderVariable*>& Compiler::getParameters () const
  599. {
  600. return this->m_parameters;
  601. }
  602. std::map <std::string, int>* Compiler::getCombos () const
  603. {
  604. return this->m_combos;
  605. }
  606. const std::map <int, ITexture*>& Compiler::getTextures () const
  607. {
  608. return this->m_textures;
  609. }
  610. std::vector<std::string> Compiler::sTypes =
  611. {
  612. "vec4", "uvec4", "ivec4", "dvec4", "bvec4",
  613. "vec3", "uvec3", "ivec3", "dvec3", "bvec3",
  614. "vec2", "uvec2", "ivec2", "dvec2", "bvec2",
  615. "float", "sampler2D", "mat4x3", "mat4", "mat3", "uint4",
  616. "void"
  617. };
  618. }