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