Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

10 роки тому
10 роки тому
8 роки тому
8 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <cstring>
  14. #include <cstdio>
  15. #if defined _WIN32
  16. # define WIN32_LEAN_AND_MEAN 1
  17. # include <windows.h>
  18. # undef WIN32_LEAN_AND_MEAN
  19. #endif
  20. #include "pegtl.hh"
  21. #include "lolgl.h"
  22. namespace lol
  23. {
  24. struct ShaderType
  25. {
  26. enum Value
  27. {
  28. Vertex = 1,
  29. Fragment,
  30. Geometry,
  31. TessControl,
  32. TessEval,
  33. }
  34. m_value;
  35. inline ShaderType(Value v) : m_value(v) {}
  36. inline ShaderType(int v) : m_value((Value)v) {}
  37. inline operator Value() { return m_value; }
  38. };
  39. static const char* attribute_names[] =
  40. {
  41. "in_Position",
  42. "in_BlendWeight",
  43. "in_BlendIndices",
  44. "in_Normal",
  45. "in_PointSize",
  46. "in_TexCoord",
  47. "in_TexCoordExt",
  48. "in_Tangent",
  49. "in_Binormal",
  50. "in_TessFactor",
  51. "in_PositionT",
  52. "in_Color",
  53. "in_Fog",
  54. "in_Depth",
  55. "in_Sample"
  56. };
  57. /*
  58. * Shader implementation class
  59. */
  60. class ShaderData
  61. {
  62. friend class Shader;
  63. private:
  64. String m_name;
  65. GLuint prog_id, vert_id, frag_id;
  66. // Benlitz: using a simple array could be faster since there is never more than a few attribute locations to store
  67. map<uint64_t, GLint> attrib_locations;
  68. map<uint64_t, bool> attrib_errors;
  69. uint32_t vert_crc, frag_crc;
  70. /* Shader patcher */
  71. static int GetVersion();
  72. static String Patch(String const &code, ShaderType type);
  73. /* Global shader cache */
  74. static Shader *shaders[];
  75. static hash<char const *> Hash;
  76. static int nshaders;
  77. };
  78. Shader *ShaderData::shaders[256];
  79. hash<char const *> ShaderData::Hash;
  80. int ShaderData::nshaders = 0;
  81. /*
  82. * LolFx parser
  83. */
  84. using namespace pegtl;
  85. struct lolfx_parser
  86. {
  87. public:
  88. String m_section;
  89. map<String, String> m_programs;
  90. private:
  91. // title <- '[' (!']')+ ']' .{eol}
  92. struct do_title
  93. : plus<not_one<']'>> {};
  94. struct title
  95. : seq<one<'['>,
  96. do_title,
  97. one<']'>,
  98. until<eol, any>> {};
  99. // FIXME: I’m using this rule because the do_title above also
  100. // gets triggered when using at<> which is non-consuming.
  101. struct title_ignore
  102. : seq<one<'['>,
  103. plus<not_one<']'>>,
  104. one<']'>,
  105. until<eol, any>> {};
  106. // code_line <- .{eol}
  107. struct code_line
  108. : until<eol, any> {};
  109. // code_section < code_line{&(title / eof)}
  110. struct code_section
  111. : until<at<sor<title_ignore, pegtl::eof>>, code_line> {};
  112. // shader < title code_section
  113. struct shader
  114. : seq<title, code_section> {};
  115. // header < code_section
  116. struct header
  117. : code_section {};
  118. // lolfx < header code_section*
  119. struct lolfx
  120. : seq<header, star<shader>> {};
  121. // default action: nothing
  122. template<typename RULE>
  123. struct action : nothing<RULE> {};
  124. public:
  125. lolfx_parser(String const &code)
  126. : m_section("header")
  127. {
  128. pegtl::parse_string<lolfx, action>(code.C(), "shader", this);
  129. }
  130. };
  131. template<>
  132. struct lolfx_parser::action<lolfx_parser::do_title>
  133. {
  134. static void apply(action_input const &in, lolfx_parser *that)
  135. {
  136. that->m_section = in.string().c_str();
  137. }
  138. };
  139. template<>
  140. struct lolfx_parser::action<lolfx_parser::code_section>
  141. {
  142. static void apply(action_input const &in, lolfx_parser *that)
  143. {
  144. that->m_programs[that->m_section] = in.string().c_str();
  145. }
  146. };
  147. /*
  148. * Public Shader class
  149. */
  150. Shader *Shader::Create(String const &name, String const &code)
  151. {
  152. lolfx_parser p(code);
  153. ASSERT(p.m_programs.has_key("vert.glsl"),
  154. "no vertex shader in %s", name.C());
  155. ASSERT(p.m_programs.has_key("frag.glsl"),
  156. "no fragment shader in %s", name.C());
  157. String vert = p.m_programs["vert.glsl"];
  158. String frag = p.m_programs["frag.glsl"];
  159. uint32_t new_vert_crc = ShaderData::Hash(vert);
  160. uint32_t new_frag_crc = ShaderData::Hash(frag);
  161. for (int n = 0; n < ShaderData::nshaders; n++)
  162. {
  163. if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
  164. && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
  165. {
  166. return ShaderData::shaders[n];
  167. }
  168. }
  169. Shader *ret = new Shader(name, vert, frag);
  170. ShaderData::shaders[ShaderData::nshaders] = ret;
  171. ShaderData::nshaders++;
  172. return ret;
  173. }
  174. void Shader::Destroy(Shader *shader)
  175. {
  176. /* XXX: do nothing! the shader should remain in cache */
  177. UNUSED(shader);
  178. }
  179. Shader::Shader(String const &name,
  180. String const &vert, String const &frag)
  181. : data(new ShaderData())
  182. {
  183. data->m_name = name;
  184. char errbuf[4096];
  185. String shader_code;
  186. GLchar const *gl_code;
  187. GLint status;
  188. GLsizei len;
  189. /* Compile vertex shader */
  190. data->vert_crc = ShaderData::Hash(vert);
  191. shader_code = ShaderData::Patch(vert, ShaderType::Vertex);
  192. data->vert_id = glCreateShader(GL_VERTEX_SHADER);
  193. gl_code = shader_code.C();
  194. glShaderSource(data->vert_id, 1, &gl_code, nullptr);
  195. glCompileShader(data->vert_id);
  196. glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
  197. glGetShaderiv(data->vert_id, GL_COMPILE_STATUS, &status);
  198. if (status != GL_TRUE)
  199. {
  200. msg::error("failed to compile vertex shader %s: %s\n",
  201. name.C(), errbuf);
  202. msg::error("shader source:\n%s\n", shader_code.C());
  203. }
  204. else if (len > 16)
  205. {
  206. msg::debug("compile log for vertex shader %s: %s\n", name.C(), errbuf);
  207. msg::debug("shader source:\n%s\n", shader_code.C());
  208. }
  209. /* Compile fragment shader */
  210. data->frag_crc = ShaderData::Hash(frag);
  211. shader_code = ShaderData::Patch(frag, ShaderType::Fragment);
  212. data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
  213. gl_code = shader_code.C();
  214. glShaderSource(data->frag_id, 1, &gl_code, nullptr);
  215. glCompileShader(data->frag_id);
  216. glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf);
  217. glGetShaderiv(data->frag_id, GL_COMPILE_STATUS, &status);
  218. if (status != GL_TRUE)
  219. {
  220. msg::error("failed to compile fragment shader %s: %s\n",
  221. name.C(), errbuf);
  222. msg::error("shader source:\n%s\n", shader_code.C());
  223. }
  224. else if (len > 16)
  225. {
  226. msg::debug("compile log for fragment shader %s: %s\n",
  227. name.C(), errbuf);
  228. msg::debug("shader source:\n%s\n", shader_code.C());
  229. }
  230. /* Create program */
  231. data->prog_id = glCreateProgram();
  232. glAttachShader(data->prog_id, data->vert_id);
  233. glAttachShader(data->prog_id, data->frag_id);
  234. glLinkProgram(data->prog_id);
  235. glGetProgramInfoLog(data->prog_id, sizeof(errbuf), &len, errbuf);
  236. glGetProgramiv(data->prog_id, GL_LINK_STATUS, &status);
  237. if (status != GL_TRUE)
  238. {
  239. msg::error("failed to link program %s: %s\n", name.C(), errbuf);
  240. }
  241. else if (len > 16)
  242. {
  243. msg::debug("link log for program %s: %s\n", name.C(), errbuf);
  244. }
  245. GLint validated;
  246. glValidateProgram(data->prog_id);
  247. glGetProgramiv(data->prog_id, GL_VALIDATE_STATUS, &validated);
  248. if (validated != GL_TRUE)
  249. {
  250. msg::error("failed to validate program %s\n", name.C());
  251. }
  252. GLint num_attribs;
  253. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTES, &num_attribs);
  254. #if EMSCRIPTEN //WebGL doesn't support GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, so chose a default size value.
  255. GLint max_len = 256;
  256. #else
  257. GLint max_len;
  258. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  259. #endif
  260. char* name_buffer = new char[max_len];
  261. for (int i = 0; i < num_attribs; ++i)
  262. {
  263. int attrib_len;
  264. int attrib_size;
  265. int attrib_type;
  266. glGetActiveAttrib(data->prog_id, i, max_len, &attrib_len, (GLint*)&attrib_size, (GLenum*)&attrib_type, name_buffer);
  267. String name(name_buffer);
  268. int index = -1;
  269. VertexUsage usage = VertexUsage::MAX;
  270. for (int j = 0; j < (int)VertexUsage::MAX; ++j)
  271. {
  272. if (name.starts_with(attribute_names[j]) ||
  273. name.starts_with(String(attribute_names[j]).to_lower()))
  274. {
  275. usage = VertexUsage(j);
  276. char* idx_ptr = name.C() + strlen(attribute_names[j]);
  277. index = strtol(idx_ptr, nullptr, 10);
  278. break;
  279. }
  280. }
  281. if (usage == VertexUsage::MAX || index == -1)
  282. {
  283. msg::error("unable to parse attribute semantic from name: %s\n",
  284. name_buffer);
  285. }
  286. else
  287. {
  288. GLint location = glGetAttribLocation(data->prog_id, name_buffer);
  289. uint64_t flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  290. flags |= (uint64_t)(uint16_t)index;
  291. // TODO: this is here just in case. Remove this once everything has been correctly tested
  292. #if _DEBUG
  293. if (data->attrib_locations.has_key(flags))
  294. {
  295. msg::error("error while parsing attribute semantics in %s\n",
  296. name.C());
  297. }
  298. #endif
  299. data->attrib_locations[flags] = location;
  300. }
  301. }
  302. delete[] name_buffer;
  303. }
  304. int Shader::GetAttribCount() const
  305. {
  306. return data->attrib_locations.count();
  307. }
  308. ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const
  309. {
  310. ShaderAttrib ret;
  311. ret.m_flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  312. ret.m_flags |= (uint64_t)(uint16_t)index;
  313. GLint l = -1;
  314. if (!data->attrib_locations.try_get(ret.m_flags, l))
  315. {
  316. /* Only spit an error once, we don’t need to flood the console. */
  317. if (!data->attrib_errors.has_key(ret.m_flags))
  318. {
  319. msg::error("attribute %s not found in shader %s\n",
  320. usage.ToString().C(), data->m_name.C());
  321. data->attrib_errors[ret.m_flags] = true;
  322. }
  323. }
  324. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  325. return ret;
  326. }
  327. ShaderUniform Shader::GetUniformLocation(String const& uni) const
  328. {
  329. return GetUniformLocation(uni.C());
  330. }
  331. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  332. {
  333. ShaderUniform ret;
  334. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  335. ret.vert = 0;
  336. return ret;
  337. }
  338. /*
  339. * Uniform setters for scalars
  340. */
  341. void Shader::SetUniform(ShaderUniform const &uni, int i)
  342. {
  343. glUniform1i((GLint)uni.frag, i);
  344. }
  345. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  346. {
  347. glUniform2i((GLint)uni.frag, v.x, v.y);
  348. }
  349. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  350. {
  351. glUniform3i((GLint)uni.frag, v.x, v.y, v.z);
  352. }
  353. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  354. {
  355. glUniform4i((GLint)uni.frag, v.x, v.y, v.z, v.w);
  356. }
  357. void Shader::SetUniform(ShaderUniform const &uni, float f)
  358. {
  359. glUniform1f((GLint)uni.frag, f);
  360. }
  361. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  362. {
  363. glUniform2fv((GLint)uni.frag, 1, &v[0]);
  364. }
  365. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  366. {
  367. glUniform3fv((GLint)uni.frag, 1, &v[0]);
  368. }
  369. void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
  370. {
  371. glUniform4fv((GLint)uni.frag, 1, &v[0]);
  372. }
  373. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  374. {
  375. glUniformMatrix2fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  376. }
  377. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  378. {
  379. glUniformMatrix3fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  380. }
  381. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  382. {
  383. glUniformMatrix4fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  384. }
  385. void Shader::SetUniform(ShaderUniform const &uni, TextureUniform tex, int index)
  386. {
  387. glActiveTexture(GL_TEXTURE0 + index);
  388. //glEnable(GL_TEXTURE_2D);
  389. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  390. SetUniform(uni, index);
  391. }
  392. /*
  393. * Uniform setters for arrays
  394. */
  395. void Shader::SetUniform(ShaderUniform const &uni, array<float> const &v)
  396. {
  397. glUniform1fv((GLint)uni.frag, (GLsizei)v.count(), &v[0]);
  398. }
  399. void Shader::SetUniform(ShaderUniform const &uni, array<vec2> const &v)
  400. {
  401. glUniform2fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  402. }
  403. void Shader::SetUniform(ShaderUniform const &uni, array<vec3> const &v)
  404. {
  405. glUniform3fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  406. }
  407. void Shader::SetUniform(ShaderUniform const &uni, array<vec4> const &v)
  408. {
  409. glUniform4fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  410. }
  411. void Shader::Bind() const
  412. {
  413. glUseProgram(data->prog_id);
  414. }
  415. void Shader::Unbind() const
  416. {
  417. /* FIXME: untested */
  418. glUseProgram(0);
  419. }
  420. Shader::~Shader()
  421. {
  422. glDetachShader(data->prog_id, data->vert_id);
  423. glDetachShader(data->prog_id, data->frag_id);
  424. glDeleteShader(data->vert_id);
  425. glDeleteShader(data->frag_id);
  426. glDeleteProgram(data->prog_id);
  427. delete data;
  428. }
  429. /* Try to detect shader compiler features */
  430. int ShaderData::GetVersion()
  431. {
  432. static int version = 0;
  433. if (!version)
  434. {
  435. #if defined HAVE_GLES_2X
  436. /* GLES 2.x supports #version 100, that's all. */
  437. return 100;
  438. #else
  439. char buf[4096];
  440. GLsizei len;
  441. int id = glCreateShader(GL_VERTEX_SHADER);
  442. /* Can we compile 1.30 shaders? */
  443. char const *test130 =
  444. "#version 130\n"
  445. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  446. glShaderSource(id, 1, &test130, nullptr);
  447. glCompileShader(id);
  448. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  449. if (len <= 0)
  450. version = 130;
  451. /* If not, can we compile 1.20 shaders? */
  452. if (!version)
  453. {
  454. char const *test120 =
  455. "#version 120\n"
  456. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  457. glShaderSource(id, 1, &test120, nullptr);
  458. glCompileShader(id);
  459. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  460. if (len <= 0)
  461. version = 120;
  462. }
  463. /* Otherwise, assume we can compile 1.10 shaders. */
  464. if (!version)
  465. version = 110;
  466. glDeleteShader(id);
  467. #endif
  468. }
  469. return version;
  470. }
  471. /*
  472. * Simple shader source patching for old GLSL versions.
  473. */
  474. String ShaderData::Patch(String const &code, ShaderType type)
  475. {
  476. int ver_driver = GetVersion();
  477. String patched_code = code;
  478. if (ver_driver >= 130)
  479. return patched_code;
  480. int ver_shader = 110;
  481. char *parser = strstr(patched_code.C(), "#version");
  482. if (parser)
  483. ver_shader = atoi(parser + strlen("#version"));
  484. /* This is GL ES, we only know version 100. */
  485. if (ver_shader > 100 && ver_driver == 100)
  486. {
  487. /* FIXME: this isn't elegant but honestly, we don't care, this
  488. * whole file is going to die soon. */
  489. char *p = strstr(patched_code.C(), "#version");
  490. if (p)
  491. {
  492. p += 8;
  493. while (*p == ' ')
  494. p++;
  495. if (p[0] == '1' && p[1] && p[2])
  496. p[1] = p[2] = '0';
  497. }
  498. }
  499. if (ver_shader > 120 && ver_driver <= 120)
  500. {
  501. char const *end = patched_code.C() + patched_code.count() + 1;
  502. /* Find main() */
  503. parser = strstr(patched_code.C(), "main");
  504. if (!parser) return patched_code;
  505. parser = strstr(parser, "(");
  506. if (!parser) return patched_code;
  507. parser = strstr(parser, ")");
  508. if (!parser) return patched_code;
  509. parser = strstr(parser, "{");
  510. if (!parser) return patched_code;
  511. char *main = parser + 1;
  512. /* Perform main() replaces */
  513. char const * const main_replaces[] =
  514. {
  515. #if 0
  516. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  517. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  518. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  519. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  520. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  521. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  522. "in vec2 in_MultiTexCoord0;",
  523. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  524. "in vec2 in_MultiTexCoord1;",
  525. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  526. "in vec2 in_MultiTexCoord2;",
  527. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  528. "in vec2 in_MultiTexCoord3;",
  529. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  530. "in vec2 in_MultiTexCoord4;",
  531. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  532. "in vec2 in_MultiTexCoord5;",
  533. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  534. "in vec2 in_MultiTexCoord6;",
  535. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  536. "in vec2 in_MultiTexCoord7;",
  537. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  538. #endif
  539. nullptr
  540. };
  541. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  542. {
  543. char *match = strstr(patched_code.C(), rep[0]);
  544. if (match && match < main)
  545. {
  546. size_t l0 = strlen(rep[0]);
  547. size_t l1 = strlen(rep[1]);
  548. memmove(main + l1, main, end - main);
  549. memcpy(main, rep[1], l1);
  550. memset(match, ' ', l0);
  551. main += l1;
  552. end += l1;
  553. }
  554. }
  555. /* Perform small replaces */
  556. char const * const fast_replaces[] =
  557. {
  558. "#version 130", "#version 120",
  559. "out vec4 out_color;", " ",
  560. "out_color =", "gl_FragColor =",
  561. "in vec2", type == ShaderType::Vertex ? "attribute vec2" : "varying vec2",
  562. "in vec3", type == ShaderType::Vertex ? "attribute vec3" : "varying vec3",
  563. "in vec4", type == ShaderType::Vertex ? "attribute vec4" : "varying vec4",
  564. "in mat4", type == ShaderType::Vertex ? "attribute mat4" : "varying mat4",
  565. "out vec2", "varying vec2",
  566. "out vec3", "varying vec3",
  567. "out vec4", "varying vec4",
  568. "out mat4", "varying mat4",
  569. nullptr
  570. };
  571. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  572. {
  573. while (true)
  574. {
  575. int index = patched_code.index_of(rep[0]);
  576. if (index == INDEX_NONE)
  577. break;
  578. size_t l0 = strlen(rep[0]);
  579. size_t l1 = strlen(rep[1]);
  580. String left = patched_code.sub(0, index);
  581. String right = patched_code.sub(index + l0, patched_code.count() - (index + l0));
  582. patched_code = left + String(rep[1]) + right;
  583. }
  584. }
  585. }
  586. return patched_code;
  587. }
  588. static const String g_ret = "\n";
  589. static const String g_eol = ";";
  590. static const String g_bop = "{";
  591. static const String g_bcl = "}";
  592. static const String g_tab = " ";
  593. //----
  594. String Shader::GetVariablePrefix(const ShaderVariable variable)
  595. {
  596. switch (variable.ToScalar())
  597. {
  598. case ShaderVariable::Attribute: return String("in_");
  599. case ShaderVariable::Uniform: return String("u_");
  600. case ShaderVariable::Varying: return String("pass_");
  601. case ShaderVariable::InOut:
  602. default: return String();
  603. }
  604. }
  605. //----
  606. String Shader::GetVariableQualifier(const ShaderVariable variable)
  607. {
  608. switch (variable.ToScalar())
  609. {
  610. case ShaderVariable::Attribute: return String("attribute");
  611. case ShaderVariable::Uniform: return String("uniform");
  612. case ShaderVariable::Varying: return String("varying");
  613. case ShaderVariable::InOut:
  614. default: return String();
  615. }
  616. }
  617. //----
  618. String Shader::GetFunctionQualifier(const ShaderVariable variable, const ShaderProgram program)
  619. {
  620. switch (program.ToScalar())
  621. {
  622. case ShaderProgram::Geometry:
  623. {
  624. //TODO : L O L ----------------
  625. return String();
  626. }
  627. case ShaderProgram::Vertex:
  628. {
  629. switch (variable.ToScalar())
  630. {
  631. case ShaderVariable::Attribute: return String("in");
  632. case ShaderVariable::Uniform: return String("in");
  633. case ShaderVariable::Varying: return String("inout");
  634. case ShaderVariable::InOut: return String("inout");
  635. default: return String();
  636. }
  637. return String();
  638. }
  639. case ShaderProgram::Pixel:
  640. {
  641. switch (variable.ToScalar())
  642. {
  643. case ShaderVariable::Attribute: return String("in");
  644. case ShaderVariable::Uniform: return String("in");
  645. case ShaderVariable::Varying: return String("in");
  646. case ShaderVariable::InOut: return String("inout");
  647. default: return String();
  648. }
  649. return String();
  650. }
  651. default:
  652. {
  653. return String();
  654. }
  655. }
  656. }
  657. //----
  658. String Shader::GetProgramQualifier(const ShaderProgram program)
  659. {
  660. switch (program.ToScalar())
  661. {
  662. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  663. case ShaderProgram::Vertex: return String("[vert.glsl]");
  664. case ShaderProgram::Pixel: return String("[frag.glsl]");
  665. default: return String();
  666. }
  667. }
  668. //----
  669. String Shader::GetProgramOutVariable(const ShaderProgram program)
  670. {
  671. switch (program.ToScalar())
  672. {
  673. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  674. case ShaderProgram::Vertex: return String("gl_Position");
  675. case ShaderProgram::Pixel: return String("gl_FragColor");
  676. default: return String();
  677. }
  678. }
  679. //----
  680. String Shader::GetProgramOutVariableLocal(const ShaderProgram program)
  681. {
  682. switch (program.ToScalar())
  683. {
  684. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  685. case ShaderProgram::Vertex: return String("out_position");
  686. case ShaderProgram::Pixel: return String("out_frag_color");
  687. default: return String();
  688. }
  689. }
  690. //ShaderVar -------------------------------------------------------------------
  691. ShaderVar ShaderVar::GetShaderOut(ShaderProgram program)
  692. {
  693. switch (program.ToScalar())
  694. {
  695. case ShaderProgram::Geometry: //TODO : L O L ------------------------------
  696. default: ASSERT(false); return ShaderVar();
  697. case ShaderProgram::Vertex: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  698. case ShaderProgram::Pixel: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  699. }
  700. }
  701. //Shader Block implementation class -------------------------------------------
  702. void ShaderBlock::AddVar(ShaderVar const& var)
  703. {
  704. ShaderVariable qualifier = var.GetQualifier();
  705. String type = var.GetType();
  706. String name = Shader::GetVariablePrefix(qualifier) + var.m_name;
  707. ASSERT(!m_parameters[qualifier.ToScalar()].has_key(name));
  708. m_parameters[qualifier.ToScalar()][name] = type;
  709. }
  710. //----
  711. void ShaderBlock::AddCallParameters(map<String, String> const& variables, String& result)
  712. {
  713. array<String> keys = variables.keys();
  714. for (String key : keys)
  715. {
  716. if (result.count() > 0)
  717. result += ", ";
  718. result += key;
  719. }
  720. }
  721. //----
  722. void ShaderBlock::AddDefinitionParameters(const ShaderVariable type, const ShaderProgram program, map<String, String>& variables, String& result)
  723. {
  724. array<String> keys = variables.keys();
  725. for (String key : keys)
  726. {
  727. if (result.count() > 0)
  728. result += ", ";
  729. result += Shader::GetFunctionQualifier(type, program) + " ";
  730. result += variables[key];
  731. result += String(" ");
  732. result += key;
  733. }
  734. }
  735. //----
  736. void ShaderBlock::Build(const ShaderProgram program, String& call, String& function)
  737. {
  738. ASSERT(m_name.count());
  739. ASSERT(m_parameters[ShaderVariable::InOut].count());
  740. //Build call in main
  741. String call_name = String("Call_") + m_name;
  742. call = call_name + "(";
  743. String call_parameters;
  744. for (int i = 0; i < ShaderVariable::MAX; i++)
  745. AddCallParameters(/*(ShaderVariable)i, */m_parameters[i], call_parameters);
  746. call += call_parameters + ");";
  747. //Build function declaration
  748. function = String("void ") + call_name + "(";
  749. String def_parameters;
  750. for (int i = 0; i < ShaderVariable::MAX; i++)
  751. AddDefinitionParameters((ShaderVariable)i, program, m_parameters[i], def_parameters);
  752. function += def_parameters + ")" + g_ret +
  753. "{" + g_ret +
  754. m_code_main + ((m_code_main.ends_with(g_ret)) ? (String()) : (g_ret)) +
  755. "}";
  756. }
  757. //Shader Builder implementation class -----------------------------------------
  758. ShaderBuilder::ShaderBuilder(String const& name, String const& version)
  759. : m_name(name), m_version(version)
  760. {
  761. ASSERT(name.count());
  762. ASSERT(version.count());
  763. }
  764. //----
  765. ShaderBuilder::~ShaderBuilder()
  766. {
  767. }
  768. //----
  769. String const& ShaderBuilder::GetName()
  770. {
  771. return m_name;
  772. }
  773. //----
  774. ShaderBuilder& ShaderBuilder::operator<<(const ShaderProgram program)
  775. {
  776. m_current_program = program;
  777. return *this;
  778. }
  779. //----
  780. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock* block)
  781. {
  782. ASSERT(m_current_program != ShaderProgram::MAX);
  783. m_blocks[m_current_program.ToScalar()].push_unique(block);
  784. return *this;
  785. }
  786. //----
  787. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock const& block)
  788. {
  789. ASSERT(m_current_program != ShaderProgram::MAX);
  790. m_blocks[m_current_program.ToScalar()].push_unique(new ShaderBlock(block));
  791. return *this;
  792. }
  793. //----
  794. String ShaderBuilder::AddSlotOutVariableLocal(const ShaderProgram program)
  795. {
  796. ShaderVariable var = ShaderVariable::InOut;
  797. String result = Shader::GetProgramOutVariableLocal(program);
  798. switch (program.ToScalar())
  799. {
  800. case ShaderProgram::Geometry:
  801. {
  802. //TODO : L O L ----------------
  803. break;
  804. }
  805. case ShaderProgram::Vertex:
  806. {
  807. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  808. break;
  809. }
  810. case ShaderProgram::Pixel:
  811. {
  812. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  813. break;
  814. }
  815. default:
  816. {
  817. break;
  818. }
  819. }
  820. return result;
  821. }
  822. //----
  823. void ShaderBuilder::MergeParameters(map<String, String>& variables, map<String, String>& merged)
  824. {
  825. array<String> keys = variables.keys();
  826. for (String key : keys)
  827. {
  828. bool has_key = merged.has_key(key);
  829. //Key exists, check the type to make sure it's the same
  830. ASSERT(!has_key || (has_key && merged[key] == variables[key]),
  831. "has_key=%d, key=%s merged[key]=%s, variables[key]=%s\n",
  832. (int)has_key, key.C(), merged[key].C(), variables[key].C());
  833. //does not exist, had it
  834. if (!has_key)
  835. merged[key] = variables[key];
  836. }
  837. }
  838. //----
  839. void ShaderBuilder::Build(String& code)
  840. {
  841. //Cleanup first
  842. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  843. for (int var = 0; var < ShaderVariable::MAX; var++)
  844. m_parameters[prog][var].empty();
  845. //Start building
  846. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  847. {
  848. //Add default local out in merged variables
  849. String out_local_var = AddSlotOutVariableLocal((ShaderProgram)prog);
  850. if (!out_local_var.count())
  851. continue;
  852. //Merge all variables
  853. for (int var = 0; var < ShaderVariable::MAX; var++)
  854. for (int block = 0; block < m_blocks[prog].count(); block++)
  855. MergeParameters(m_blocks[prog][block]->m_parameters[var], m_parameters[prog][var]);
  856. //Actually write code
  857. code += Shader::GetProgramQualifier((ShaderProgram)prog) + g_ret;
  858. //Add actual code
  859. code += String("#version ") + m_version + g_ret + g_ret;
  860. //Added shader variables
  861. for (int var = 0; var < ShaderVariable::InOut; var++)
  862. {
  863. array<String> keys = m_parameters[prog][var].keys();
  864. if (keys.count())
  865. {
  866. code += String("//- ") + Shader::GetVariableQualifier((ShaderVariable)var) + " ----" + g_ret;
  867. for (String key : keys)
  868. {
  869. code += Shader::GetVariableQualifier((ShaderVariable)var) + " ";
  870. code += m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  871. }
  872. if (var + 1 < ShaderVariable::InOut)
  873. code += g_ret;
  874. }
  875. }
  876. code += g_ret;
  877. //Build Blocks code and add it
  878. array<String> calls;
  879. for (int block = 0; block < m_blocks[prog].count(); block++)
  880. {
  881. String call;
  882. String function;
  883. m_blocks[prog][block]->Build(ShaderProgram(prog), call, function);
  884. calls << call;
  885. if (m_blocks[prog][block]->m_code_custom.count())
  886. {
  887. code += String("//- ") + m_blocks[prog][block]->GetName() + " custom code ----" + g_ret;
  888. code += m_blocks[prog][block]->m_code_custom + g_ret + g_ret;
  889. }
  890. code += String("//- ") + m_blocks[prog][block]->GetName() + " main code ----" + g_ret;
  891. code += function + g_ret + g_ret;
  892. }
  893. //Added main definition
  894. code += String("//- Main ----") + g_ret +
  895. String("void main(void)") + g_ret + "{" + g_ret;
  896. //Add local variables
  897. int var = ShaderVariable::InOut;
  898. array<String> keys = m_parameters[prog][var].keys();
  899. for (String key : keys)
  900. {
  901. if (keys.count())
  902. {
  903. code += g_tab + m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  904. }
  905. }
  906. code += g_ret;
  907. //Add calls
  908. code += g_tab + String("//- Calls ----") + g_ret;
  909. for (String call : calls)
  910. code += g_tab + call + g_ret;
  911. code += g_ret;
  912. code += g_tab + Shader::GetProgramOutVariable((ShaderProgram)prog) + " = " + out_local_var + ";" + g_ret +
  913. String("}") + g_ret + g_ret;
  914. }
  915. }
  916. } /* namespace lol */