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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. shader.use();
  203. shader.loadUniform(0, Window::getSize());
  204. shader.loadUniform(1, texture, store);
  205. shader.loadUniform(2, color);
  206. vertices.bindBuffer(0, 2);
  207. uvs.bindBuffer(1, 2);
  208. set2DState(true);
  209. glDrawArrays(mode, 0, vertices.getSize());
  210. set2DState(false);
  211. vertices.unbind(0);
  212. uvs.unbind(1);
  213. }
  214. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, unsigned int texture,
  215. glm::mat4 MVP, TextureStorage store, Shader& shader) {
  216. assert(vertices.getSize() == uvs.getSize());
  217. assert((vertices.getSize() % 3) == 0);
  218. shader.use();
  219. shader.loadUniform(0, MVP);
  220. shader.loadUniform(1, texture, store);
  221. vertices.bindBuffer(0, 3);
  222. uvs.bindBuffer(1, 2);
  223. glDrawArrays(GL_TRIANGLES, 0, vertices.getSize());
  224. vertices.unbind(0);
  225. uvs.unbind(1);
  226. }
  227. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, ShaderBuffer& indices,
  228. unsigned int texture, glm::mat4 MVP, TextureStorage store,
  229. Shader& shader) {
  230. assert(vertices.getSize() == uvs.getSize());
  231. assert((indices.getSize() % 3) == 0);
  232. shader.use();
  233. shader.loadUniform(0, MVP);
  234. shader.loadUniform(1, texture, store);
  235. vertices.bindBuffer(0, 3);
  236. uvs.bindBuffer(1, 2);
  237. indices.bindBuffer();
  238. glDrawElements(GL_TRIANGLES, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  239. vertices.unbind(0);
  240. uvs.unbind(1);
  241. }
  242. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, glm::mat4 MVP,
  243. unsigned int mode, Shader& shader) {
  244. assert(vertices.getSize() == colors.getSize());
  245. if (mode == GL_TRIANGLES)
  246. assert((vertices.getSize() % 3) == 0)
  247. shader.use();
  248. shader.loadUniform(0, MVP);
  249. vertices.bindBuffer(0, 3);
  250. colors.bindBuffer(1, 3);
  251. glDrawArrays(mode, 0, vertices.getSize());
  252. vertices.unbind(0);
  253. colors.unbind(1);
  254. }
  255. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, ShaderBuffer& indices,
  256. glm::mat4 MVP, unsigned int mode, Shader& shader) {
  257. assert(vertices.getSize() == colors.getSize());
  258. if (mode == GL_TRIANGLES)
  259. assert((indices.getSize() % 3) == 0)
  260. shader.use();
  261. shader.loadUniform(0, MVP);
  262. vertices.bindBuffer(0, 3);
  263. colors.bindBuffer(1, 3);
  264. indices.bindBuffer();
  265. glDrawElements(mode, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  266. vertices.unbind(0);
  267. colors.unbind(1);
  268. }
  269. // --------------------------------------
  270. // *INDENT-OFF*
  271. const char* Shader::textShaderVertex = R"!?!(
  272. #version 330 core
  273. layout(location = 0) in vec2 vertexPosition_screen;
  274. layout(location = 1) in vec2 vertexUV;
  275. out vec2 UV;
  276. uniform vec2 screen;
  277. void main() {
  278. vec2 halfScreen = screen / 2;
  279. vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
  280. gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
  281. UV = vertexUV;
  282. }
  283. )!?!";
  284. const char* Shader::textShaderFragment = R"!?!(
  285. #version 330 core
  286. in vec2 UV;
  287. out vec4 color;
  288. uniform sampler2D textureSampler;
  289. uniform vec4 colorVar;
  290. void main() {
  291. color = texture(textureSampler, UV) * colorVar;
  292. }
  293. )!?!";
  294. // --------------------------------------
  295. const char* Shader::textureShaderVertex = R"!?!(
  296. #version 330 core
  297. layout(location = 0) in vec3 vertexPosition_modelspace;
  298. layout(location = 1) in vec2 vertexUV;
  299. out vec2 UV;
  300. uniform mat4 MVP;
  301. void main() {
  302. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  303. -vertexPosition_modelspace.y,
  304. vertexPosition_modelspace.z,
  305. 1);
  306. gl_Position = vec4(-pos.x, pos.yzw);
  307. UV = vertexUV;
  308. }
  309. )!?!";
  310. const char* Shader::textureShaderFragment = R"!?!(
  311. #version 330 core
  312. in vec2 UV;
  313. out vec4 color;
  314. uniform sampler2D textureSampler;
  315. void main() {
  316. color = texture(textureSampler, UV);
  317. }
  318. )!?!";
  319. // --------------------------------------
  320. const char* Shader::colorShaderVertex = R"!?!(
  321. #version 330 core
  322. layout(location = 0) in vec3 vertexPosition_modelspace;
  323. layout(location = 1) in vec3 vertexColor;
  324. out vec3 Color;
  325. uniform mat4 MVP;
  326. void main() {
  327. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  328. -vertexPosition_modelspace.y,
  329. vertexPosition_modelspace.z,
  330. 1);
  331. gl_Position = vec4(-pos.x, pos.yzw);
  332. Color = vertexColor;
  333. }
  334. )!?!";
  335. const char* Shader::colorShaderFragment = R"!?!(
  336. #version 330 core
  337. in vec3 Color;
  338. out vec4 color;
  339. void main() {
  340. color = vec4(Color, 1);
  341. }
  342. )!?!";
  343. // --------------------------------------
  344. // *INDENT-ON*