Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Shader.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*!
  2. * \file src/system/Shader.cpp
  3. * \brief OpenGL Shader Implementation
  4. *
  5. * \author xythobuz
  6. */
  7. #include <sstream>
  8. #include "global.h"
  9. #include "Log.h"
  10. #include "Render.h"
  11. #include "system/Window.h"
  12. #include "system/Shader.h"
  13. #include <glbinding/gl/gl.h>
  14. ShaderBuffer::~ShaderBuffer() {
  15. if (created)
  16. gl::glDeleteBuffers(1, &buffer);
  17. }
  18. void ShaderBuffer::bufferData(int elem, int size, void* data) {
  19. if (!created) {
  20. gl::glGenBuffers(1, &buffer);
  21. created = true;
  22. }
  23. boundSize = elem;
  24. gl::glBindBuffer(gl::GL_ARRAY_BUFFER, buffer);
  25. gl::glBufferData(gl::GL_ARRAY_BUFFER, elem * size, data, gl::GL_DYNAMIC_DRAW);
  26. }
  27. void ShaderBuffer::bindBuffer() {
  28. if (!created) {
  29. gl::glGenBuffers(1, &buffer);
  30. created = true;
  31. }
  32. gl::glBindBuffer(gl::GL_ELEMENT_ARRAY_BUFFER, buffer);
  33. }
  34. void ShaderBuffer::bindBuffer(int location, int size) {
  35. if (!created) {
  36. gl::glGenBuffers(1, &buffer);
  37. created = true;
  38. }
  39. gl::glEnableVertexAttribArray(location);
  40. gl::glBindBuffer(gl::GL_ARRAY_BUFFER, buffer);
  41. gl::glVertexAttribPointer(location, size, gl::GL_FLOAT, gl::GL_FALSE, 0, nullptr);
  42. }
  43. void ShaderBuffer::unbind(int location) {
  44. orAssert(created == true);
  45. gl::glDisableVertexAttribArray(location);
  46. }
  47. // ----------------------------------------------------------------------------
  48. ShaderTexture::ShaderTexture(int w, int h) : width(w), height(h) {
  49. gl::glGenFramebuffers(1, &framebuffer);
  50. bind();
  51. texture = TextureManager::loadBufferSlot(nullptr, width, height, ColorMode::RGBA,
  52. 32, TextureStorage::SYSTEM, -1, false);
  53. gl::glGenRenderbuffers(1, &depth);
  54. gl::glBindRenderbuffer(gl::GL_RENDERBUFFER, depth);
  55. gl::glRenderbufferStorage(gl::GL_RENDERBUFFER, gl::GL_DEPTH_COMPONENT, width, height);
  56. gl::glFramebufferRenderbuffer(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, gl::GL_RENDERBUFFER,
  57. depth);
  58. gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_COLOR_ATTACHMENT0,
  59. TextureManager::getTextureID(texture, TextureStorage::SYSTEM), 0);
  60. gl::GLenum drawBuffer = gl::GL_COLOR_ATTACHMENT0;
  61. gl::glDrawBuffers(1, &drawBuffer);
  62. orAssert(gl::glCheckFramebufferStatus(gl::GL_FRAMEBUFFER) == gl::GL_FRAMEBUFFER_COMPLETE);
  63. }
  64. ShaderTexture::~ShaderTexture() {
  65. gl::glDeleteRenderbuffers(1, &depth);
  66. gl::glDeleteFramebuffers(1, &framebuffer);
  67. //! \fixme free texture slot
  68. }
  69. void ShaderTexture::clear() {
  70. bind();
  71. gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT);
  72. }
  73. void ShaderTexture::bind() {
  74. gl::glBindFramebuffer(gl::GL_FRAMEBUFFER, framebuffer);
  75. gl::glViewport(0, 0, width, height);
  76. }
  77. // ----------------------------------------------------------------------------
  78. Shader::~Shader() {
  79. if (programID >= 0)
  80. gl::glDeleteProgram(programID);
  81. }
  82. int Shader::getAttrib(const char* name) {
  83. orAssert(programID >= 0);
  84. orAssert(name != nullptr);
  85. orAssert(name[0] != '\0');
  86. return gl::glGetAttribLocation(programID, name);
  87. }
  88. int Shader::addUniform(const char* name) {
  89. orAssert(programID >= 0);
  90. int r = gl::glGetUniformLocation(programID, name);
  91. if (r < 0) {
  92. Log::get(LOG_ERROR) << "Can't find GLSL Uniform \"" << name << "\"!" << Log::endl;
  93. return -1;
  94. }
  95. uniforms.push_back(r);
  96. return uniforms.size() - 1;
  97. }
  98. unsigned int Shader::getUniform(int n) {
  99. orAssert(n >= 0);
  100. orAssert(n < uniforms.size());
  101. return uniforms.at(n);
  102. }
  103. void Shader::loadUniform(int uni, glm::vec2 vec) {
  104. gl::glUniform2f(getUniform(uni), vec.x, vec.y);
  105. }
  106. void Shader::loadUniform(int uni, glm::vec4 vec) {
  107. gl::glUniform4f(getUniform(uni), vec.r, vec.g, vec.b, vec.a);
  108. }
  109. void Shader::loadUniform(int uni, glm::mat4 mat) {
  110. gl::glUniformMatrix4fv(getUniform(uni), 1, gl::GL_FALSE, &mat[0][0]);
  111. }
  112. void Shader::loadUniform(int uni, int texture, TextureStorage store) {
  113. if ((Render::getMode() == RenderMode::Solid)
  114. && (store == TextureStorage::GAME)) {
  115. gl::glUniform1i(getUniform(uni), TextureManager::bindTexture(TEXTURE_SPLASH,
  116. TextureStorage::SYSTEM));
  117. } else {
  118. gl::glUniform1i(getUniform(uni), TextureManager::bindTexture(texture, store));
  119. }
  120. }
  121. void Shader::use() {
  122. orAssert(programID >= 0);
  123. static int lastID = -1;
  124. if (programID != lastID) {
  125. gl::glUseProgram(programID);
  126. lastID = programID;
  127. }
  128. }
  129. int Shader::compile(const char* vertex, const char* fragment) {
  130. orAssert(vertex != nullptr);
  131. orAssert(fragment != nullptr);
  132. gl::GLuint vertexID = gl::glCreateShader(gl::GL_VERTEX_SHADER);
  133. gl::GLuint fragmentID = gl::glCreateShader(gl::GL_FRAGMENT_SHADER);
  134. gl::GLint result = gl::GLint(gl::GL_FALSE);
  135. gl::GLint logLength = 0;
  136. // Compile vertex shader
  137. gl::glShaderSource(vertexID, 1, &vertex, nullptr);
  138. gl::glCompileShader(vertexID);
  139. // Check vertex shader
  140. gl::glGetShaderiv(vertexID, gl::GL_COMPILE_STATUS, &result);
  141. gl::glGetShaderiv(vertexID, gl::GL_INFO_LOG_LENGTH, &logLength);
  142. if ((logLength > 0) && (result != gl::GLint(gl::GL_TRUE))) {
  143. std::vector<char> message(logLength + 1);
  144. gl::glGetShaderInfoLog(vertexID, logLength, nullptr, &message[0]);
  145. Log::get(LOG_ERROR) << "Vertex Shader compilation error:" << Log::endl;
  146. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  147. gl::glDeleteShader(vertexID);
  148. gl::glDeleteShader(fragmentID);
  149. return -1;
  150. }
  151. // Compile fragment shader
  152. gl::glShaderSource(fragmentID, 1, &fragment, nullptr);
  153. gl::glCompileShader(fragmentID);
  154. // Check fragment shader
  155. gl::glGetShaderiv(fragmentID, gl::GL_COMPILE_STATUS, &result);
  156. gl::glGetShaderiv(fragmentID, gl::GL_INFO_LOG_LENGTH, &logLength);
  157. if ((logLength > 0) && (result != gl::GLint(gl::GL_TRUE))) {
  158. std::vector<char> message(logLength + 1);
  159. gl::glGetShaderInfoLog(fragmentID, logLength, nullptr, &message[0]);
  160. Log::get(LOG_ERROR) << "Fragment Shader compilation error:" << Log::endl;
  161. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  162. gl::glDeleteShader(vertexID);
  163. gl::glDeleteShader(fragmentID);
  164. return -2;
  165. }
  166. // Link both shaders
  167. programID = gl::glCreateProgram();
  168. gl::glAttachShader(programID, vertexID);
  169. gl::glAttachShader(programID, fragmentID);
  170. gl::glLinkProgram(programID);
  171. // Check resulting program
  172. gl::glGetProgramiv(programID, gl::GL_LINK_STATUS, &result);
  173. gl::glGetProgramiv(programID, gl::GL_INFO_LOG_LENGTH, &logLength);
  174. if ((logLength > 0) && (result != gl::GLint(gl::GL_TRUE))) {
  175. std::vector<char> message(logLength + 1);
  176. gl::glGetProgramInfoLog(programID, logLength, nullptr, &message[0]);
  177. Log::get(LOG_ERROR) << "Shader link error:" << Log::endl;
  178. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  179. gl::glDeleteShader(vertexID);
  180. gl::glDeleteShader(fragmentID);
  181. gl::glDeleteProgram(programID);
  182. return -3;
  183. }
  184. gl::glDeleteShader(vertexID);
  185. gl::glDeleteShader(fragmentID);
  186. return programID;
  187. }
  188. // ----------------------------------------------------------------------------
  189. std::string Shader::getVersion(bool linked) {
  190. static std::string cache;
  191. static std::string cacheLinked;
  192. static bool cacheFilled = false;
  193. if (!cacheFilled) {
  194. std::ostringstream str;
  195. str << "OpenGL v" << gl::glGetString(gl::GL_VERSION);
  196. cache = str.str();
  197. str.str("");
  198. str << "OpenGL " << gl::glGetString(gl::GL_SHADING_LANGUAGE_VERSION) << " "
  199. << gl::glGetString(gl::GL_RENDERER) << " (" << gl::glGetString(gl::GL_VENDOR) << ")";
  200. cacheLinked = str.str();
  201. cacheFilled = true;
  202. }
  203. if (linked) {
  204. return cacheLinked;
  205. } else {
  206. return cache;
  207. }
  208. }
  209. Shader Shader::textureShader;
  210. Shader Shader::colorShader;
  211. Shader Shader::transformedColorShader;
  212. unsigned int Shader::vertexArrayID = 0;
  213. bool Shader::lastBufferWasNotFramebuffer = true;
  214. int Shader::initialize() {
  215. gl::glGenVertexArrays(1, &vertexArrayID);
  216. gl::glBindVertexArray(vertexArrayID);
  217. // Set background color
  218. gl::glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
  219. set2DState(false);
  220. gl::glDepthFunc(gl::GL_LESS);
  221. gl::glEnable(gl::GL_BLEND);
  222. gl::glBlendEquation(gl::GL_FUNC_ADD);
  223. gl::glBlendFunc(gl::GL_SRC_ALPHA, gl::GL_ONE_MINUS_SRC_ALPHA);
  224. gl::glPointSize(5.0f);
  225. if (textureShader.compile(textureShaderVertex, textureShaderFragment) < 0)
  226. return -1;
  227. if (textureShader.addUniform("MVP") < 0)
  228. return -2;
  229. if (textureShader.addUniform("textureSampler") < 0)
  230. return -3;
  231. if (colorShader.compile(colorShaderVertex, colorShaderFragment) < 0)
  232. return -4;
  233. if (colorShader.addUniform("MVP") < 0)
  234. return -5;
  235. if (transformedColorShader.compile(transformedColorShaderVertex,
  236. transformedColorShaderFragment) < 0)
  237. return -6;
  238. return 0;
  239. }
  240. void Shader::shutdown() {
  241. gl::glDeleteVertexArrays(1, &vertexArrayID);
  242. }
  243. void Shader::set2DState(bool on, bool depth) {
  244. if (on) {
  245. gl::glDisable(gl::GL_CULL_FACE);
  246. if (depth)
  247. gl::glDisable(gl::GL_DEPTH_TEST);
  248. } else {
  249. gl::glEnable(gl::GL_CULL_FACE);
  250. if (depth)
  251. gl::glEnable(gl::GL_DEPTH_TEST);
  252. }
  253. }
  254. void Shader::bindProperBuffer(ShaderTexture* target) {
  255. if ((target == nullptr) && lastBufferWasNotFramebuffer) {
  256. lastBufferWasNotFramebuffer = false;
  257. gl::glBindFramebuffer(gl::GL_FRAMEBUFFER, 0);
  258. gl::glViewport(0, 0, Window::getSize().x, Window::getSize().y);
  259. } else if (target != nullptr) {
  260. lastBufferWasNotFramebuffer = true;
  261. target->bind();
  262. }
  263. }
  264. void Shader::drawGL(std::vector<glm::vec3>& vertices, std::vector<glm::vec2>& uvs,
  265. glm::mat4 MVP, unsigned int texture, TextureStorage store,
  266. gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  267. bindProperBuffer(target);
  268. shader.use();
  269. shader.loadUniform(0, MVP);
  270. shader.loadUniform(1, texture, store);
  271. shader.vertexBuffer.bufferData(vertices);
  272. shader.otherBuffer.bufferData(uvs);
  273. shader.vertexBuffer.bindBuffer(0, 3);
  274. shader.otherBuffer.bindBuffer(1, 2);
  275. gl::glDrawArrays(mode, 0, shader.vertexBuffer.getSize());
  276. shader.vertexBuffer.unbind(0);
  277. shader.otherBuffer.unbind(1);
  278. }
  279. void Shader::drawGL(std::vector<glm::vec3>& vertices, std::vector<glm::vec2>& uvs,
  280. std::vector<unsigned short>& indices, glm::mat4 MVP,
  281. unsigned int texture, TextureStorage store,
  282. gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  283. drawGLBuffer(vertices, uvs);
  284. drawGLOnly(indices, MVP, texture, store, mode, target, shader);
  285. }
  286. void Shader::drawGLBuffer(std::vector<glm::vec3>& vertices, std::vector<glm::vec2>& uvs,
  287. Shader& shader) {
  288. shader.vertexBuffer.bufferData(vertices);
  289. shader.otherBuffer.bufferData(uvs);
  290. }
  291. void Shader::drawGLOnly(std::vector<unsigned short>& indices, glm::mat4 MVP,
  292. unsigned int texture, TextureStorage store,
  293. gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  294. bindProperBuffer(target);
  295. shader.use();
  296. shader.loadUniform(0, MVP);
  297. shader.loadUniform(1, texture, store);
  298. shader.indexBuffer.bufferData(indices);
  299. shader.vertexBuffer.bindBuffer(0, 3);
  300. shader.otherBuffer.bindBuffer(1, 2);
  301. shader.indexBuffer.bindBuffer();
  302. gl::glDrawElements(mode, shader.indexBuffer.getSize(), gl::GL_UNSIGNED_SHORT, nullptr);
  303. shader.vertexBuffer.unbind(0);
  304. shader.otherBuffer.unbind(1);
  305. }
  306. void Shader::drawGL(std::vector<glm::vec3>& vertices, std::vector<glm::vec3>& colors,
  307. glm::mat4 MVP, gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  308. bindProperBuffer(target);
  309. shader.use();
  310. shader.loadUniform(0, MVP);
  311. shader.vertexBuffer.bufferData(vertices);
  312. shader.otherBuffer.bufferData(colors);
  313. shader.vertexBuffer.bindBuffer(0, 3);
  314. shader.otherBuffer.bindBuffer(1, 3);
  315. gl::glDrawArrays(mode, 0, shader.vertexBuffer.getSize());
  316. shader.vertexBuffer.unbind(0);
  317. shader.otherBuffer.unbind(1);
  318. }
  319. void Shader::drawGL(std::vector<glm::vec3>& vertices, std::vector<glm::vec3>& colors,
  320. std::vector<unsigned short>& indices, glm::mat4 MVP,
  321. gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  322. bindProperBuffer(target);
  323. shader.use();
  324. shader.loadUniform(0, MVP);
  325. shader.vertexBuffer.bufferData(vertices);
  326. shader.otherBuffer.bufferData(colors);
  327. shader.indexBuffer.bufferData(indices);
  328. shader.vertexBuffer.bindBuffer(0, 3);
  329. shader.otherBuffer.bindBuffer(1, 3);
  330. shader.indexBuffer.bindBuffer();
  331. gl::glDrawElements(mode, shader.indexBuffer.getSize(), gl::GL_UNSIGNED_SHORT, nullptr);
  332. shader.vertexBuffer.unbind(0);
  333. shader.otherBuffer.unbind(1);
  334. }
  335. void Shader::drawGL(std::vector<glm::vec4>& vertices, std::vector<glm::vec3>& colors,
  336. gl::GLenum mode, ShaderTexture* target, Shader& shader) {
  337. bindProperBuffer(target);
  338. shader.use();
  339. shader.vertexBuffer.bufferData(vertices);
  340. shader.otherBuffer.bufferData(colors);
  341. shader.vertexBuffer.bindBuffer(0, 4);
  342. shader.otherBuffer.bindBuffer(1, 3);
  343. gl::glDrawArrays(mode, 0, shader.vertexBuffer.getSize());
  344. shader.vertexBuffer.unbind(0);
  345. shader.otherBuffer.unbind(0);
  346. }
  347. void Shader::drawGL(std::vector<glm::vec4>& vertices, std::vector<glm::vec3>& colors,
  348. std::vector<unsigned short>& indices, gl::GLenum mode,
  349. ShaderTexture* target, Shader& shader) {
  350. bindProperBuffer(target);
  351. shader.use();
  352. shader.vertexBuffer.bufferData(vertices);
  353. shader.otherBuffer.bufferData(colors);
  354. shader.indexBuffer.bufferData(indices);
  355. shader.vertexBuffer.bindBuffer(0, 4);
  356. shader.otherBuffer.bindBuffer(1, 3);
  357. shader.indexBuffer.bindBuffer();
  358. gl::glDrawElements(mode, shader.indexBuffer.getSize(), gl::GL_UNSIGNED_SHORT, nullptr);
  359. shader.vertexBuffer.unbind(0);
  360. shader.otherBuffer.unbind(0);
  361. }
  362. // --------------------------------------
  363. // *INDENT-OFF*
  364. const char* Shader::textureShaderVertex = R"!?!(
  365. #version 330 core
  366. layout(location = 0) in vec3 vertexPosition_modelspace;
  367. layout(location = 1) in vec2 vertexUV;
  368. out vec2 UV;
  369. uniform mat4 MVP;
  370. void main() {
  371. vec4 pos = MVP * vec4(vertexPosition_modelspace, 1);
  372. gl_Position = pos;
  373. UV = vertexUV;
  374. }
  375. )!?!";
  376. const char* Shader::textureShaderFragment = R"!?!(
  377. #version 330 core
  378. in vec2 UV;
  379. layout(location = 0) out vec4 color;
  380. uniform sampler2D textureSampler;
  381. void main() {
  382. color = texture(textureSampler, UV);
  383. }
  384. )!?!";
  385. // --------------------------------------
  386. const char* Shader::colorShaderVertex = R"!?!(
  387. #version 330 core
  388. layout(location = 0) in vec3 vertexPosition_modelspace;
  389. layout(location = 1) in vec3 vertexColor;
  390. out vec3 color;
  391. uniform mat4 MVP;
  392. void main() {
  393. vec4 pos = MVP * vec4(vertexPosition_modelspace, 1);
  394. gl_Position = pos;
  395. color = vertexColor;
  396. }
  397. )!?!";
  398. const char* Shader::colorShaderFragment = R"!?!(
  399. #version 330 core
  400. in vec3 color;
  401. layout(location = 0) out vec4 color_out;
  402. void main() {
  403. color_out = vec4(color, 1);
  404. }
  405. )!?!";
  406. // --------------------------------------
  407. const char* Shader::transformedColorShaderVertex = R"!?!(
  408. #version 330 core
  409. layout(location = 0) in vec4 vertexPosition;
  410. layout(location = 1) in vec3 vertexColor;
  411. out vec3 color;
  412. void main() {
  413. gl_Position = vertexPosition;
  414. color = vertexColor;
  415. }
  416. )!?!";
  417. const char* Shader::transformedColorShaderFragment = R"!?!(
  418. #version 330 core
  419. in vec3 color;
  420. layout(location = 0) out vec4 color_out;
  421. void main() {
  422. color_out = vec4(color, 1);
  423. }
  424. )!?!";
  425. // --------------------------------------
  426. // *INDENT-ON*