Open Source Tomb Raider Engine
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

Shader.cpp 14KB

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