Shader.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /**
  2. * Copyright (c) 2006-2020 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include "common/config.h"
  22. #include "Shader.h"
  23. #include "ShaderStage.h"
  24. #include "Graphics.h"
  25. // C++
  26. #include <algorithm>
  27. #include <limits>
  28. #include <sstream>
  29. namespace love
  30. {
  31. namespace graphics
  32. {
  33. namespace opengl
  34. {
  35. Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
  36. : love::graphics::Shader(vertex, pixel)
  37. , program(0)
  38. , builtinUniforms()
  39. , builtinUniformInfo()
  40. , builtinAttributes()
  41. , lastPointSize(0.0f)
  42. {
  43. // load shader source and create program object
  44. loadVolatile();
  45. }
  46. Shader::~Shader()
  47. {
  48. unloadVolatile();
  49. for (const auto &p : uniforms)
  50. {
  51. // Allocated with malloc().
  52. if (p.second.data != nullptr)
  53. free(p.second.data);
  54. if (p.second.baseType == UNIFORM_SAMPLER)
  55. {
  56. for (int i = 0; i < p.second.count; i++)
  57. {
  58. if (p.second.textures[i] != nullptr)
  59. p.second.textures[i]->release();
  60. }
  61. delete[] p.second.textures;
  62. }
  63. }
  64. }
  65. void Shader::mapActiveUniforms()
  66. {
  67. // Built-in uniform locations default to -1 (nonexistent.)
  68. for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
  69. {
  70. builtinUniforms[i] = -1;
  71. builtinUniformInfo[i] = nullptr;
  72. }
  73. GLint activeprogram = 0;
  74. glGetIntegerv(GL_CURRENT_PROGRAM, &activeprogram);
  75. gl.useProgram(program);
  76. GLint numuniforms;
  77. glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numuniforms);
  78. GLchar cname[256];
  79. const GLint bufsize = (GLint) (sizeof(cname) / sizeof(GLchar));
  80. std::map<std::string, UniformInfo> olduniforms = uniforms;
  81. uniforms.clear();
  82. for (int uindex = 0; uindex < numuniforms; uindex++)
  83. {
  84. GLsizei namelen = 0;
  85. GLenum gltype = 0;
  86. UniformInfo u = {};
  87. glGetActiveUniform(program, (GLuint) uindex, bufsize, &namelen, &u.count, &gltype, cname);
  88. u.name = std::string(cname, (size_t) namelen);
  89. u.location = glGetUniformLocation(program, u.name.c_str());
  90. u.baseType = getUniformBaseType(gltype);
  91. u.textureType = getUniformTextureType(gltype);
  92. u.isDepthSampler = isDepthTextureType(gltype);
  93. if (u.baseType == UNIFORM_MATRIX)
  94. u.matrix = getMatrixSize(gltype);
  95. else
  96. u.components = getUniformTypeComponents(gltype);
  97. // glGetActiveUniform appends "[0]" to the end of array uniform names...
  98. if (u.name.length() > 3)
  99. {
  100. size_t findpos = u.name.find("[0]");
  101. if (findpos != std::string::npos && findpos == u.name.length() - 3)
  102. u.name.erase(u.name.length() - 3);
  103. }
  104. // If this is a built-in (LOVE-created) uniform, store the location.
  105. BuiltinUniform builtin = BUILTIN_MAX_ENUM;
  106. if (getConstant(u.name.c_str(), builtin))
  107. builtinUniforms[int(builtin)] = u.location;
  108. if (u.location == -1)
  109. continue;
  110. if (u.baseType == UNIFORM_SAMPLER && builtin != BUILTIN_TEXTURE_MAIN)
  111. {
  112. TextureUnit unit;
  113. unit.type = u.textureType;
  114. unit.active = true;
  115. unit.texture = gl.getDefaultTexture(u.textureType);
  116. for (int i = 0; i < u.count; i++)
  117. textureUnits.push_back(unit);
  118. }
  119. // Make sure previously set uniform data is preserved, and shader-
  120. // initialized values are retrieved.
  121. auto oldu = olduniforms.find(u.name);
  122. if (oldu != olduniforms.end())
  123. {
  124. u.data = oldu->second.data;
  125. u.dataSize = oldu->second.dataSize;
  126. u.textures = oldu->second.textures;
  127. updateUniform(&u, u.count, true);
  128. }
  129. else
  130. {
  131. u.dataSize = 0;
  132. switch (u.baseType)
  133. {
  134. case UNIFORM_FLOAT:
  135. u.dataSize = sizeof(float) * u.components * u.count;
  136. u.data = malloc(u.dataSize);
  137. break;
  138. case UNIFORM_INT:
  139. case UNIFORM_BOOL:
  140. case UNIFORM_SAMPLER:
  141. u.dataSize = sizeof(int) * u.components * u.count;
  142. u.data = malloc(u.dataSize);
  143. break;
  144. case UNIFORM_UINT:
  145. u.dataSize = sizeof(unsigned int) * u.components * u.count;
  146. u.data = malloc(u.dataSize);
  147. break;
  148. case UNIFORM_MATRIX:
  149. u.dataSize = sizeof(float) * (u.matrix.rows * u.matrix.columns) * u.count;
  150. u.data = malloc(u.dataSize);
  151. break;
  152. default:
  153. break;
  154. }
  155. if (u.dataSize > 0)
  156. {
  157. memset(u.data, 0, u.dataSize);
  158. if (u.baseType == UNIFORM_SAMPLER)
  159. {
  160. int startunit = (int) textureUnits.size() - u.count;
  161. if (builtin == BUILTIN_TEXTURE_MAIN)
  162. startunit = 0;
  163. for (int i = 0; i < u.count; i++)
  164. u.ints[i] = startunit + i;
  165. glUniform1iv(u.location, u.count, u.ints);
  166. u.textures = new love::graphics::Texture*[u.count];
  167. memset(u.textures, 0, sizeof(Texture *) * u.count);
  168. }
  169. }
  170. size_t offset = 0;
  171. // Store any shader-initialized values in our own memory.
  172. for (int i = 0; i < u.count; i++)
  173. {
  174. GLint location = u.location;
  175. if (u.count > 1)
  176. {
  177. std::ostringstream ss;
  178. ss << i;
  179. std::string indexname = u.name + "[" + ss.str() + "]";
  180. location = glGetUniformLocation(program, indexname.c_str());
  181. }
  182. if (location == -1)
  183. continue;
  184. switch (u.baseType)
  185. {
  186. case UNIFORM_FLOAT:
  187. glGetUniformfv(program, location, &u.floats[offset]);
  188. offset += u.components;
  189. break;
  190. case UNIFORM_INT:
  191. case UNIFORM_BOOL:
  192. glGetUniformiv(program, location, &u.ints[offset]);
  193. offset += u.components;
  194. break;
  195. case UNIFORM_UINT:
  196. glGetUniformuiv(program, location, &u.uints[offset]);
  197. offset += u.components;
  198. break;
  199. case UNIFORM_MATRIX:
  200. glGetUniformfv(program, location, &u.floats[offset]);
  201. offset += u.matrix.rows * u.matrix.columns;
  202. break;
  203. default:
  204. break;
  205. }
  206. }
  207. }
  208. uniforms[u.name] = u;
  209. if (builtin != BUILTIN_MAX_ENUM)
  210. builtinUniformInfo[(int)builtin] = &uniforms[u.name];
  211. if (u.baseType == UNIFORM_SAMPLER)
  212. {
  213. // Make sure all stored textures have their Volatiles loaded before
  214. // the sendTextures call, since it calls getHandle().
  215. for (int i = 0; i < u.count; i++)
  216. {
  217. if (u.textures[i] == nullptr)
  218. continue;
  219. Volatile *v = dynamic_cast<Volatile *>(u.textures[i]);
  220. if (v != nullptr)
  221. v->loadVolatile();
  222. }
  223. sendTextures(&u, u.textures, u.count, true);
  224. }
  225. }
  226. // Make sure uniforms that existed before but don't exist anymore are
  227. // cleaned up. This theoretically shouldn't happen, but...
  228. for (const auto &p : olduniforms)
  229. {
  230. if (uniforms.find(p.first) == uniforms.end())
  231. {
  232. free(p.second.data);
  233. if (p.second.baseType != UNIFORM_SAMPLER)
  234. continue;
  235. for (int i = 0; i < p.second.count; i++)
  236. {
  237. if (p.second.textures[i] != nullptr)
  238. p.second.textures[i]->release();
  239. }
  240. delete[] p.second.textures;
  241. }
  242. }
  243. gl.useProgram(activeprogram);
  244. }
  245. bool Shader::loadVolatile()
  246. {
  247. OpenGL::TempDebugGroup debuggroup("Shader load");
  248. lastPointSize = -1.0f;
  249. // zero out active texture list
  250. textureUnits.clear();
  251. textureUnits.push_back(TextureUnit());
  252. for (const auto &stage : stages)
  253. {
  254. if (stage.get() != nullptr)
  255. ((ShaderStage*)stage.get())->loadVolatile();
  256. }
  257. program = glCreateProgram();
  258. if (program == 0)
  259. throw love::Exception("Cannot create shader program object.");
  260. for (const auto &stage : stages)
  261. {
  262. if (stage.get() != nullptr)
  263. glAttachShader(program, (GLuint) stage->getHandle());
  264. }
  265. // Bind generic vertex attribute indices to names in the shader.
  266. for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
  267. {
  268. const char *name = nullptr;
  269. if (vertex::getConstant((BuiltinVertexAttribute) i, name))
  270. glBindAttribLocation(program, i, (const GLchar *) name);
  271. }
  272. glLinkProgram(program);
  273. GLint status;
  274. glGetProgramiv(program, GL_LINK_STATUS, &status);
  275. if (status == GL_FALSE)
  276. {
  277. std::string warnings = getProgramWarnings();
  278. glDeleteProgram(program);
  279. program = 0;
  280. throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
  281. }
  282. // Get all active uniform variables in this shader from OpenGL.
  283. mapActiveUniforms();
  284. for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
  285. {
  286. const char *name = nullptr;
  287. if (vertex::getConstant(BuiltinVertexAttribute(i), name))
  288. builtinAttributes[i] = glGetAttribLocation(program, name);
  289. else
  290. builtinAttributes[i] = -1;
  291. }
  292. if (current == this)
  293. {
  294. // make sure glUseProgram gets called.
  295. current = nullptr;
  296. attach();
  297. }
  298. return true;
  299. }
  300. void Shader::unloadVolatile()
  301. {
  302. if (program != 0)
  303. {
  304. if (current == this)
  305. gl.useProgram(0);
  306. glDeleteProgram(program);
  307. program = 0;
  308. }
  309. // active texture list is probably invalid, clear it
  310. textureUnits.clear();
  311. textureUnits.push_back(TextureUnit());
  312. attributes.clear();
  313. // And the locations of any built-in uniform variables.
  314. for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
  315. builtinUniforms[i] = -1;
  316. }
  317. std::string Shader::getProgramWarnings() const
  318. {
  319. GLint strsize, nullpos;
  320. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strsize);
  321. if (strsize == 0)
  322. return "";
  323. char *tempstr = new char[strsize];
  324. // be extra sure that the error string will be 0-terminated
  325. memset(tempstr, '\0', strsize);
  326. glGetProgramInfoLog(program, strsize, &nullpos, tempstr);
  327. tempstr[nullpos] = '\0';
  328. std::string warnings(tempstr);
  329. delete[] tempstr;
  330. return warnings;
  331. }
  332. std::string Shader::getWarnings() const
  333. {
  334. std::string warnings;
  335. const char *stagestr;
  336. for (const auto &stage : stages)
  337. {
  338. if (stage.get() == nullptr)
  339. continue;
  340. const std::string &stagewarnings = stage->getWarnings();
  341. if (ShaderStage::getConstant(stage->getStageType(), stagestr))
  342. warnings += std::string(stagestr) + std::string(" shader:\n") + stagewarnings;
  343. }
  344. warnings += getProgramWarnings();
  345. return warnings;
  346. }
  347. void Shader::attach()
  348. {
  349. if (current != this)
  350. {
  351. Graphics::flushStreamDrawsGlobal();
  352. gl.useProgram(program);
  353. current = this;
  354. // retain/release happens in Graphics::setShader.
  355. // Make sure all textures are bound to their respective texture units.
  356. for (int i = 0; i < (int) textureUnits.size(); ++i)
  357. {
  358. const TextureUnit &unit = textureUnits[i];
  359. if (unit.active)
  360. gl.bindTextureToUnit(unit.type, unit.texture, i, false);
  361. }
  362. // send any pending uniforms to the shader program.
  363. for (const auto &p : pendingUniformUpdates)
  364. updateUniform(p.first, p.second, true);
  365. pendingUniformUpdates.clear();
  366. }
  367. }
  368. const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const
  369. {
  370. const auto it = uniforms.find(name);
  371. if (it == uniforms.end())
  372. return nullptr;
  373. return &(it->second);
  374. }
  375. const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const
  376. {
  377. return builtinUniformInfo[(int)builtin];
  378. }
  379. void Shader::updateUniform(const UniformInfo *info, int count)
  380. {
  381. updateUniform(info, count, false);
  382. }
  383. void Shader::updateUniform(const UniformInfo *info, int count, bool internalupdate)
  384. {
  385. if (current != this && !internalupdate)
  386. {
  387. pendingUniformUpdates.push_back(std::make_pair(info, count));
  388. return;
  389. }
  390. if (!internalupdate)
  391. flushStreamDraws();
  392. int location = info->location;
  393. UniformType type = info->baseType;
  394. if (type == UNIFORM_FLOAT)
  395. {
  396. switch (info->components)
  397. {
  398. case 1:
  399. glUniform1fv(location, count, info->floats);
  400. break;
  401. case 2:
  402. glUniform2fv(location, count, info->floats);
  403. break;
  404. case 3:
  405. glUniform3fv(location, count, info->floats);
  406. break;
  407. case 4:
  408. glUniform4fv(location, count, info->floats);
  409. break;
  410. }
  411. }
  412. else if (type == UNIFORM_INT || type == UNIFORM_BOOL || type == UNIFORM_SAMPLER)
  413. {
  414. switch (info->components)
  415. {
  416. case 1:
  417. glUniform1iv(location, count, info->ints);
  418. break;
  419. case 2:
  420. glUniform2iv(location, count, info->ints);
  421. break;
  422. case 3:
  423. glUniform3iv(location, count, info->ints);
  424. break;
  425. case 4:
  426. glUniform4iv(location, count, info->ints);
  427. break;
  428. }
  429. }
  430. else if (type == UNIFORM_UINT)
  431. {
  432. switch (info->components)
  433. {
  434. case 1:
  435. glUniform1uiv(location, count, info->uints);
  436. break;
  437. case 2:
  438. glUniform2uiv(location, count, info->uints);
  439. break;
  440. case 3:
  441. glUniform3uiv(location, count, info->uints);
  442. break;
  443. case 4:
  444. glUniform4uiv(location, count, info->uints);
  445. break;
  446. }
  447. }
  448. else if (type == UNIFORM_MATRIX)
  449. {
  450. int columns = info->matrix.columns;
  451. int rows = info->matrix.rows;
  452. if (columns == 2 && rows == 2)
  453. glUniformMatrix2fv(location, count, GL_FALSE, info->floats);
  454. else if (columns == 3 && rows == 3)
  455. glUniformMatrix3fv(location, count, GL_FALSE, info->floats);
  456. else if (columns == 4 && rows == 4)
  457. glUniformMatrix4fv(location, count, GL_FALSE, info->floats);
  458. else if (columns == 2 && rows == 3)
  459. glUniformMatrix2x3fv(location, count, GL_FALSE, info->floats);
  460. else if (columns == 2 && rows == 4)
  461. glUniformMatrix2x4fv(location, count, GL_FALSE, info->floats);
  462. else if (columns == 3 && rows == 2)
  463. glUniformMatrix3x2fv(location, count, GL_FALSE, info->floats);
  464. else if (columns == 3 && rows == 4)
  465. glUniformMatrix3x4fv(location, count, GL_FALSE, info->floats);
  466. else if (columns == 4 && rows == 2)
  467. glUniformMatrix4x2fv(location, count, GL_FALSE, info->floats);
  468. else if (columns == 4 && rows == 3)
  469. glUniformMatrix4x3fv(location, count, GL_FALSE, info->floats);
  470. }
  471. }
  472. void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count)
  473. {
  474. Shader::sendTextures(info, textures, count, false);
  475. }
  476. void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count, bool internalUpdate)
  477. {
  478. if (info->baseType != UNIFORM_SAMPLER)
  479. return;
  480. bool shaderactive = current == this;
  481. if (!internalUpdate && shaderactive)
  482. flushStreamDraws();
  483. count = std::min(count, info->count);
  484. // Bind the textures to the texture units.
  485. for (int i = 0; i < count; i++)
  486. {
  487. love::graphics::Texture *tex = textures[i];
  488. if (tex != nullptr)
  489. {
  490. const SamplerState &sampler = tex->getSamplerState();
  491. if (!tex->isReadable())
  492. {
  493. if (internalUpdate)
  494. continue;
  495. else
  496. throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
  497. }
  498. else if (info->isDepthSampler != sampler.depthSampleMode.hasValue)
  499. {
  500. if (internalUpdate)
  501. continue;
  502. else if (info->isDepthSampler)
  503. throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set.");
  504. else
  505. throw love::Exception("Depth textures which have depth comparison set can only be used with depth/shadow samplers in shaders.");
  506. }
  507. else if (tex->getTextureType() != info->textureType)
  508. {
  509. if (internalUpdate)
  510. continue;
  511. else
  512. {
  513. const char *textypestr = "unknown";
  514. const char *shadertextypestr = "unknown";
  515. Texture::getConstant(tex->getTextureType(), textypestr);
  516. Texture::getConstant(info->textureType, shadertextypestr);
  517. throw love::Exception("Texture's type (%s) must match the type of %s (%s).", textypestr, info->name.c_str(), shadertextypestr);
  518. }
  519. }
  520. tex->retain();
  521. }
  522. if (info->textures[i] != nullptr)
  523. info->textures[i]->release();
  524. info->textures[i] = tex;
  525. GLuint gltex = 0;
  526. if (textures[i] != nullptr)
  527. gltex = (GLuint) tex->getHandle();
  528. else
  529. gltex = gl.getDefaultTexture(info->textureType);
  530. int texunit = info->ints[i];
  531. if (shaderactive)
  532. gl.bindTextureToUnit(info->textureType, gltex, texunit, false);
  533. // Store texture id so it can be re-bound to the texture unit later.
  534. textureUnits[texunit].texture = gltex;
  535. }
  536. }
  537. void Shader::flushStreamDraws() const
  538. {
  539. if (current == this)
  540. Graphics::flushStreamDrawsGlobal();
  541. }
  542. bool Shader::hasUniform(const std::string &name) const
  543. {
  544. return uniforms.find(name) != uniforms.end();
  545. }
  546. ptrdiff_t Shader::getHandle() const
  547. {
  548. return program;
  549. }
  550. int Shader::getVertexAttributeIndex(const std::string &name)
  551. {
  552. auto it = attributes.find(name);
  553. if (it != attributes.end())
  554. return it->second;
  555. GLint location = glGetAttribLocation(program, name.c_str());
  556. attributes[name] = location;
  557. return location;
  558. }
  559. void Shader::setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture)
  560. {
  561. const BuiltinUniform builtins[3] = {
  562. BUILTIN_TEXTURE_VIDEO_Y,
  563. BUILTIN_TEXTURE_VIDEO_CB,
  564. BUILTIN_TEXTURE_VIDEO_CR,
  565. };
  566. love::graphics::Texture *textures[3] = {ytexture, cbtexture, crtexture};
  567. for (int i = 0; i < 3; i++)
  568. {
  569. const UniformInfo *info = builtinUniformInfo[builtins[i]];
  570. if (info != nullptr)
  571. sendTextures(info, &textures[i], 1, true);
  572. }
  573. }
  574. void Shader::updatePointSize(float size)
  575. {
  576. if (size == lastPointSize || current != this)
  577. return;
  578. GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
  579. if (location >= 0)
  580. glUniform1f(location, size);
  581. lastPointSize = size;
  582. }
  583. void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int viewportH)
  584. {
  585. if (current != this)
  586. return;
  587. if (GLAD_ES_VERSION_2_0)
  588. updatePointSize(gl.getPointSize());
  589. BuiltinUniformData data;
  590. data.transformMatrix = gfx->getTransform();
  591. data.projectionMatrix = gfx->getProjection();
  592. // The normal matrix is the transpose of the inverse of the rotation portion
  593. // (top-left 3x3) of the transform matrix.
  594. {
  595. Matrix3 normalmatrix = Matrix3(data.transformMatrix).transposedInverse();
  596. const float *e = normalmatrix.getElements();
  597. for (int i = 0; i < 3; i++)
  598. {
  599. data.normalMatrix[i].x = e[i * 3 + 0];
  600. data.normalMatrix[i].y = e[i * 3 + 1];
  601. data.normalMatrix[i].z = e[i * 3 + 2];
  602. data.normalMatrix[i].w = 0.0f;
  603. }
  604. }
  605. data.screenSizeParams.x = viewportW;
  606. data.screenSizeParams.y = viewportH;
  607. // The shader does pixcoord.y = gl_FragCoord.y * params.z + params.w.
  608. // This lets us flip pixcoord.y when needed, to be consistent (drawing
  609. // with no RT active makes the pixel coordinates y-flipped.)
  610. if (gfx->isRenderTargetActive())
  611. {
  612. // No flipping: pixcoord.y = gl_FragCoord.y * 1.0 + 0.0.
  613. data.screenSizeParams.z = 1.0f;
  614. data.screenSizeParams.w = 0.0f;
  615. }
  616. else
  617. {
  618. // gl_FragCoord.y is flipped when drawing to the screen, so we
  619. // un-flip: pixcoord.y = gl_FragCoord.y * -1.0 + height.
  620. data.screenSizeParams.z = -1.0f;
  621. data.screenSizeParams.w = viewportH;
  622. }
  623. data.constantColor = gfx->getColor();
  624. gammaCorrectColor(data.constantColor);
  625. GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
  626. if (location >= 0)
  627. glUniform4fv(location, 13, (const GLfloat *) &data);
  628. }
  629. int Shader::getUniformTypeComponents(GLenum type) const
  630. {
  631. if (getUniformBaseType(type) == UNIFORM_SAMPLER)
  632. return 1;
  633. switch (type)
  634. {
  635. case GL_INT:
  636. case GL_UNSIGNED_INT:
  637. case GL_FLOAT:
  638. case GL_BOOL:
  639. return 1;
  640. case GL_INT_VEC2:
  641. case GL_UNSIGNED_INT_VEC2:
  642. case GL_FLOAT_VEC2:
  643. case GL_FLOAT_MAT2:
  644. case GL_BOOL_VEC2:
  645. return 2;
  646. case GL_INT_VEC3:
  647. case GL_UNSIGNED_INT_VEC3:
  648. case GL_FLOAT_VEC3:
  649. case GL_FLOAT_MAT3:
  650. case GL_BOOL_VEC3:
  651. return 3;
  652. case GL_INT_VEC4:
  653. case GL_UNSIGNED_INT_VEC4:
  654. case GL_FLOAT_VEC4:
  655. case GL_FLOAT_MAT4:
  656. case GL_BOOL_VEC4:
  657. return 4;
  658. default:
  659. return 1;
  660. }
  661. }
  662. Shader::MatrixSize Shader::getMatrixSize(GLenum type) const
  663. {
  664. MatrixSize m;
  665. switch (type)
  666. {
  667. case GL_FLOAT_MAT2:
  668. m.columns = m.rows = 2;
  669. break;
  670. case GL_FLOAT_MAT3:
  671. m.columns = m.rows = 3;
  672. break;
  673. case GL_FLOAT_MAT4:
  674. m.columns = m.rows = 4;
  675. break;
  676. case GL_FLOAT_MAT2x3:
  677. m.columns = 2;
  678. m.rows = 3;
  679. break;
  680. case GL_FLOAT_MAT2x4:
  681. m.columns = 2;
  682. m.rows = 4;
  683. break;
  684. case GL_FLOAT_MAT3x2:
  685. m.columns = 3;
  686. m.rows = 2;
  687. break;
  688. case GL_FLOAT_MAT3x4:
  689. m.columns = 3;
  690. m.rows = 4;
  691. break;
  692. case GL_FLOAT_MAT4x2:
  693. m.columns = 4;
  694. m.rows = 2;
  695. break;
  696. case GL_FLOAT_MAT4x3:
  697. m.columns = 4;
  698. m.rows = 3;
  699. break;
  700. }
  701. return m;
  702. }
  703. Shader::UniformType Shader::getUniformBaseType(GLenum type) const
  704. {
  705. switch (type)
  706. {
  707. case GL_INT:
  708. case GL_INT_VEC2:
  709. case GL_INT_VEC3:
  710. case GL_INT_VEC4:
  711. return UNIFORM_INT;
  712. case GL_UNSIGNED_INT:
  713. case GL_UNSIGNED_INT_VEC2:
  714. case GL_UNSIGNED_INT_VEC3:
  715. case GL_UNSIGNED_INT_VEC4:
  716. return UNIFORM_UINT;
  717. case GL_FLOAT:
  718. case GL_FLOAT_VEC2:
  719. case GL_FLOAT_VEC3:
  720. case GL_FLOAT_VEC4:
  721. return UNIFORM_FLOAT;
  722. case GL_FLOAT_MAT2:
  723. case GL_FLOAT_MAT3:
  724. case GL_FLOAT_MAT4:
  725. case GL_FLOAT_MAT2x3:
  726. case GL_FLOAT_MAT2x4:
  727. case GL_FLOAT_MAT3x2:
  728. case GL_FLOAT_MAT3x4:
  729. case GL_FLOAT_MAT4x2:
  730. case GL_FLOAT_MAT4x3:
  731. return UNIFORM_MATRIX;
  732. case GL_BOOL:
  733. case GL_BOOL_VEC2:
  734. case GL_BOOL_VEC3:
  735. case GL_BOOL_VEC4:
  736. return UNIFORM_BOOL;
  737. case GL_SAMPLER_1D:
  738. case GL_SAMPLER_1D_SHADOW:
  739. case GL_SAMPLER_1D_ARRAY:
  740. case GL_SAMPLER_1D_ARRAY_SHADOW:
  741. case GL_SAMPLER_2D:
  742. case GL_SAMPLER_2D_MULTISAMPLE:
  743. case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
  744. case GL_SAMPLER_2D_RECT:
  745. case GL_SAMPLER_2D_RECT_SHADOW:
  746. case GL_SAMPLER_2D_SHADOW:
  747. case GL_SAMPLER_2D_ARRAY:
  748. case GL_SAMPLER_2D_ARRAY_SHADOW:
  749. case GL_SAMPLER_3D:
  750. case GL_SAMPLER_CUBE:
  751. case GL_SAMPLER_CUBE_SHADOW:
  752. case GL_SAMPLER_CUBE_MAP_ARRAY:
  753. case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
  754. return UNIFORM_SAMPLER;
  755. default:
  756. return UNIFORM_UNKNOWN;
  757. }
  758. }
  759. TextureType Shader::getUniformTextureType(GLenum type) const
  760. {
  761. switch (type)
  762. {
  763. case GL_SAMPLER_1D:
  764. case GL_SAMPLER_1D_SHADOW:
  765. case GL_SAMPLER_1D_ARRAY:
  766. case GL_SAMPLER_1D_ARRAY_SHADOW:
  767. // 1D-typed textures are not supported.
  768. return TEXTURE_MAX_ENUM;
  769. case GL_SAMPLER_2D:
  770. case GL_SAMPLER_2D_SHADOW:
  771. return TEXTURE_2D;
  772. case GL_SAMPLER_2D_MULTISAMPLE:
  773. case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
  774. // Multisample textures are not supported.
  775. return TEXTURE_MAX_ENUM;
  776. case GL_SAMPLER_2D_RECT:
  777. case GL_SAMPLER_2D_RECT_SHADOW:
  778. // Rectangle textures are not supported.
  779. return TEXTURE_MAX_ENUM;
  780. case GL_SAMPLER_2D_ARRAY:
  781. case GL_SAMPLER_2D_ARRAY_SHADOW:
  782. return TEXTURE_2D_ARRAY;
  783. case GL_SAMPLER_3D:
  784. return TEXTURE_VOLUME;
  785. case GL_SAMPLER_CUBE:
  786. case GL_SAMPLER_CUBE_SHADOW:
  787. return TEXTURE_CUBE;
  788. case GL_SAMPLER_CUBE_MAP_ARRAY:
  789. case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
  790. // Cubemap array textures are not supported.
  791. return TEXTURE_MAX_ENUM;
  792. default:
  793. return TEXTURE_MAX_ENUM;
  794. }
  795. }
  796. bool Shader::isDepthTextureType(GLenum type) const
  797. {
  798. switch (type)
  799. {
  800. case GL_SAMPLER_1D_SHADOW:
  801. case GL_SAMPLER_1D_ARRAY_SHADOW:
  802. case GL_SAMPLER_2D_SHADOW:
  803. case GL_SAMPLER_2D_ARRAY_SHADOW:
  804. case GL_SAMPLER_CUBE_SHADOW:
  805. case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
  806. return true;
  807. default:
  808. return false;
  809. }
  810. }
  811. } // opengl
  812. } // graphics
  813. } // love