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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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. Shader::~Shader() {
  46. if (programID >= 0)
  47. glDeleteProgram(programID);
  48. }
  49. int Shader::addUniform(const char* name) {
  50. assert(programID >= 0);
  51. int r = glGetUniformLocation(programID, name);
  52. if (r < 0) {
  53. Log::get(LOG_ERROR) << "Can't find GLSL Uniform \"" << name << "\"!" << Log::endl;
  54. return -1;
  55. }
  56. uniforms.push_back(r);
  57. return uniforms.size() - 1;
  58. }
  59. unsigned int Shader::getUniform(int n) {
  60. assert(n >= 0);
  61. assert(n < uniforms.size());
  62. return uniforms.at(n);
  63. }
  64. void Shader::loadUniform(int uni, glm::vec2 vec) {
  65. glUniform2f(getUniform(uni), vec.x, vec.y);
  66. }
  67. void Shader::loadUniform(int uni, glm::vec4 vec) {
  68. glUniform4f(getUniform(uni), vec.r, vec.g, vec.b, vec.a);
  69. }
  70. void Shader::loadUniform(int uni, glm::mat4 mat) {
  71. glUniformMatrix4fv(getUniform(uni), 1, GL_FALSE, &mat[0][0]);
  72. }
  73. void Shader::loadUniform(int uni, int texture, TextureStorage store) {
  74. glUniform1i(getUniform(uni), TextureManager::bindTexture(texture, store));
  75. }
  76. void Shader::use() {
  77. assert(programID >= 0);
  78. glUseProgram(programID);
  79. }
  80. int Shader::compile(const char* vertex, const char* fragment) {
  81. assert(vertex != nullptr);
  82. assert(fragment != nullptr);
  83. GLuint vertexID = glCreateShader(GL_VERTEX_SHADER);
  84. GLuint fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
  85. GLint result = GL_FALSE;
  86. GLint logLength = 0;
  87. // Compile vertex shader
  88. glShaderSource(vertexID, 1, &vertex, nullptr);
  89. glCompileShader(vertexID);
  90. // Check vertex shader
  91. glGetShaderiv(vertexID, GL_COMPILE_STATUS, &result);
  92. glGetShaderiv(vertexID, GL_INFO_LOG_LENGTH, &logLength);
  93. if (logLength > 0) {
  94. std::vector<char> message(logLength + 1);
  95. glGetShaderInfoLog(vertexID, logLength, nullptr, &message[0]);
  96. if (result != GL_TRUE)
  97. Log::get(LOG_ERROR) << "Vertex Shader compilation error:" << Log::endl;
  98. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  99. glDeleteShader(vertexID);
  100. glDeleteShader(fragmentID);
  101. return -1;
  102. }
  103. // Compile fragment shader
  104. glShaderSource(fragmentID, 1, &fragment, nullptr);
  105. glCompileShader(fragmentID);
  106. // Check fragment shader
  107. glGetShaderiv(fragmentID, GL_COMPILE_STATUS, &result);
  108. glGetShaderiv(fragmentID, GL_INFO_LOG_LENGTH, &logLength);
  109. if (logLength > 0) {
  110. std::vector<char> message(logLength + 1);
  111. glGetShaderInfoLog(fragmentID, logLength, nullptr, &message[0]);
  112. if (result != GL_TRUE)
  113. Log::get(LOG_ERROR) << "Fragment Shader compilation error:" << Log::endl;
  114. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  115. glDeleteShader(vertexID);
  116. glDeleteShader(fragmentID);
  117. return -2;
  118. }
  119. // Link both shaders
  120. programID = glCreateProgram();
  121. glAttachShader(programID, vertexID);
  122. glAttachShader(programID, fragmentID);
  123. glLinkProgram(programID);
  124. // Check resulting program
  125. glGetProgramiv(programID, GL_LINK_STATUS, &result);
  126. glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLength);
  127. if (logLength > 0) {
  128. std::vector<char> message(logLength + 1);
  129. glGetProgramInfoLog(programID, logLength, nullptr, &message[0]);
  130. if (result != GL_TRUE)
  131. Log::get(LOG_ERROR) << "Shader link error:" << Log::endl;
  132. Log::get(LOG_ERROR) << &message[0] << Log::endl;
  133. glDeleteShader(vertexID);
  134. glDeleteShader(fragmentID);
  135. glDeleteProgram(programID);
  136. return -3;
  137. }
  138. glDeleteShader(vertexID);
  139. glDeleteShader(fragmentID);
  140. return programID;
  141. }
  142. // ----------------------------------------------------------------------------
  143. Shader Shader::textShader;
  144. Shader Shader::textureShader;
  145. Shader Shader::colorShader;
  146. unsigned int Shader::vertexArrayID = 0;
  147. int Shader::initialize() {
  148. Log::get(LOG_DEBUG) << "GL Ven.: " << glGetString(GL_VENDOR) << Log::endl;
  149. Log::get(LOG_DEBUG) << "GL Ren.: " << glGetString(GL_RENDERER) << Log::endl;
  150. Log::get(LOG_DEBUG) << "GL Ver.: " << glGetString(GL_VERSION) << Log::endl;
  151. Log::get(LOG_DEBUG) << "GLSL V.: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << Log::endl;
  152. glGenVertexArrays(1, &vertexArrayID);
  153. glBindVertexArray(vertexArrayID);
  154. // Set background to black
  155. //glClearColor(BLACK[0] / 256.0f, BLACK[1] / 256.0f, BLACK[2] / 256.0f, BLACK[3] / 256.0f);
  156. glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
  157. set2DState(false);
  158. glDepthFunc(GL_LESS);
  159. glEnable(GL_BLEND);
  160. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  161. glPointSize(5.0f);
  162. if (textShader.compile(textShaderVertex, textShaderFragment) < 0)
  163. return -1;
  164. if (textShader.addUniform("screen") < 0)
  165. return -2;
  166. if (textShader.addUniform("textureSampler") < 0)
  167. return -3;
  168. if (textShader.addUniform("colorVar") < 0)
  169. return -4;
  170. if (textureShader.compile(textureShaderVertex, textureShaderFragment) < 0)
  171. return -5;
  172. if (textureShader.addUniform("MVP") < 0)
  173. return -6;
  174. if (textureShader.addUniform("textureSampler") < 0)
  175. return -7;
  176. if (colorShader.compile(colorShaderVertex, colorShaderFragment) < 0)
  177. return -8;
  178. if (colorShader.addUniform("MVP") < 0)
  179. return -9;
  180. return 0;
  181. }
  182. void Shader::shutdown() {
  183. glDeleteVertexArrays(1, &vertexArrayID);
  184. }
  185. void Shader::set2DState(bool on, bool depth) {
  186. if (on) {
  187. glDisable(GL_CULL_FACE);
  188. if (depth)
  189. glDisable(GL_DEPTH_TEST);
  190. } else {
  191. glEnable(GL_CULL_FACE);
  192. if (depth)
  193. glEnable(GL_DEPTH_TEST);
  194. }
  195. }
  196. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, glm::vec4 color,
  197. unsigned int texture, TextureStorage store, unsigned int mode,
  198. Shader& shader) {
  199. assert(vertices.getSize() == uvs.getSize());
  200. if (mode == GL_TRIANGLES) {
  201. assert((vertices.getSize() % 3) == 0)
  202. }
  203. shader.use();
  204. shader.loadUniform(0, Window::getSize());
  205. shader.loadUniform(1, texture, store);
  206. shader.loadUniform(2, color);
  207. vertices.bindBuffer(0, 2);
  208. uvs.bindBuffer(1, 2);
  209. set2DState(true);
  210. glDrawArrays(mode, 0, vertices.getSize());
  211. set2DState(false);
  212. vertices.unbind(0);
  213. uvs.unbind(1);
  214. }
  215. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, unsigned int texture,
  216. glm::mat4 MVP, TextureStorage store, Shader& shader) {
  217. assert(vertices.getSize() == uvs.getSize());
  218. assert((vertices.getSize() % 3) == 0);
  219. shader.use();
  220. shader.loadUniform(0, MVP);
  221. shader.loadUniform(1, texture, store);
  222. vertices.bindBuffer(0, 3);
  223. uvs.bindBuffer(1, 2);
  224. glDrawArrays(GL_TRIANGLES, 0, vertices.getSize());
  225. vertices.unbind(0);
  226. uvs.unbind(1);
  227. }
  228. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, ShaderBuffer& indices,
  229. unsigned int texture, glm::mat4 MVP, TextureStorage store,
  230. Shader& shader) {
  231. assert(vertices.getSize() == uvs.getSize());
  232. assert((indices.getSize() % 3) == 0);
  233. shader.use();
  234. shader.loadUniform(0, MVP);
  235. shader.loadUniform(1, texture, store);
  236. vertices.bindBuffer(0, 3);
  237. uvs.bindBuffer(1, 2);
  238. indices.bindBuffer();
  239. glDrawElements(GL_TRIANGLES, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  240. vertices.unbind(0);
  241. uvs.unbind(1);
  242. }
  243. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, glm::mat4 MVP,
  244. unsigned int mode, Shader& shader) {
  245. assert(vertices.getSize() == colors.getSize());
  246. if (mode == GL_TRIANGLES) {
  247. assert((vertices.getSize() % 3) == 0)
  248. }
  249. shader.use();
  250. shader.loadUniform(0, MVP);
  251. vertices.bindBuffer(0, 3);
  252. colors.bindBuffer(1, 3);
  253. glDrawArrays(mode, 0, vertices.getSize());
  254. vertices.unbind(0);
  255. colors.unbind(1);
  256. }
  257. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, ShaderBuffer& indices,
  258. glm::mat4 MVP, unsigned int mode, Shader& shader) {
  259. assert(vertices.getSize() == colors.getSize());
  260. if (mode == GL_TRIANGLES) {
  261. assert((indices.getSize() % 3) == 0)
  262. }
  263. shader.use();
  264. shader.loadUniform(0, MVP);
  265. vertices.bindBuffer(0, 3);
  266. colors.bindBuffer(1, 3);
  267. indices.bindBuffer();
  268. glDrawElements(mode, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  269. vertices.unbind(0);
  270. colors.unbind(1);
  271. }
  272. // --------------------------------------
  273. // *INDENT-OFF*
  274. const char* Shader::textShaderVertex = R"!?!(
  275. #version 330 core
  276. layout(location = 0) in vec2 vertexPosition_screen;
  277. layout(location = 1) in vec2 vertexUV;
  278. out vec2 UV;
  279. uniform vec2 screen;
  280. void main() {
  281. vec2 halfScreen = screen / 2;
  282. vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
  283. gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
  284. UV = vertexUV;
  285. }
  286. )!?!";
  287. const char* Shader::textShaderFragment = R"!?!(
  288. #version 330 core
  289. in vec2 UV;
  290. out vec4 color;
  291. uniform sampler2D textureSampler;
  292. uniform vec4 colorVar;
  293. void main() {
  294. color = texture(textureSampler, UV) * colorVar;
  295. }
  296. )!?!";
  297. // --------------------------------------
  298. const char* Shader::textureShaderVertex = R"!?!(
  299. #version 330 core
  300. layout(location = 0) in vec3 vertexPosition_modelspace;
  301. layout(location = 1) in vec2 vertexUV;
  302. out vec2 UV;
  303. uniform mat4 MVP;
  304. void main() {
  305. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  306. -vertexPosition_modelspace.y,
  307. vertexPosition_modelspace.z,
  308. 1);
  309. gl_Position = vec4(-pos.x, pos.yzw);
  310. UV = vertexUV;
  311. }
  312. )!?!";
  313. const char* Shader::textureShaderFragment = R"!?!(
  314. #version 330 core
  315. in vec2 UV;
  316. out vec4 color;
  317. uniform sampler2D textureSampler;
  318. void main() {
  319. color = texture(textureSampler, UV);
  320. }
  321. )!?!";
  322. // --------------------------------------
  323. const char* Shader::colorShaderVertex = R"!?!(
  324. #version 330 core
  325. layout(location = 0) in vec3 vertexPosition_modelspace;
  326. layout(location = 1) in vec3 vertexColor;
  327. out vec3 Color;
  328. uniform mat4 MVP;
  329. void main() {
  330. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  331. -vertexPosition_modelspace.y,
  332. vertexPosition_modelspace.z,
  333. 1);
  334. gl_Position = vec4(-pos.x, pos.yzw);
  335. Color = vertexColor;
  336. }
  337. )!?!";
  338. const char* Shader::colorShaderFragment = R"!?!(
  339. #version 330 core
  340. in vec3 Color;
  341. out vec4 color;
  342. void main() {
  343. color = vec4(Color, 1);
  344. }
  345. )!?!";
  346. // --------------------------------------
  347. // *INDENT-ON*