OpenRaider  0.1.4-dev
Open Source Tomb Raider Game Engine implementation
Shader.cpp
Go to the documentation of this file.
1 
8 #include "global.h"
9 #include "Log.h"
10 #include "system/Window.h"
11 #include "system/Shader.h"
12 
14  if (created)
15  glDeleteBuffers(1, &buffer);
16 }
17 
18 void ShaderBuffer::bufferData(int elem, int size, void* data) {
19  if (!created) {
20  glGenBuffers(1, &buffer);
21  created = true;
22  }
23 
24  boundSize = elem;
25  glBindBuffer(GL_ARRAY_BUFFER, buffer);
26  glBufferData(GL_ARRAY_BUFFER, elem * size, data, GL_STATIC_DRAW);
27 }
28 
30  if (!created) {
31  glGenBuffers(1, &buffer);
32  created = true;
33  }
34 
35  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
36 }
37 
38 void ShaderBuffer::bindBuffer(int location, int size) {
39  if (!created) {
40  glGenBuffers(1, &buffer);
41  created = true;
42  }
43 
44  glEnableVertexAttribArray(location);
45  glBindBuffer(GL_ARRAY_BUFFER, buffer);
46  glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE, 0, nullptr);
47 }
48 
49 void ShaderBuffer::unbind(int location) {
50  assert(created == true);
51  glDisableVertexAttribArray(location);
52 }
53 
54 // ----------------------------------------------------------------------------
55 
56 ShaderTexture::ShaderTexture(int w, int h) : width(w), height(h) {
57  glGenFramebuffers(1, &framebuffer);
58  bind();
59 
61  32, TextureStorage::SYSTEM, -1, false);
62 
63  glGenRenderbuffers(1, &depth);
64  glBindRenderbuffer(GL_RENDERBUFFER, depth);
65  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
66  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
67 
68  glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
70 
71  GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
72  glDrawBuffers(1, &drawBuffer);
73 
74  assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
75 }
76 
78  glDeleteRenderbuffers(1, &depth);
79  glDeleteFramebuffers(1, &framebuffer);
80 
82 }
83 
85  bind();
86  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
87 }
88 
90  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
91  glViewport(0, 0, width, height);
92 }
93 
94 // ----------------------------------------------------------------------------
95 
97  if (programID >= 0)
98  glDeleteProgram(programID);
99 }
100 
101 int Shader::addUniform(const char* name) {
102  assert(programID >= 0);
103  int r = glGetUniformLocation(programID, name);
104  if (r < 0) {
105  Log::get(LOG_ERROR) << "Can't find GLSL Uniform \"" << name << "\"!" << Log::endl;
106  return -1;
107  }
108  uniforms.push_back(r);
109  return uniforms.size() - 1;
110 }
111 
112 unsigned int Shader::getUniform(int n) {
113  assert(n >= 0);
114  assert(n < uniforms.size());
115  return uniforms.at(n);
116 }
117 
118 void Shader::loadUniform(int uni, glm::vec2 vec) {
119  glUniform2f(getUniform(uni), vec.x, vec.y);
120 }
121 
122 void Shader::loadUniform(int uni, glm::vec4 vec) {
123  glUniform4f(getUniform(uni), vec.r, vec.g, vec.b, vec.a);
124 }
125 
126 void Shader::loadUniform(int uni, glm::mat4 mat) {
127  glUniformMatrix4fv(getUniform(uni), 1, GL_FALSE, &mat[0][0]);
128 }
129 
130 void Shader::loadUniform(int uni, int texture, TextureStorage store) {
131  glUniform1i(getUniform(uni), TextureManager::bindTexture(texture, store));
132 }
133 
134 void Shader::use() {
135  assert(programID >= 0);
136  glUseProgram(programID);
137 }
138 
139 int Shader::compile(const char* vertex, const char* fragment) {
140  assert(vertex != nullptr);
141  assert(fragment != nullptr);
142 
143  GLuint vertexID = glCreateShader(GL_VERTEX_SHADER);
144  GLuint fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
145 
146  GLint result = GL_FALSE;
147  GLint logLength = 0;
148 
149  // Compile vertex shader
150  glShaderSource(vertexID, 1, &vertex, nullptr);
151  glCompileShader(vertexID);
152 
153  // Check vertex shader
154  glGetShaderiv(vertexID, GL_COMPILE_STATUS, &result);
155  glGetShaderiv(vertexID, GL_INFO_LOG_LENGTH, &logLength);
156  if (logLength > 0) {
157  std::vector<char> message(logLength + 1);
158  glGetShaderInfoLog(vertexID, logLength, nullptr, &message[0]);
159  if (result != GL_TRUE)
160  Log::get(LOG_ERROR) << "Vertex Shader compilation error:" << Log::endl;
161  Log::get(LOG_ERROR) << &message[0] << Log::endl;
162  glDeleteShader(vertexID);
163  glDeleteShader(fragmentID);
164  return -1;
165  }
166 
167  // Compile fragment shader
168  glShaderSource(fragmentID, 1, &fragment, nullptr);
169  glCompileShader(fragmentID);
170 
171  // Check fragment shader
172  glGetShaderiv(fragmentID, GL_COMPILE_STATUS, &result);
173  glGetShaderiv(fragmentID, GL_INFO_LOG_LENGTH, &logLength);
174  if (logLength > 0) {
175  std::vector<char> message(logLength + 1);
176  glGetShaderInfoLog(fragmentID, logLength, nullptr, &message[0]);
177  if (result != GL_TRUE)
178  Log::get(LOG_ERROR) << "Fragment Shader compilation error:" << Log::endl;
179  Log::get(LOG_ERROR) << &message[0] << Log::endl;
180  glDeleteShader(vertexID);
181  glDeleteShader(fragmentID);
182  return -2;
183  }
184 
185  // Link both shaders
186  programID = glCreateProgram();
187  glAttachShader(programID, vertexID);
188  glAttachShader(programID, fragmentID);
189  glLinkProgram(programID);
190 
191  // Check resulting program
192  glGetProgramiv(programID, GL_LINK_STATUS, &result);
193  glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLength);
194  if (logLength > 0) {
195  std::vector<char> message(logLength + 1);
196  glGetProgramInfoLog(programID, logLength, nullptr, &message[0]);
197  if (result != GL_TRUE)
198  Log::get(LOG_ERROR) << "Shader link error:" << Log::endl;
199  Log::get(LOG_ERROR) << &message[0] << Log::endl;
200  glDeleteShader(vertexID);
201  glDeleteShader(fragmentID);
202  glDeleteProgram(programID);
203  return -3;
204  }
205 
206  glDeleteShader(vertexID);
207  glDeleteShader(fragmentID);
208  return programID;
209 }
210 
211 // ----------------------------------------------------------------------------
212 
216 unsigned int Shader::vertexArrayID = 0;
217 
219  Log::get(LOG_DEBUG) << "GL Ven.: " << glGetString(GL_VENDOR) << Log::endl;
220  Log::get(LOG_DEBUG) << "GL Ren.: " << glGetString(GL_RENDERER) << Log::endl;
221  Log::get(LOG_DEBUG) << "GL Ver.: " << glGetString(GL_VERSION) << Log::endl;
222  Log::get(LOG_DEBUG) << "GLSL V.: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << Log::endl;
223 
224  glGenVertexArrays(1, &vertexArrayID);
225  glBindVertexArray(vertexArrayID);
226 
227  // Set background color
228  glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
229 
230  set2DState(false);
231  glDepthFunc(GL_LESS);
232 
233  glEnable(GL_BLEND);
234  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
235 
236  glPointSize(5.0f);
237 
239  return -1;
240  if (textShader.addUniform("screen") < 0)
241  return -2;
242  if (textShader.addUniform("textureSampler") < 0)
243  return -3;
244  if (textShader.addUniform("colorVar") < 0)
245  return -4;
246 
248  return -5;
249  if (textureShader.addUniform("MVP") < 0)
250  return -6;
251  if (textureShader.addUniform("textureSampler") < 0)
252  return -7;
253 
255  return -8;
256  if (colorShader.addUniform("MVP") < 0)
257  return -9;
258 
259  return 0;
260 }
261 
263  glDeleteVertexArrays(1, &vertexArrayID);
264 }
265 
266 void Shader::set2DState(bool on, bool depth) {
267  if (on) {
268  glDisable(GL_CULL_FACE);
269  if (depth)
270  glDisable(GL_DEPTH_TEST);
271  } else {
272  glEnable(GL_CULL_FACE);
273  if (depth)
274  glEnable(GL_DEPTH_TEST);
275  }
276 }
277 
278 void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, glm::vec4 color,
279  unsigned int texture, TextureStorage store, unsigned int mode,
280  ShaderTexture* target, Shader& shader) {
281  assert(vertices.getSize() == uvs.getSize());
282  if (mode == GL_TRIANGLES) {
283  assert((vertices.getSize() % 3) == 0);
284  }
285 
286  if (target == nullptr) {
287  glBindFramebuffer(GL_FRAMEBUFFER, 0);
288  glViewport(0, 0, Window::getSize().x, Window::getSize().y);
289  } else {
290  target->bind();
291  }
292 
293  shader.use();
294  shader.loadUniform(0, Window::getSize());
295  shader.loadUniform(1, texture, store);
296  shader.loadUniform(2, color);
297  vertices.bindBuffer(0, 2);
298  uvs.bindBuffer(1, 2);
299 
300  set2DState(true);
301  glDrawArrays(mode, 0, vertices.getSize());
302  set2DState(false);
303 
304  vertices.unbind(0);
305  uvs.unbind(1);
306 }
307 
308 void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, unsigned int texture,
309  glm::mat4 MVP, TextureStorage store, ShaderTexture* target,
310  Shader& shader) {
311  assert(vertices.getSize() == uvs.getSize());
312  assert((vertices.getSize() % 3) == 0);
313 
314  if (target == nullptr) {
315  glBindFramebuffer(GL_FRAMEBUFFER, 0);
316  glViewport(0, 0, Window::getSize().x, Window::getSize().y);
317  } else {
318  target->bind();
319  }
320 
321  shader.use();
322  shader.loadUniform(0, MVP);
323  shader.loadUniform(1, texture, store);
324  vertices.bindBuffer(0, 3);
325  uvs.bindBuffer(1, 2);
326  glDrawArrays(GL_TRIANGLES, 0, vertices.getSize());
327  vertices.unbind(0);
328  uvs.unbind(1);
329 }
330 
331 void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& uvs, ShaderBuffer& indices,
332  unsigned int texture, glm::mat4 MVP, TextureStorage store,
333  ShaderTexture* target, Shader& shader) {
334  assert(vertices.getSize() == uvs.getSize());
335  assert((indices.getSize() % 3) == 0);
336 
337  if (target == nullptr) {
338  glBindFramebuffer(GL_FRAMEBUFFER, 0);
339  glViewport(0, 0, Window::getSize().x, Window::getSize().y);
340  } else {
341  target->bind();
342 
343  unsigned int sz = vertices.getSize();
344  glm::vec3* buffer = new glm::vec3[sz];
345  glBindBuffer(GL_ARRAY_BUFFER, vertices.getBuffer());
346  glGetBufferSubData(GL_ARRAY_BUFFER, 0, sz * sizeof(glm::vec3), buffer);
347 
348  Log::get(LOG_DEBUG) << "drawGL Vertex dump:" << Log::endl;
349  for (unsigned int i = 0; i < sz; i++) {
350  glm::vec4 tmp(buffer[i], 1.0f);
351  tmp = MVP * tmp;
352  glm::vec3 res(tmp.x, tmp.y, tmp.z);
353  Log::get(LOG_DEBUG) << buffer[i] << " -> " << res << Log::endl;
354  }
355 
356  delete [] buffer;
357  }
358 
359  shader.use();
360  shader.loadUniform(0, MVP);
361  shader.loadUniform(1, texture, store);
362  vertices.bindBuffer(0, 3);
363  uvs.bindBuffer(1, 2);
364  indices.bindBuffer();
365  glDrawElements(GL_TRIANGLES, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
366  vertices.unbind(0);
367  uvs.unbind(1);
368 }
369 
370 void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, glm::mat4 MVP,
371  unsigned int mode, ShaderTexture* target, Shader& shader) {
372  assert(vertices.getSize() == colors.getSize());
373  if (mode == GL_TRIANGLES) {
374  assert((vertices.getSize() % 3) == 0);
375  }
376 
377  if (target == nullptr) {
378  glBindFramebuffer(GL_FRAMEBUFFER, 0);
379  glViewport(0, 0, Window::getSize().x, Window::getSize().y);
380  } else {
381  target->bind();
382  }
383 
384  shader.use();
385  shader.loadUniform(0, MVP);
386  vertices.bindBuffer(0, 3);
387  colors.bindBuffer(1, 3);
388  glDrawArrays(mode, 0, vertices.getSize());
389  vertices.unbind(0);
390  colors.unbind(1);
391 }
392 
393 void Shader::drawGL(ShaderBuffer& vertices, ShaderBuffer& colors, ShaderBuffer& indices,
394  glm::mat4 MVP, unsigned int mode, ShaderTexture* target, Shader& shader) {
395  assert(vertices.getSize() == colors.getSize());
396  if (mode == GL_TRIANGLES) {
397  assert((indices.getSize() % 3) == 0);
398  }
399 
400  if (target == nullptr) {
401  glBindFramebuffer(GL_FRAMEBUFFER, 0);
402  glViewport(0, 0, Window::getSize().x, Window::getSize().y);
403  } else {
404  target->bind();
405  }
406 
407  shader.use();
408  shader.loadUniform(0, MVP);
409  vertices.bindBuffer(0, 3);
410  colors.bindBuffer(1, 3);
411  indices.bindBuffer();
412  glDrawElements(mode, indices.getSize(), GL_UNSIGNED_SHORT, nullptr);
413  vertices.unbind(0);
414  colors.unbind(1);
415 }
416 
417 // --------------------------------------
418 // *INDENT-OFF*
419 
420 const char* Shader::textShaderVertex = R"!?!(
421 #version 330 core
422 
423 layout(location = 0) in vec2 vertexPosition_screen;
424 layout(location = 1) in vec2 vertexUV;
425 
426 out vec2 UV;
427 
428 uniform vec2 screen;
429 
430 void main() {
431  vec2 halfScreen = screen / 2;
432  vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
433 
434  gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
435  UV = vertexUV;
436 }
437 )!?!";
438 
439 const char* Shader::textShaderFragment = R"!?!(
440 #version 330 core
441 
442 in vec2 UV;
443 
444 layout(location = 0) out vec4 color;
445 
446 uniform sampler2D textureSampler;
447 uniform vec4 colorVar;
448 
449 void main() {
450  color = texture(textureSampler, UV) * colorVar;
451 }
452 )!?!";
453 
454 // --------------------------------------
455 
456 const char* Shader::textureShaderVertex = R"!?!(
457 #version 330 core
458 
459 layout(location = 0) in vec3 vertexPosition_modelspace;
460 layout(location = 1) in vec2 vertexUV;
461 
462 out vec2 UV;
463 
464 uniform mat4 MVP;
465 
466 void main() {
467  vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
468  -vertexPosition_modelspace.y,
469  vertexPosition_modelspace.z,
470  1);
471  gl_Position = vec4(-pos.x, pos.yzw);
472  UV = vertexUV;
473 }
474 )!?!";
475 
476 const char* Shader::textureShaderFragment = R"!?!(
477 #version 330 core
478 
479 in vec2 UV;
480 
481 layout(location = 0) out vec4 color;
482 
483 uniform sampler2D textureSampler;
484 
485 void main() {
486  color = texture(textureSampler, UV);
487 }
488 )!?!";
489 
490 // --------------------------------------
491 
492 const char* Shader::colorShaderVertex = R"!?!(
493 #version 330 core
494 
495 layout(location = 0) in vec3 vertexPosition_modelspace;
496 layout(location = 1) in vec3 vertexColor;
497 
498 out vec3 color;
499 
500 uniform mat4 MVP;
501 
502 void main() {
503  vec4 pos = MVP * vec4(vertexPosition_modelspace.x,
504  -vertexPosition_modelspace.y,
505  vertexPosition_modelspace.z,
506  1);
507  gl_Position = vec4(-pos.x, pos.yzw);
508  color = vertexColor;
509 }
510 )!?!";
511 
512 const char* Shader::colorShaderFragment = R"!?!(
513 #version 330 core
514 
515 in vec3 color;
516 
517 layout(location = 0) out vec4 color_out;
518 
519 void main() {
520  color_out = vec4(color, 1);
521 }
522 )!?!";
523 
524 // --------------------------------------
525 // *INDENT-ON*
526 
ShaderTexture(int w=512, int h=512)
Definition: Shader.cpp:56
static const char * textureShaderFragment
Definition: Shader.h:104
void bufferData(int elem, int size, void *data)
Definition: Shader.cpp:18
static Shader textShader
Definition: Shader.h:98
int width
Definition: Shader.h:49
unsigned int buffer
Definition: Shader.h:35
static const char * textShaderVertex
Definition: Shader.h:99
OpenGL Shader Implementation.
int height
Definition: Shader.h:49
int getSize()
Definition: Shader.h:31
static void shutdown()
Definition: Shader.cpp:262
Included everywhere.
void bindBuffer()
Definition: Shader.cpp:29
void loadUniform(int uni, glm::vec2 vec)
Definition: Shader.cpp:118
static LogLevel & get(int level)
Definition: Log.cpp:14
int compile(const char *vertex, const char *fragment)
Definition: Shader.cpp:139
int texture
Definition: Shader.h:51
int programID
Definition: Shader.h:95
~Shader()
Definition: Shader.cpp:96
unsigned int depth
Definition: Shader.h:50
static int initialize()
Definition: Shader.cpp:218
static const char * colorShaderFragment
Definition: Shader.h:108
Global Logging Utility.
bool created
Definition: Shader.h:34
Windowing Interface.
#define assert(x)
Definition: global.h:124
static Shader colorShader
Definition: Shader.h:106
static int bindTexture(unsigned int n, TextureStorage s)
Bind texture to next free texture unit.
static const char * textureShaderVertex
Definition: Shader.h:103
static void drawGL(ShaderBuffer &vertices, ShaderBuffer &uvs, glm::vec4 color, unsigned int texture, TextureStorage store=TextureStorage::SYSTEM, unsigned int mode=GL_TRIANGLES, ShaderTexture *target=nullptr, Shader &shader=textShader)
Definition: Shader.cpp:278
static unsigned int getTextureID(int n, TextureStorage s)
#define LOG_DEBUG
Definition: Log.h:22
static const char * textShaderFragment
Definition: Shader.h:100
unsigned int getBuffer()
Definition: Shader.h:30
static Shader textureShader
Definition: Shader.h:102
static const char endl
Definition: Log.h:35
#define LOG_ERROR
Definition: Log.h:19
static const char * colorShaderVertex
Definition: Shader.h:107
TextureStorage
void clear()
Definition: Shader.cpp:84
unsigned int framebuffer
Definition: Shader.h:50
Definition: Shader.h:54
int addUniform(const char *name)
Definition: Shader.cpp:101
void use()
Definition: Shader.cpp:134
~ShaderTexture()
Definition: Shader.cpp:77
static unsigned int vertexArrayID
Definition: Shader.h:110
static int loadBufferSlot(unsigned char *image=nullptr, unsigned int width=256, unsigned int height=256, ColorMode mode=ColorMode::RGBA, unsigned int bpp=32, TextureStorage s=TextureStorage::GAME, int slot=-1, bool filter=true)
Loads Buffer as texture.
~ShaderBuffer()
Definition: Shader.cpp:13
int boundSize
Definition: Shader.h:36
void bind()
Definition: Shader.cpp:89
static void set2DState(bool on, bool depth=true)
Definition: Shader.cpp:266
std::vector< unsigned int > uniforms
Definition: Shader.h:96
void unbind(int location)
Definition: Shader.cpp:49
static glm::i32vec2 getSize()
Definition: Window.cpp:71
unsigned int getUniform(int n)
Definition: Shader.cpp:112