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 15KB

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