Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Shader.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. getLog() << "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. getLog() << "Vertex Shader compilation error:" << Log::endl;
  98. getLog() << &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. getLog() << "Fragment Shader compilation error:" << Log::endl;
  114. getLog() << &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. getLog() << "Shader link error:" << Log::endl;
  132. getLog() << &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. getLog() << "GL Ven.: " << glGetString(GL_VENDOR) << Log::endl;
  149. getLog() << "GL Ren.: " << glGetString(GL_RENDERER) << Log::endl;
  150. getLog() << "GL Ver.: " << glGetString(GL_VERSION) << Log::endl;
  151. getLog() << "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. // Set up Z buffer
  158. glEnable(GL_DEPTH_TEST);
  159. // Accept fragment if closer to camera
  160. glDepthFunc(GL_LESS);
  161. glEnable(GL_BLEND);
  162. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  163. // Set up culling
  164. //glEnable(GL_CULL_FACE); //! \todo Transparency?
  165. glPointSize(5.0f);
  166. if (textShader.compile(textShaderVertex, textShaderFragment) < 0)
  167. return -1;
  168. if (textShader.addUniform("screen") < 0)
  169. return -2;
  170. if (textShader.addUniform("textureSampler") < 0)
  171. return -3;
  172. if (textShader.addUniform("colorVar") < 0)
  173. return -4;
  174. if (textureShader.compile(textureShaderVertex, textureShaderFragment) < 0)
  175. return -5;
  176. if (textureShader.addUniform("MVP") < 0)
  177. return -6;
  178. if (textureShader.addUniform("textureSampler") < 0)
  179. return -7;
  180. if (colorShader.compile(colorShaderVertex, colorShaderFragment) < 0)
  181. return -8;
  182. if (colorShader.addUniform("MVP") < 0)
  183. return -9;
  184. return 0;
  185. }
  186. void Shader::shutdown() {
  187. glDeleteVertexArrays(1, &vertexArrayID);
  188. }
  189. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, glm::vec4 color,
  190. unsigned int texture, TextureStorage store) {
  191. assert(vertices.getSize() == uvs.getSize());
  192. assert((vertices.getSize() % 3) == 0);
  193. textShader.use();
  194. textShader.loadUniform(0, Window::getSize());
  195. textShader.loadUniform(1, texture, store);
  196. textShader.loadUniform(2, color);
  197. vertices.bindBuffer(0, 2);
  198. uvs.bindBuffer(1, 2);
  199. glDisable(GL_DEPTH_TEST);
  200. glDrawArrays(GL_TRIANGLES, 0, vertices.getSize());
  201. glEnable(GL_DEPTH_TEST);
  202. vertices.unbind(0);
  203. uvs.unbind(1);
  204. }
  205. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, unsigned int texture,
  206. glm::mat4 MVP, TextureStorage store) {
  207. assert(vertices.getSize() == uvs.getSize());
  208. assert((vertices.getSize() % 3) == 0);
  209. textureShader.use();
  210. textureShader.loadUniform(0, MVP);
  211. textureShader.loadUniform(1, texture, store);
  212. vertices.bindBuffer(0, 3);
  213. uvs.bindBuffer(1, 2);
  214. glDrawArrays(GL_TRIANGLES, 0, vertices.getSize());
  215. vertices.unbind(0);
  216. uvs.unbind(1);
  217. }
  218. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, ShaderBuffer& indices,
  219. unsigned int texture, glm::mat4 MVP, TextureStorage store) {
  220. assert(vertices.getSize() == uvs.getSize());
  221. assert((indices.getSize() % 3) == 0);
  222. textureShader.use();
  223. textureShader.loadUniform(0, MVP);
  224. textureShader.loadUniform(1, texture, store);
  225. vertices.bindBuffer(0, 3);
  226. uvs.bindBuffer(1, 2);
  227. indices.bindBuffer();
  228. glDrawElements(GL_TRIANGLES, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  229. vertices.unbind(0);
  230. uvs.unbind(1);
  231. }
  232. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, glm::mat4 MVP, unsigned int mode) {
  233. assert(vertices.getSize() == colors.getSize());
  234. colorShader.use();
  235. colorShader.loadUniform(0, MVP);
  236. vertices.bindBuffer(0, 3);
  237. colors.bindBuffer(1, 3);
  238. glDrawArrays(mode, 0, vertices.getSize());
  239. vertices.unbind(0);
  240. colors.unbind(1);
  241. }
  242. void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, ShaderBuffer& indices,
  243. glm::mat4 MVP, unsigned int mode) {
  244. assert(vertices.getSize() == colors.getSize());
  245. colorShader.use();
  246. colorShader.loadUniform(0, MVP);
  247. vertices.bindBuffer(0, 3);
  248. colors.bindBuffer(1, 3);
  249. indices.bindBuffer();
  250. glDrawElements(mode, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
  251. vertices.unbind(0);
  252. colors.unbind(1);
  253. }
  254. // --------------------------------------
  255. // *INDENT-OFF*
  256. const char* Shader::textShaderVertex = R"!?!(
  257. #version 330 core
  258. layout(location = 0) in vec2 vertexPosition_screen;
  259. layout(location = 1) in vec2 vertexUV;
  260. out vec2 UV;
  261. uniform vec2 screen;
  262. void main() {
  263. vec2 halfScreen = screen / 2;
  264. vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
  265. gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
  266. UV = vertexUV;
  267. }
  268. )!?!";
  269. const char* Shader::textShaderFragment = R"!?!(
  270. #version 330 core
  271. in vec2 UV;
  272. out vec4 color;
  273. uniform sampler2D textureSampler;
  274. uniform vec4 colorVar;
  275. void main() {
  276. color = texture(textureSampler, UV) * colorVar;
  277. }
  278. )!?!";
  279. // --------------------------------------
  280. const char* Shader::textureShaderVertex = R"!?!(
  281. #version 330 core
  282. layout(location = 0) in vec3 vertexPosition_modelspace;
  283. layout(location = 1) in vec2 vertexUV;
  284. out vec2 UV;
  285. uniform mat4 MVP;
  286. void main() {
  287. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  288. -vertexPosition_modelspace.y,
  289. vertexPosition_modelspace.z,
  290. 1);
  291. gl_Position = vec4(-pos.x, pos.yzw);
  292. UV = vertexUV;
  293. }
  294. )!?!";
  295. const char* Shader::textureShaderFragment = R"!?!(
  296. #version 330 core
  297. in vec2 UV;
  298. out vec4 color;
  299. uniform sampler2D textureSampler;
  300. void main() {
  301. color = texture(textureSampler, UV);
  302. }
  303. )!?!";
  304. // --------------------------------------
  305. const char* Shader::colorShaderVertex = R"!?!(
  306. #version 330 core
  307. layout(location = 0) in vec3 vertexPosition_modelspace;
  308. layout(location = 1) in vec3 vertexColor;
  309. out vec3 Color;
  310. uniform mat4 MVP;
  311. void main() {
  312. vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
  313. -vertexPosition_modelspace.y,
  314. vertexPosition_modelspace.z,
  315. 1);
  316. gl_Position = vec4(-pos.x, pos.yzw);
  317. Color = vertexColor;
  318. }
  319. )!?!";
  320. const char* Shader::colorShaderFragment = R"!?!(
  321. #version 330 core
  322. in vec3 Color;
  323. out vec4 color;
  324. void main() {
  325. color = vec4(Color, 1);
  326. }
  327. )!?!";
  328. // --------------------------------------
  329. // *INDENT-ON*