Open Source Tomb Raider Engine
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

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*