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 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*