SuperTuxKart
Loading...
Searching...
No Matches
shader.hpp
1// SuperTuxKart - a fun racing game with go-kart
2// Copyright (C) 2014-2015 SuperTuxKart-Team
3//
4// This program is free software; you can redistribute it and/or
5// modify it under the terms of the GNU General Public License
6// as published by the Free Software Foundation; either version 3
7// of the License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18#ifndef SERVER_ONLY
19
20#ifndef HEADER_SHADER_HPP
21#define HEADER_SHADER_HPP
22
23#include "graphics/gl_headers.hpp"
24#include "graphics/shader_files_manager.hpp"
25#include "graphics/shared_gpu_objects.hpp"
26#include "utils/singleton.hpp"
27
28#include <matrix4.h>
29#include <SColor.h>
30#include <vector3d.h>
31#include <array>
32
33#include <string>
34#include <vector>
35
43{
44protected:
46 static std::vector<void (*)()> m_all_kill_functions;
47
48 enum AttributeType
49 {
50 OBJECT,
51 PARTICLES_SIM,
52 PARTICLES_RENDERING,
53 SKINNED_MESH,
54 }; // AttributeType
55
57 GLuint m_program;
58 std::vector<std::shared_ptr<GLuint> > m_shaders;
59
60 // ========================================================================
62 template<typename ... Types>
64 {
65 return;
66 } // loadAndAttachShader
67 // ------------------------------------------------------------------------
68 template<typename ... Types>
69 void loadAndAttachShader(GLint shader_type, const std::string &name,
70 Types ... args)
71 {
72 auto shader_id = ShaderFilesManager::getInstance()
73 ->getShaderFile(name, shader_type);
74 if (shader_id)
75 {
76 m_shaders.push_back(shader_id);
77 glAttachShader(m_program, *shader_id);
78 }
79 loadAndAttachShader(args...);
80 } // loadAndAttachShader
81 // ------------------------------------------------------------------------
83 template<typename ... Types>
84 void loadAndAttachShader(GLint shader_type, const char *name,
85 Types ... args)
86 {
87 loadAndAttachShader(shader_type, std::string(name), args...);
88 } // loadAndAttachShader
89
90public:
91 ShaderBase();
93 {
94 glDeleteProgram(m_program);
95 }
96 int loadTFBProgram(const std::string &vertex_file_path,
97 const char **varyings,
98 unsigned varyingscount);
99 static void killShaders();
100 GLuint createVAO();
101 // ------------------------------------------------------------------------
103 void use() { glUseProgram(m_program); }
104 // ------------------------------------------------------------------------
105 GLuint getUniformLocation(const char *name)
106 {
107 return glGetUniformLocation(m_program, name);
108 } // getUniformLocation
109}; // ShaderBase
110
111// ============================================================================
117template<typename T, typename... Args>
118class Shader : public ShaderBase, public Singleton<T>
119{
120private:
121 std::vector<GLuint> m_uniforms;
122
124 void bindPoint(const char *name, int index)
125 {
126 GLuint block_index = glGetUniformBlockIndex(m_program, name);
127 if (block_index != GL_INVALID_INDEX)
128 glUniformBlockBinding(m_program, block_index, index);
129 } // bindPoint
130
131
132 // ========================================================================
133 // assignUniforms: Variadic Template
134protected:
138 template<typename... U>
139 void assignUniforms(U... rest)
140 {
141 static_assert(sizeof...(rest) == sizeof...(Args),
142 "Count of Uniform's name mismatch");
143 assignUniformsImpl(rest...);
144 } // assignUniforms
145private:
146 // ------------------------------------------------------------------------
149 {
150 bindPoint("Matrices", 0);
151 bindPoint("LightingData", 1);
152 bindPoint("SPFogData", 2);
153 } // assignUniformsImpl
154
155 // ------------------------------------------------------------------------
160 template<typename... U>
161 void assignUniformsImpl(const char* name, U... rest)
162 {
163 m_uniforms.push_back(glGetUniformLocation(m_program, name));
164 assignUniformsImpl(rest...);
165 } // assignUniformsImpl
166
167
168 // ==============================================
169 // setUniforms: Variadic template implementation.
170
171public:
173 void setUniforms(const Args & ... args) const
174 {
175 setUniformsImpl(args...);
176 } // setUniforms
177 // ------------------------------------------------------------------------
178private:
180 template<unsigned N = 0, typename... Args1>
181 void setUniformsImpl(const std::vector<float> &v, Args1... arg) const
182 {
183 glUniform1fv(m_uniforms[N], (int)v.size(), v.data());
184 setUniformsImpl<N + 1>(arg...);
185 } // setUniformsImpl
186
187 // ------------------------------------------------------------------------
190 template<unsigned N = 0>
191 void setUniformsImpl() const
192 {
193 } // setUniformImpl
194
195 // ------------------------------------------------------------------------
197 template<unsigned N = 0, typename... Args1>
198 void setUniformsImpl(const irr::core::matrix4 &mat, Args1... arg) const
199 {
200 glUniformMatrix4fv(m_uniforms[N], 1, GL_FALSE, mat.pointer());
201 setUniformsImpl<N + 1>(arg...);
202 } // setUniformImpl
203
204 // ------------------------------------------------------------------------
206 template<unsigned N = 0, typename... Args1>
207 void setUniformsImpl(const irr::video::SColorf &col, Args1... arg) const
208 {
209 glUniform3f(m_uniforms[N], col.r, col.g, col.b);
210 setUniformsImpl<N + 1>(arg...);
211 } // setUniformsImpl
212
213 // ------------------------------------------------------------------------
215 template<unsigned N = 0, typename... Args1>
216 void setUniformsImpl(const irr::video::SColor &col, Args1... arg) const
217 {
218 glUniform4i(m_uniforms[N], col.getRed(), col.getGreen(),
219 col.getBlue(), col.getAlpha());
220 setUniformsImpl<N + 1>(arg...);
221 } // setUniformsImpl
222
223 // ------------------------------------------------------------------------
225 template<unsigned N = 0, typename... Args1>
226 void setUniformsImpl(const std::array<float, 4> &ff, Args1... arg) const
227 {
228 glUniform4f(m_uniforms[N], ff[0], ff[1], ff[2], ff[3]);
229 setUniformsImpl<N + 1>(arg...);
230 } // setUniformsImpl
231
232 // ------------------------------------------------------------------------
234 template<unsigned N = 0, typename... Args1>
235 void setUniformsImpl(const irr::core::vector3df &v, Args1... arg) const
236 {
237 glUniform3f(m_uniforms[N], v.X, v.Y, v.Z);
238 setUniformsImpl<N + 1>(arg...);
239 } // setUniformsImpl
240
241 // ------------------------------------------------------------------------
243 template<unsigned N = 0, typename... Args1>
244 void setUniformsImpl(const irr::core::vector2df &v, Args1... arg) const
245 {
246 glUniform2f(m_uniforms[N], v.X, v.Y);
247 setUniformsImpl<N + 1>(arg...);
248 } // setUniformsImpl
249
250 // ------------------------------------------------------------------------
252 template<unsigned N = 0, typename... Args1>
253 void setUniformsImpl(const irr::core::dimension2df &v, Args1... arg) const
254 {
255 glUniform2f(m_uniforms[N], v.Width, v.Height);
256 setUniformsImpl<N + 1>(arg...);
257 } // setUniformsImpl
258
259 // ------------------------------------------------------------------------
261 template<unsigned N = 0, typename... Args1>
262 void setUniformsImpl(float f, Args1... arg) const
263 {
264 glUniform1f(m_uniforms[N], f);
265 setUniformsImpl<N + 1>(arg...);
266 } // setUniformsImpl
267
268 // ------------------------------------------------------------------------
270 template<unsigned N = 0, typename... Args1>
271 void setUniformsImpl(int f, Args1... arg) const
272 {
273 glUniform1i(m_uniforms[N], f);
274 setUniformsImpl<N + 1>(arg...);
275 } // setUniformsImpl
276
277
278 // printFileList: Variadic template for printing a list of shader filenames
279 // ========================================================================
285protected:
286 template<typename ...Types>
287 void printFileList(GLint shader_type, const char *filepath, Types ... args)
288 {
289 Log::error("shader", filepath);
290 printFileList(args...);
291 } // printFileList
292
293 // ------------------------------------------------------------------------
295private:
296 template<typename ...Types>
298 {
299 return;
300 } // printFileList
301
302
303 // Variadic template implementation of assignTextureUnit
304 // ========================================================================
305public:
312 template<typename... T1>
313 void assignTextureUnit(GLuint index, const char* uniform, T1... rest)
314 {
315 glUseProgram(m_program);
316 GLuint uniform_loc = glGetUniformLocation(m_program, uniform);
317 glUniform1i(uniform_loc, index);
318 // Avoid doing any additional glUseProgram for the remaining calls
319 assignTextureUnitNoUse(rest...);
320 glUseProgram(0);
321 } // assignTextureUnit
322
323private:
324 // ------------------------------------------------------------------------
327
328 // ------------------------------------------------------------------------
331 template<typename... T1>
332 void assignTextureUnitNoUse(GLuint index, const char* uniform, T1... rest)
333 {
334 GLuint uniform_loc = glGetUniformLocation(m_program, uniform);
335 glUniform1i(uniform_loc, index);
336 assignTextureUnitNoUse(rest...);
337 } // assignTextureUnitNoUse
338
339 // ========================================================================
340
341public:
342
348 {
349 m_all_kill_functions.push_back(this->kill);
350 } // Shader
351
352 // ------------------------------------------------------------------------
355 template<typename ... Types>
356 void loadProgram(AttributeType type, Types ... args)
357 {
358 m_program = glCreateProgram();
359 loadAndAttachShader(args...);
360 glLinkProgram(m_program);
361
362 GLint Result = GL_FALSE;
363 glGetProgramiv(m_program, GL_LINK_STATUS, &Result);
364 if (Result == GL_FALSE)
365 {
366 int info_length;
367 Log::error("Shader", "Error when linking these shaders :");
368 printFileList(args...);
369 glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_length);
370 char *error_message = new char[info_length];
371 glGetProgramInfoLog(m_program, info_length, NULL, error_message);
372 Log::error("Shader", error_message);
373 delete[] error_message;
374 }
375 // After linking all shaders can be detached
376 for (auto shader : m_shaders)
377 {
378 glDetachShader(m_program, *shader);
379 }
380 } // loadProgram
381 // ------------------------------------------------------------------------
382 void drawFullScreenEffect(Args...args)
383 {
384 use();
385 glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
386 setUniforms(args...);
387 glDrawArrays(GL_TRIANGLES, 0, 3);
388 } // drawFullScreenEffect
389
390}; // Shader
391
392
393#endif
394
395#endif // !SERVER_ONLY
396
A simple non-templated base class.
Definition: shader.hpp:43
ShaderBase()
Constructor, which adds the shader to all instantiated shaders (for the reload-all-shaders debug opti...
Definition: shader.cpp:72
void use()
Activates the shader calling glUseProgram.
Definition: shader.hpp:103
void loadAndAttachShader(GLint shader_type, const char *name, Types ... args)
Convenience interface using const char.
Definition: shader.hpp:84
static std::vector< void(*)()> m_all_kill_functions
Maintains a list of all shaders.
Definition: shader.hpp:46
void loadAndAttachShader()
Ends recursion.
Definition: shader.hpp:63
GLuint m_program
OpenGL's program id.
Definition: shader.hpp:57
int loadTFBProgram(const std::string &vertex_file_path, const char **varyings, unsigned varyingscount)
Loads a transform feedback buffer shader with a given number of varying parameters.
Definition: shader.cpp:37
SharedShader getShaderFile(const std::string &file, unsigned type)
Get a shader file.
Definition: shader_files_manager.cpp:282
The main templated base class for all shaders that do not use textures.
Definition: shader.hpp:119
void printFileList(GLint shader_type, const char *filepath, Types ... args)
Variadic template to print a list of file names.
Definition: shader.hpp:287
void setUniformsImpl(float f, Args1... arg) const
Implementation for setUniforms for a float uniform.
Definition: shader.hpp:262
void bindPoint(const char *name, int index)
Finds the specified uniform block and assigns a binding point to it.
Definition: shader.hpp:124
void setUniformsImpl(const irr::core::vector3df &v, Args1... arg) const
Implementation for setUniforms for a vector3df uniform.
Definition: shader.hpp:235
void setUniformsImpl(const irr::core::vector2df &v, Args1... arg) const
Implementation for setUniforms for a vector2df uniform.
Definition: shader.hpp:244
void assignUniforms(U... rest)
This variadic template collects all names of uniforms in a std::vector.
Definition: shader.hpp:139
void setUniformsImpl() const
End of recursion for setUniforms implementation.
Definition: shader.hpp:191
void setUniformsImpl(const irr::core::matrix4 &mat, Args1... arg) const
Implementation for setUniforms for a matrix uniform.
Definition: shader.hpp:198
void setUniformsImpl(const irr::video::SColor &col, Args1... arg) const
Implementation for setUniforms for a SColor uniform.
Definition: shader.hpp:216
void assignTextureUnitNoUse(GLuint index, const char *uniform, T1... rest)
Recursive implementation of assignTextureUnit, but without the call to gluseProgram (which is done by...
Definition: shader.hpp:332
void setUniforms(const Args &... args) const
Sets the uniforms for this shader.
Definition: shader.hpp:173
void setUniformsImpl(const std::vector< float > &v, Args1... arg) const
Implementation for setUniforms for a vector<float> uniform.
Definition: shader.hpp:181
void assignUniformsImpl()
End of recursive implementation of assignUniforms.
Definition: shader.hpp:148
void setUniformsImpl(const std::array< float, 4 > &ff, Args1... arg) const
Implementation for setUniforms for a 4 floats uniform.
Definition: shader.hpp:226
void setUniformsImpl(const irr::core::dimension2df &v, Args1... arg) const
Implementation for setUniforms for a dimension2df uniform.
Definition: shader.hpp:253
void setUniformsImpl(const irr::video::SColorf &col, Args1... arg) const
Implementation for setUniforms for a matrix SColorF values.
Definition: shader.hpp:207
void setUniformsImpl(int f, Args1... arg) const
Implementation for setUniforms for an int uniform.
Definition: shader.hpp:271
Shader()
Constructor.
Definition: shader.hpp:347
void assignTextureUnit(GLuint index, const char *uniform, T1... rest)
Variadic top level/public interface.
Definition: shader.hpp:313
void assignUniformsImpl(const char *name, U... rest)
Recursive implementation of assignniforms.
Definition: shader.hpp:161
void assignTextureUnitNoUse()
End of recursion.
Definition: shader.hpp:326
void printFileList()
End recursion for variadic template.
Definition: shader.hpp:297
void loadProgram(AttributeType type, Types ... args)
Load a list of shaders and links them all together.
Definition: shader.hpp:356
Definition: singleton.hpp:87
static void kill()
Used to kill the singleton, if needed.
Definition: singleton.hpp:107
static ShaderFilesManager * getInstance()
Used to get the instance.
Definition: singleton.hpp:99