Gamedev Framework (gf)  0.1.0
A C++11 framework for 2D games
Shader.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * Part of this file comes from SFML, with the same license:
22  * Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
23  */
24 #ifndef GF_SHADER_H
25 #define GF_SHADER_H
26 
27 #include <string>
28 #include <map>
29 
30 #include "Filesystem.h"
31 #include "Matrix.h"
32 #include "Portability.h"
33 #include "Texture.h"
34 #include "Vector.h"
35 
36 namespace gf {
37 #ifndef DOXYGEN_SHOULD_SKIP_THIS
38 inline namespace v1 {
39 #endif
40 
41  class InputStream;
42 
43  /**
44  * @ingroup graphics
45  * @brief An OpenGL vertex and/or fragment shader
46  *
47  * Shaders are programs written using a specific language,
48  * executed directly by the graphics card and allowing
49  * to apply real-time operations to the rendered entities.
50  *
51  * There are two kinds of shaders:
52  *
53  * - vertex shaders, that process vertices
54  * - fragment (or pixel) shaders, that process pixels
55  *
56  * A gf::Shader can be composed of either a vertex shader
57  * alone, a geometry shader alone, a fragment shader alone,
58  * or any combination of them. (see the variants of the
59  * load functions).
60  *
61  * Shaders are written in GLSL, which is a C-like
62  * language dedicated to OpenGL shaders. You'll probably
63  * need to learn its basics before writing your own shaders
64  * for gf. See also @ref shader.
65  *
66  * Like any C/C++ program, a GLSL shader has its own variables
67  * called _uniforms_ that you can set from your C++ application.
68  * gf::Shader handles different types of uniforms:
69  *
70  * - scalars: `float`, `int`
71  * - vectors (2, 3 or 4 components)
72  * - matrices (3x3 or 4x4)
73  * - samplers (textures)
74  *
75  * Every uniform variable in a shader can be set through one of the
76  * setUniform() overloads. For example, if you have a shader with the
77  * following uniforms:
78  *
79  * ~~~
80  * uniform float offset;
81  * uniform vec3 point;
82  * uniform vec4 color;
83  * uniform mat3 matrix;
84  * uniform sampler2D overlay;
85  * ~~~
86  *
87  * You can set their values from C++ code as follows:
88  *
89  * ~~~
90  * shader.setUniform("offset", 2.0f);
91  * shader.setUniform("point", gf::Vector3f(0.5f, 0.8f, 0.3f));
92  * shader.setUniform("color", color); // color is a gf::Color4f
93  * shader.setUniform("matrix", trans); // trans is a gf::Matrix3f
94  * shader.setUniform("overlay", texture); // texture is a gf::Texture
95  * ~~~
96  *
97  * To apply a shader to a drawable, you must pass it as part of the
98  * gf::RenderStates in the call to @ref RenderTarget::draw() function:
99  *
100  * ~~~{.cc}
101  * gf::RenderStates states;
102  * states.shader = &shader;
103  * renderer.draw(sprite, states);
104  * ~~~
105  *
106  * In the code above we pass a pointer to the shader, because it may
107  * be null (which means "default shader").
108  *
109  * Shaders can be used on any drawable, but some combinations are
110  * not interesting. For example, using a vertex shader on a gf::Sprite
111  * is limited because there are only 4 vertices, the sprite would
112  * have to be subdivided in order to apply wave effects.
113  * Another bad example is a fragment shader with gf::Text: the texture
114  * of the text is not the actual text that you see on screen, it is
115  * a big texture containing all the characters of the font in an
116  * arbitrary order; thus, texture lookups on pixels other than the
117  * current one may not give you the expected result.
118  */
119  class GF_API Shader {
120  public:
121  /**
122  * @brief Type of shaders
123  */
124  enum Type {
125  Vertex, ///< Type for a vertex shader
126  Fragment, ///< Type for a fragment (or pixel) shader
127  };
128 
129  /**
130  * @brief Default constructor
131  *
132  * This constructor creates an invalid shader.
133  */
134  Shader();
135 
136  /**
137  * @brief Destructor
138  */
139  ~Shader();
140 
141  /**
142  * @brief Deleted copy constructor
143  */
144  Shader(const Shader&) = delete;
145 
146  /**
147  * @brief Deleted copy assignment
148  */
149  Shader& operator=(const Shader&) = delete;
150 
151  /**
152  * @name Loading
153  * @{
154  */
155 
156  /**
157  * @brief Load the vertex of fragment shader from a file
158  *
159  * This function loads a single shader, vertex or
160  * fragment, identified by the second argument.
161  *
162  * The source must be a text file containing a valid
163  * shader in GLSL language. GLSL is a C-like language
164  * dedicated to OpenGL shaders; you'll probably need to
165  * read a good documentation for it before writing your
166  * own shaders.
167  *
168  * @param filename Path of the vertex or fragment shader file to load
169  * @param type Type of shader (vertex or fragment)
170  *
171  * @return True if loading succeeded, false if it failed
172  *
173  * @sa loadFromMemory(), loadFromStream()
174  */
175  bool loadFromFile(const Path& filename, Type type);
176 
177  /**
178  * @brief Load both the vertex and fragment shaders from files
179  *
180  * This function loads both the vertex and the fragment
181  * shaders. If one of them fails to load, the shader is left
182  * empty (the valid shader is unloaded).
183  *
184  * The sources must be a text files containing a valid
185  * shader in GLSL language. GLSL is a C-like language
186  * dedicated to OpenGL shaders; you'll probably need to
187  * read a good documentation for it before writing your
188  * own shaders.
189  *
190  * @param vertexShaderFilename Path of the vertex shader file to load
191  * @param fragmentShaderFilename Path of the fragment shader file to load
192  *
193  * @return True if loading succeeded, false if it failed
194  *
195  * @sa loadFromMemory(), loadFromStream()
196  */
197  bool loadFromFile(const Path& vertexShaderFilename, const Path& fragmentShaderFilename);
198 
199  /**
200  * @brief Load the vertex or fragment shader from a source code in memory
201  *
202  * This function loads a single shader, vertex
203  * or fragment, identified by the second argument.
204  *
205  * The source code must be a valid shader in GLSL language.
206  * GLSL is a C-like language dedicated to OpenGL shaders;
207  * you'll probably need to read a good documentation for
208  * it before writing your own shaders.
209  *
210  * @param shader String containing the source code of the shader
211  * @param type Type of shader (vertex or fragment)
212  *
213  * @return True if loading succeeded, false if it failed
214  *
215  * @sa loadFromFile(), loadFromStream()
216  */
217  bool loadFromMemory(const std::string& shader, Type type);
218 
219  /**
220  * @brief Load both the vertex and fragment shaders from source codes
221  * in memory
222  *
223  * This function loads both the vertex and the fragment
224  * shaders. If one of them fails to load, the shader is left
225  * empty (the valid shader is unloaded).
226  *
227  * The source codes must be a valid shaders in GLSL language.
228  * GLSL is a C-like language dedicated to OpenGL shaders;
229  * you'll probably need to read a good documentation for
230  * it before writing your own shaders.
231  *
232  * @param vertexShader String containing the source code of the vertex shader
233  * @param fragmentShader String containing the source code of the fragment shader
234  *
235  * @return True if loading succeeded, false if it failed
236  *
237  * @sa loadFromFile(), loadFromStream()
238  */
239  bool loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader);
240 
241 
242  /**
243  * @brief Load the vertex or fragment shader from a custom stream
244  *
245  * This function loads a single shader, vertex
246  * or fragment, identified by the second argument.
247  *
248  * The source code must be a valid shader in GLSL language.
249  * GLSL is a C-like language dedicated to OpenGL shaders;
250  * you'll probably need to read a good documentation for it
251  * before writing your own shaders.
252  *
253  * @param stream Source stream to read from
254  * @param type Type of shader (vertex, geometry or fragment)
255  *
256  * @return True if loading succeeded, false if it failed
257  *
258  * @sa loadFromFile(), loadFromMemory()
259  */
260  bool loadFromStream(InputStream& stream, Type type);
261 
262  /**
263  * @brief Load both the vertex and fragment shaders from custom streams
264  *
265  * This function loads both the vertex and the fragment
266  * shaders. If one of them fails to load, the shader is left
267  * empty (the valid shader is unloaded).
268  *
269  * The source codes must be valid shaders in GLSL language.
270  * GLSL is a C-like language dedicated to OpenGL shaders;
271  * you'll probably need to read a good documentation for
272  * it before writing your own shaders.
273  *
274  * @param vertexShaderStream Source stream to read the vertex shader from
275  * @param fragmentShaderStream Source stream to read the fragment shader from
276  *
277  * @return True if loading succeeded, false if it failed
278  *
279  * @sa loadFromFile(), loadFromMemory()
280  */
281  bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream);
282 
283  /** @} */
284 
285  /**
286  * @name Uniform setting
287  * @{
288  */
289 
290  /**
291  * @brief Specify value for a `float` uniform
292  *
293  * @param name Name of the uniform variable in GLSL
294  * @param val Value of the `float` scalar
295  */
296  void setUniform(const std::string& name, float val);
297 
298  /**
299  * @brief Specify value for a `int` uniform
300  *
301  * @param name Name of the uniform variable in GLSL
302  * @param val Value of the `int` scalar
303  */
304  void setUniform(const std::string& name, int val);
305 
306  /**
307  * @brief Specify value for a `vec2` uniform
308  *
309  * @param name Name of the uniform variable in GLSL
310  * @param vec Value of the `vec2` vector
311  */
312  void setUniform(const std::string& name, const Vector2f& vec);
313 
314  /**
315  * @brief Specify value for a `vec3` uniform
316  *
317  * @param name Name of the uniform variable in GLSL
318  * @param vec Value of the `vec3` vector
319  */
320  void setUniform(const std::string& name, const Vector3f& vec);
321 
322  /**
323  * @brief Specify value for a `vec4` uniform
324  *
325  * @param name Name of the uniform variable in GLSL
326  * @param vec Value of the `vec4` vector
327  */
328  void setUniform(const std::string& name, const Vector4f& vec);
329 
330  /**
331  * @brief Specify value for a `mat3` uniform
332  *
333  * @param name Name of the uniform variable in GLSL
334  * @param mat Value of the `mat3` matrix
335  */
336  void setUniform(const std::string& name, const Matrix3f& mat);
337 
338  /**
339  * @brief Specify value for a `mat4` uniform
340  *
341  * @param name Name of the uniform variable in GLSL
342  * @param mat Value of the `mat4` matrix
343  */
344  void setUniform(const std::string& name, const Matrix4f& mat);
345 
346  /**
347  * @brief Specify a texture for a `sampler2D` uniform
348  *
349  * The corresponding parameter in the shader must be a 2D texture,
350  * i.e. a `sampler2D` GLSL type.
351  *
352  * In the shader code:
353  *
354  * ~~~
355  * uniform sampler2D the_texture; // this is the variable in the shader
356  * ~~~
357  *
358  * In the source code:
359  *
360  * ~~~{.cc}
361  * gf::Texture texture;
362  *
363  * shader.setUniform("the_texture", texture);
364  * ~~~
365  *
366  * It is important to note that the texture must remain alive as long
367  * as the shader uses it, no copy is made internally.
368  *
369  * @param name Name of the uniform variable in GLSL
370  * @param tex Value of the `sampler2D` texture
371  */
372  void setUniform(const std::string& name, const BareTexture& tex);
373 
374  /** @} */
375 
376  /**
377  * @brief Bind a shader for rendering
378  *
379  * This function is for internal use only.
380  *
381  * @param shader Shader to bind, can be null to use no shader
382  */
383 
384  static void bind(const Shader *shader);
385 
386  private:
387  friend class RenderTarget;
388  bool compile(const char *vertexShaderCode, const char *fragmentShaderCode);
389  int getUniformLocation(const std::string& name);
390  int getAttributeLocation(const std::string& name);
391 
392  struct Guard;
393 
394  private:
395  unsigned m_program;
396 
397  std::map<int, const BareTexture *> m_textures;
398  };
399 
400 #ifndef DOXYGEN_SHOULD_SKIP_THIS
401 }
402 #endif
403 }
404 
405 #endif // GF_SHADER_H
~Shader()
Destructor.
Vector< float, 2 > Vector2f
A float vector with 2 components.
Definition: Vector.h:741
bool loadFromFile(const Path &filename, Type type)
Load the vertex of fragment shader from a file.
friend class RenderTarget
Definition: Shader.h:387
Shader(const Shader &)=delete
Deleted copy constructor.
bool loadFromFile(const Path &vertexShaderFilename, const Path &fragmentShaderFilename)
Load both the vertex and fragment shaders from files.
Matrix< float, 3, 3 > Matrix3f
A float square matrix of size 3.
Definition: Matrix.h:326
bool loadFromStream(InputStream &vertexShaderStream, InputStream &fragmentShaderStream)
Load both the vertex and fragment shaders from custom streams.
An OpenGL vertex and/or fragment shader.
Definition: Shader.h:119
void setUniform(const std::string &name, float val)
Specify value for a float uniform.
bool loadFromStream(InputStream &stream, Type type)
Load the vertex or fragment shader from a custom stream.
static void bind(const Shader *shader)
Bind a shader for rendering.
Definition: Action.h:34
An image that lives in the graphic memory that can be used for drawing.
Definition: Texture.h:67
Abstract class for custom file input streams.
Definition: InputStream.h:51
void setUniform(const std::string &name, const BareTexture &tex)
Specify a texture for a sampler2D uniform.
void setUniform(const std::string &name, const Vector4f &vec)
Specify value for a vec4 uniform.
Type for a fragment (or pixel) shader.
Definition: Shader.h:126
Shader()
Default constructor.
void setUniform(const std::string &name, const Matrix4f &mat)
Specify value for a mat4 uniform.
Vector< float, 4 > Vector4f
A float vector with 4 components.
Definition: Vector.h:753
Matrix< float, 4, 4 > Matrix4f
A float square matrix of size 4.
Definition: Matrix.h:334
Shader & operator=(const Shader &)=delete
Deleted copy assignment.
bool loadFromMemory(const std::string &shader, Type type)
Load the vertex or fragment shader from a source code in memory.
#define GF_API
Definition: Portability.h:35
Type for a vertex shader.
Definition: Shader.h:125
Vector< float, 3 > Vector3f
A float vector with 3 components.
Definition: Vector.h:747
void setUniform(const std::string &name, int val)
Specify value for a int uniform.
Type
Type of shaders.
Definition: Shader.h:124
bool loadFromMemory(const std::string &vertexShader, const std::string &fragmentShader)
Load both the vertex and fragment shaders from source codes in memory.