GameKit  0.0.1a
C++ gamedev tools
Shader.cpp
Go to the documentation of this file.
1 /*
2  * =====================================================================================
3  *
4  * Filename: Shader.cpp
5  *
6  * Description:
7  *
8  * Created: 15/12/2014 16:30:34
9  *
10  * Author: Quentin Bazin, <quent42340@gmail.com>
11  *
12  * =====================================================================================
13  */
14 #include <iostream>
15 #include <fstream>
16 
17 #define GLM_FORCE_RADIANS
18 #include <glm/gtc/type_ptr.hpp>
19 
20 #include "gk/gl/GLCheck.hpp"
21 #include "gk/gl/Shader.hpp"
22 #include "gk/gl/Transform.hpp"
23 #include "gk/core/Exception.hpp"
24 
25 namespace gk {
26 
27 Shader::Shader(const std::string &vertexFilename, const std::string &fragmentFilename) {
28  loadFromFile(vertexFilename, fragmentFilename);
29 }
30 
32  while(m_vertexShaders.size() != 0) {
33  glCheck(glDeleteShader(m_vertexShaders.back()));
34  m_vertexShaders.pop_back();
35  }
36 
37  while(m_fragmentShaders.size() != 0) {
38  glCheck(glDeleteShader(m_fragmentShaders.back()));
39  m_fragmentShaders.pop_back();
40  }
41 
42  glCheck(glDeleteProgram(m_program));
43 }
44 
45 void Shader::loadFromFile(const std::string &vertexFilename, const std::string &fragmentFilename) {
46  createProgram();
47 
48  addShader(GL_VERTEX_SHADER, vertexFilename);
49  addShader(GL_FRAGMENT_SHADER, fragmentFilename);
50 
51  linkProgram();
52 }
53 
55  glCheck(m_program = glCreateProgram());
56 }
57 
59  glCheck(glLinkProgram(m_program));
60 
61  GLint linkOK = GL_FALSE;
62  glCheck(glGetProgramiv(m_program, GL_LINK_STATUS, &linkOK));
63  if(!linkOK){
64  GLint errorSize = 0;
65  glCheck(glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &errorSize));
66 
67  char *errorMsg = new char[errorSize + 1];
68 
69  glCheck(glGetProgramInfoLog(m_program, errorSize, &errorSize, errorMsg));
70  errorMsg[errorSize] = '\0';
71 
72  std::string error = std::string(errorMsg);
73 
74  delete[] errorMsg;
75  glCheck(glDeleteProgram(m_program));
76 
77  throw EXCEPTION("Program", m_program, "link failed:", error);
78  }
79 }
80 
81 void Shader::addShader(GLenum type, const std::string &filename) {
82  GLuint shader;
83  glCheck(shader = glCreateShader(type));
84 
85  if(type == GL_VERTEX_SHADER) {
86  m_vertexShaders.push_back(shader);
87  } else {
88  m_fragmentShaders.push_back(shader);
89  }
90 
91  std::ifstream file(filename);
92  if(!file) {
93  glCheck(glDeleteShader(shader));
94 
95  throw EXCEPTION("Failed to open", filename);
96  }
97 
98  std::string line;
99  std::string sourceCode;
100 
101  while(getline(file, line)) sourceCode += line + '\n';
102  file.close();
103 
104  const GLchar *sourceCodeString = sourceCode.c_str();
105 
106  glCheck(glShaderSource(shader, 1, &sourceCodeString, nullptr));
107 
108  glCheck(glCompileShader(shader));
109 
110  GLint compileOK = GL_FALSE;
111  glCheck(glGetShaderiv(shader, GL_COMPILE_STATUS, &compileOK));
112  if(!compileOK) {
113  GLint errorSize = 0;
114  glCheck(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errorSize));
115 
116  char *errorMsg = new char[errorSize + 1];
117 
118  glCheck(glGetShaderInfoLog(shader, errorSize, &errorSize, errorMsg));
119  errorMsg[errorSize] = '\0';
120 
121  std::string error = std::string(errorMsg);
122 
123  delete[] errorMsg;
124  glCheck(glDeleteShader(shader));
125 
126  throw EXCEPTION("Shader", filename, "compilation failed:", error);
127  }
128 
129  glCheck(glAttachShader(m_program, shader));
130 }
131 
132 GLint Shader::attrib(const std::string &name) const {
133  GLint attrib;
134  glCheck(attrib = glGetAttribLocation(m_program, name.c_str()));
135 
136  if(attrib == -1) {
137  DEBUG("Could not bind attribute:", name);
138  }
139 
140  return attrib;
141 }
142 
143 GLint Shader::uniform(const std::string &name) const {
144  GLint uniform;
145  glCheck(uniform = glGetUniformLocation(m_program, name.c_str()));
146 
147  if(uniform == -1) {
148  DEBUG("Could not bind uniform:", name);
149  }
150 
151  return uniform;
152 }
153 
154 void Shader::enableVertexAttribArray(const std::string &name) const {
155  glCheck(glEnableVertexAttribArray(attrib(name)));
156 }
157 
158 void Shader::disableVertexAttribArray(const std::string &name) const {
159  glCheck(glDisableVertexAttribArray(attrib(name)));
160 }
161 
162 void Shader::setUniform(const std::string &name, int n) const {
163  glCheck(glUniform1i(uniform(name), n));
164 }
165 
166 void Shader::setUniform(const std::string &name, float x, float y) const {
167  glCheck(glUniform2f(uniform(name), x, y));
168 }
169 
170 void Shader::setUniform(const std::string &name, const glm::mat4 &matrix) const {
171  glCheck(glUniformMatrix4fv(uniform(name), 1, GL_FALSE, glm::value_ptr(matrix)));
172 }
173 
174 void Shader::setUniform(const std::string &name, const Transform &transform) const {
175  glCheck(glUniformMatrix4fv(uniform(name), 1, GL_FALSE, transform.getRawMatrix()));
176 }
177 
178 void Shader::bind(const Shader *shader) {
179  if(shader) {
180  glCheck(glUseProgram(shader->m_program));
181  } else {
182  glCheck(glUseProgram(0));
183  }
184 }
185 
186 } // namespace gk
187 
void enableVertexAttribArray(const std::string &name) const
Definition: Shader.cpp:154
#define DEBUG(args...)
Definition: Debug.hpp:31
void disableVertexAttribArray(const std::string &name) const
Definition: Shader.cpp:158
Shader()=default
void createProgram()
Definition: Shader.cpp:54
#define EXCEPTION(args...)
Definition: Exception.hpp:22
const float * getRawMatrix() const
Definition: Transform.hpp:44
static void bind(const Shader *shader)
Definition: Shader.cpp:178
std::vector< GLuint > m_fragmentShaders
Definition: Shader.hpp:58
void loadFromFile(const std::string &vertexFilename, const std::string &fragementFilename)
Definition: Shader.cpp:45
void linkProgram()
Definition: Shader.cpp:58
void addShader(GLenum type, const std::string &filename)
Definition: Shader.cpp:81
GLint attrib(const std::string &name) const
Definition: Shader.cpp:132
#define glCheck(expr)
Definition: GLCheck.hpp:18
std::vector< GLuint > m_vertexShaders
Definition: Shader.hpp:57
void setUniform(const std::string &name, int n) const
Definition: Shader.cpp:162
GLuint m_program
Definition: Shader.hpp:60
GLint uniform(const std::string &name) const
Definition: Shader.cpp:143