sgltk 0.6
Simple OpenGL Tool Kit
Loading...
Searching...
No Matches
shader.cpp
1#include "shader.h"
2
3using namespace sgltk;
4
5int Shader::counter = 0;
6int Shader::bound = -1;
7std::vector<std::string> Shader::paths = {"./"};
8
9void Shader::add_path(std::string path) {
10 if(path[path.length() - 1] != '/')
11 path += '/';
12
13 if(std::find(paths.begin(), paths.end(), path) == paths.end())
14 paths.push_back(path);
15}
16
17Shader::Shader() {
18 if(counter < 0) {
19 std::string error("Error creating new shader program");
20 App::error_string.push_back(error);
21 throw std::runtime_error(error);
22 }
23 id = counter;
24 counter++;
25 transform_feedback = false;
26 modify = true;
27 linked = false;
28 program = glCreateProgram();
29 if(!program) {
30 std::string error("Error creating new shader program");
31 App::error_string.push_back(error);
32 throw std::runtime_error(error);
33 }
34}
35
36Shader::~Shader() {
37 glDeleteProgram(program);
38}
39
40bool Shader::attach_file(const std::string& filename, GLenum type) {
41 std::string path;
42 GLint compiled;
43 int info_log_length;
44 std::ifstream file;
45 const char *code;
46 GLuint tmp;
47 GLint size;
48
49 if((filename.length() > 1 && filename[0] == '/') ||
50 (filename.length() > 2 && filename[1] == ':')) {
51 //absolute path
52 file.open(filename.c_str(), std::ifstream::in | std::ifstream::binary);
53 path = filename;
54 } else {
55 //relative path
56 for(unsigned int i = 0; i < paths.size(); i++) {
57 file.open((paths[i] + filename).c_str(), std::ifstream::in | std::ifstream::binary);
58 if(file) {
59 path = paths[i] + filename;
60 break;
61 }
62 }
63 }
64
65 if(!file) {
66 App::error_string.push_back(std::string("Could not open shader file: ")
67 + filename);
68 return false;
69 }
70 file.seekg(0, file.end);
71 size = static_cast<GLint>(file.tellg());
72 file.seekg(0, file.beg);
73 std::unique_ptr<char[]> buf = std::make_unique<char[]>(size);
74 file.read(buf.get(), size);
75
76 file.close();
77 code = buf.get();
78
79 tmp = glCreateShader(type);
80 glShaderSource(tmp, 1, &code, &size);
81 glCompileShader(tmp);
82 glGetShaderiv(tmp, GL_COMPILE_STATUS, &compiled);
83 if(!compiled) {
84 glGetShaderiv(tmp, GL_INFO_LOG_LENGTH, &info_log_length);
85 std::unique_ptr<char[]> info_log = std::make_unique<char[]>(info_log_length);
86 glGetShaderInfoLog(tmp, info_log_length, &info_log_length, info_log.get());
87 std::cerr << "CompileShader() infoLog " << filename
88 << std::endl << info_log.get() << std::endl;
89 glDeleteShader(tmp);
90 return false;
91 }
92
93 glAttachShader(program, tmp);
94 attached.push_back(tmp);
95 if(modify) {
96 shader_path_map[path] = type;
97 }
98
99 glDeleteShader(tmp);
100 return true;
101}
102
103bool Shader::attach_string(const std::string& shader_string, GLenum type) {
104 GLint compiled;
105 const char *string_ptr = shader_string.c_str();
106 int size = shader_string.length();
107 int info_log_length;
108
109 GLuint tmp = glCreateShader(type);
110 glShaderSource(tmp, 1, &(string_ptr), &(size));
111 glCompileShader(tmp);
112 glGetShaderiv(tmp, GL_COMPILE_STATUS, &compiled);
113 if(!compiled) {
114 glGetShaderiv(tmp, GL_INFO_LOG_LENGTH, &info_log_length);
115 std::unique_ptr<char[]> infoLog = std::make_unique<char[]>(info_log_length);
116 glGetShaderInfoLog(tmp, info_log_length, &info_log_length, infoLog.get());
117 std::cerr << "CompileShader() infoLog " << std::endl
118 << infoLog.get() << std::endl;
119 glDeleteShader(tmp);
120 return false;
121 }
122
123 glAttachShader(program, tmp);
124 attached.push_back(tmp);
125 if(modify) {
126 shader_string_map[shader_string] = type;
127 }
128
129 glDeleteShader(tmp);
130 return true;
131}
132
133void Shader::set_transform_feedback_variables(std::vector<std::string>& variables, GLenum buffer_mode) {
134 transform_feedback = true;
135 std::vector<const char*> vars(variables.size());
136 for(unsigned int i = 0; i < variables.size(); i++) {
137 vars[i] = variables[i].c_str();
138 }
139 glTransformFeedbackVaryings(program, variables.size(), vars.data(), buffer_mode);
140 if(linked) {
141 link();
142 }
143}
144
146 modify = false;
147 unbind();
148 glDeleteProgram(program);
149 program = glCreateProgram();
150 for(const std::pair<std::string, GLenum>& it : shader_path_map) {
151 attach_file(it.first, it.second);
152 }
153 for(const std::pair<std::string, GLenum>& it : shader_string_map) {
154 attach_string(it.first, it.second);
155 }
156 link();
157 modify = true;
158}
159
161 GLint isLinked = 0;
162 glLinkProgram(program);
163 glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
164 if(isLinked == GL_FALSE) {
165 GLint info_log_length;
166 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
167 std::unique_ptr<char[]> info_log = std::make_unique<char[]>(info_log_length);
168 glGetProgramInfoLog(program, info_log_length, &info_log_length, info_log.get());
169 App::error_string.push_back(std::string(info_log.get()));
170 linked = false;
171 return false;
172 }
173 for(GLuint shader : attached) {
174 glDetachShader(program, shader);
175 }
176 linked = true;
177 return true;
178}
179
181 if(bound == id) {
182 return;
183 }
184 bound = id;
185 glUseProgram(program);
186}
187
189 if(bound == id) {
190 glUseProgram(0);
191 }
192 bound = -1;
193}
194
195int Shader::get_attribute_location(const std::string& name) {
196 return glGetAttribLocation(program, name.c_str());
197}
198
199int Shader::get_uniform_location(const std::string& name) {
200 return glGetUniformLocation(program, name.c_str());
201}
202
203void Shader::set_uniform(int location, const glm::vec2& value) {
204 set_uniform(location, value.x, value.y);
205}
206
207void Shader::set_uniform(int location, const glm::dvec2& value) {
208 set_uniform(location, value.x, value.y);
209}
210
211void Shader::set_uniform(int location, const glm::vec3& value) {
212 set_uniform(location, value.x, value.y, value.z);
213}
214
215void Shader::set_uniform(int location, const glm::dvec3& value) {
216 set_uniform(location, value.x, value.y, value.z);
217}
218
219void Shader::set_uniform(int location, const glm::vec4& value) {
220 set_uniform(location, value.x, value.y, value.z, value.w);
221}
222
223void Shader::set_uniform(int location, const glm::dvec4& value) {
224 set_uniform(location, value.x, value.y, value.z, value.w);
225}
226
227void Shader::set_uniform(const std::string& name, const glm::vec2& value) {
228 set_uniform(name, value.x, value.y);
229}
230
231void Shader::set_uniform(const std::string& name, const glm::dvec2& value) {
232 set_uniform(name, value.x, value.y);
233}
234
235void Shader::set_uniform(const std::string& name, const glm::vec3& value) {
236 set_uniform(name, value.x, value.y, value.z);
237}
238
239void Shader::set_uniform(const std::string& name, const glm::dvec3& value) {
240 set_uniform(name, value.x, value.y, value.z);
241}
242
243void Shader::set_uniform(const std::string& name, const glm::vec4& value) {
244 set_uniform(name, value.x, value.y, value.z, value.w);
245}
246
247void Shader::set_uniform(const std::string& name, const glm::dvec4& value) {
248 set_uniform(name, value.x, value.y, value.z, value.w);
249}
250
251void Shader::set_uniform(int location, bool transpose, const glm::mat2& value) {
252 set_uniform(location, 1, 2, 2, transpose, glm::value_ptr(value));
253}
254
255void Shader::set_uniform(int location, bool transpose, const glm::dmat2& value) {
256 set_uniform(location, 1, 2, 2, transpose, glm::value_ptr(value));
257}
258
259void Shader::set_uniform(int location, bool transpose, const glm::mat3& value) {
260 set_uniform(location, 1, 3, 3, transpose, glm::value_ptr(value));
261}
262
263void Shader::set_uniform(int location, bool transpose, const glm::dmat3& value) {
264 set_uniform(location, 1, 3, 3, transpose, glm::value_ptr(value));
265}
266
267void Shader::set_uniform(int location, bool transpose, const glm::mat4& value) {
268 set_uniform(location, 1, 4, 4, transpose, glm::value_ptr(value));
269}
270
271void Shader::set_uniform(int location, bool transpose, const glm::dmat4& value) {
272 set_uniform(location, 1, 4, 4, transpose, glm::value_ptr(value));
273}
274
275void Shader::set_uniform(const std::string& name,
276 bool transpose,
277 const glm::mat2& value) {
278 set_uniform(name, 1, 2, 2, transpose, glm::value_ptr(value));
279}
280
281void Shader::set_uniform(const std::string& name,
282 bool transpose,
283 const glm::dmat2& value) {
284 set_uniform(name, 1, 2, 2, transpose, glm::value_ptr(value));
285}
286
287void Shader::set_uniform(const std::string& name,
288 bool transpose,
289 const glm::mat3& value) {
290 set_uniform(name, 1, 3, 3, transpose, glm::value_ptr(value));
291}
292
293void Shader::set_uniform(const std::string& name,
294 bool transpose,
295 const glm::dmat3& value) {
296 set_uniform(name, 1, 3, 3, transpose, glm::value_ptr(value));
297}
298
299void Shader::set_uniform(const std::string& name,
300 bool transpose,
301 const glm::mat4& value) {
302 set_uniform(name, 1, 4, 4, transpose, glm::value_ptr(value));
303}
304
305void Shader::set_uniform(const std::string& name,
306 bool transpose,
307 const glm::dmat4& value) {
308 set_uniform(name, 1, 4, 4, transpose, glm::value_ptr(value));
309}
310
311void Shader::set_uniform(int location, const std::vector<glm::vec2>& value) {
312 set_uniform(location, value.size(), 2, glm::value_ptr(value[0]));
313}
314
315void Shader::set_uniform(int location, const std::vector<glm::dvec2>& value) {
316 set_uniform(location, value.size(), 2, glm::value_ptr(value[0]));
317}
318
319void Shader::set_uniform(int location, const std::vector<glm::vec3>& value) {
320 set_uniform(location, value.size(), 3, glm::value_ptr(value[0]));
321}
322
323void Shader::set_uniform(int location, const std::vector<glm::dvec3>& value) {
324 set_uniform(location, value.size(), 3, glm::value_ptr(value[0]));
325}
326
327void Shader::set_uniform(int location, const std::vector<glm::vec4>& value) {
328 set_uniform(location, value.size(), 4, glm::value_ptr(value[0]));
329}
330
331void Shader::set_uniform(int location, const std::vector<glm::dvec4>& value) {
332 set_uniform(location, value.size(), 4, glm::value_ptr(value[0]));
333}
334
335void Shader::set_uniform(const std::string& name,
336 const std::vector<glm::vec2>& value) {
337 set_uniform(name, value.size(), 2, glm::value_ptr(value[0]));
338}
339
340void Shader::set_uniform(const std::string& name,
341 const std::vector<glm::dvec2>& value) {
342 set_uniform(name, value.size(), 2, glm::value_ptr(value[0]));
343}
344
345void Shader::set_uniform(const std::string& name,
346 const std::vector<glm::vec3>& value) {
347 set_uniform(name, value.size(), 3, glm::value_ptr(value[0]));
348}
349
350void Shader::set_uniform(const std::string& name,
351 const std::vector<glm::dvec3>& value) {
352 set_uniform(name, value.size(), 3, glm::value_ptr(value[0]));
353}
354
355void Shader::set_uniform(const std::string& name,
356 const std::vector<glm::vec4>& value) {
357 set_uniform(name, value.size(), 4, glm::value_ptr(value[0]));
358}
359
360void Shader::set_uniform(const std::string& name,
361 const std::vector<glm::dvec4>& value) {
362 set_uniform(name, value.size(), 4, glm::value_ptr(value[0]));
363}
364
365void Shader::set_uniform(int location,
366 bool transpose,
367 const std::vector<glm::mat2>& value) {
368 set_uniform(location, value.size(), 2, 2,
369 transpose, glm::value_ptr(value[0]));
370}
371
372void Shader::set_uniform(int location,
373 bool transpose,
374 const std::vector<glm::dmat2>& value) {
375 set_uniform(location, value.size(), 2, 2,
376 transpose, glm::value_ptr(value[0]));
377}
378
379void Shader::set_uniform(int location,
380 bool transpose,
381 const std::vector<glm::mat3>& value) {
382 set_uniform(location, value.size(), 3, 3,
383 transpose, glm::value_ptr(value[0]));
384}
385
386void Shader::set_uniform(int location,
387 bool transpose,
388 const std::vector<glm::dmat3>& value) {
389 set_uniform(location, value.size(), 3, 3,
390 transpose, glm::value_ptr(value[0]));
391}
392
393void Shader::set_uniform(int location,
394 bool transpose,
395 const std::vector<glm::mat4>& value) {
396 set_uniform(location, value.size(), 4, 4,
397 transpose, glm::value_ptr(value[0]));
398}
399
400void Shader::set_uniform(int location,
401 bool transpose,
402 const std::vector<glm::dmat4>& value) {
403 set_uniform(location, value.size(), 4, 4,
404 transpose, glm::value_ptr(value[0]));
405}
406
407void Shader::set_uniform(const std::string& name,
408 bool transpose,
409 const std::vector<glm::mat2>& value) {
410 set_uniform(name, value.size(), 2, 2,
411 transpose, glm::value_ptr(value[0]));
412}
413
414void Shader::set_uniform(const std::string& name,
415 bool transpose,
416 const std::vector<glm::dmat2>& value) {
417 set_uniform(name, value.size(), 2, 2,
418 transpose, glm::value_ptr(value[0]));
419}
420
421void Shader::set_uniform(const std::string& name,
422 bool transpose,
423 const std::vector<glm::mat3>& value) {
424 set_uniform(name, value.size(), 3, 3,
425 transpose, glm::value_ptr(value[0]));
426}
427
428void Shader::set_uniform(const std::string& name,
429 bool transpose,
430 const std::vector<glm::dmat3>& value) {
431 set_uniform(name, value.size(), 3, 3,
432 transpose, glm::value_ptr(value[0]));
433}
434
435void Shader::set_uniform(const std::string& name,
436 bool transpose,
437 const std::vector<glm::mat4>& value) {
438 set_uniform(name, value.size(), 4, 4,
439 transpose, glm::value_ptr(value[0]));
440}
441
442void Shader::set_uniform(const std::string& name,
443 bool transpose,
444 const std::vector<glm::dmat4>& value) {
445 set_uniform(name, value.size(), 4, 4,
446 transpose, glm::value_ptr(value[0]));
447}
static std::vector< std::string > error_string
A list of all error strings.
Definition app.h:151
bool link()
Links the attached shaders.
Definition shader.cpp:160
void unbind()
Unbinds the shader and restores the previously bound shader.
Definition shader.cpp:188
bool attach_file(const std::string &filename, GLenum type)
Compiles and attaches shader files.
Definition shader.cpp:40
bool attach_string(const std::string &shader_string, GLenum type)
Compiles and attaches shader strings.
Definition shader.cpp:103
void recompile()
Reads, compiles and links all associated shaders again.
Definition shader.cpp:145
int get_attribute_location(const std::string &name)
Returns the location of an attribute variable.
Definition shader.cpp:195
void set_transform_feedback_variables(std::vector< std::string > &variables, GLenum buffer_mode)
Sets the variable to record in transform feedback buffers.
Definition shader.cpp:133
bool transform_feedback
True if the shader records values into transform feedback buffer(s)
Definition shader.h:36
void set_uniform(int location, T v0)
Sets the uniform.
void bind()
Binds the shader and stores the previously bound shader.
Definition shader.cpp:180
GLuint program
Shader name.
Definition shader.h:49
int get_uniform_location(const std::string &name)
Returns the location of a uniform variable.
Definition shader.cpp:199
static void add_path(std::string path)
Adds a path to the list of paths to be searched ▸ for image files.
Definition shader.cpp:9