Gamedev Framework (gf)  0.3.0
A C++11 framework for 2D games
Texture.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_TEXTURE_H
25 #define GF_TEXTURE_H
26 
27 #include <cstdint>
28 
29 #include "Filesystem.h"
30 #include "Portability.h"
31 #include "Rect.h"
32 #include "Vector.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
39  class Image;
40  class InputStream;
41 
42  /**
43  * @ingroup graphics
44  * @brief An image that lives in the graphic memory that can be used for drawing
45  *
46  * gf::BareTexture stores pixels that can be drawn, with a sprite
47  * for example. A texture lives in the graphics card memory,
48  * therefore it is very fast to draw a texture to a render target,
49  * or copy a render target to a texture (the graphics card can
50  * access both directly).
51  *
52  * Being stored in the graphics card memory has some drawbacks.
53  * A texture cannot be manipulated as freely as a gf::Image,
54  * you need to prepare the pixels first and then upload them
55  * to the texture in a single operation (see BareTexture::update()).
56  *
57  * gf::BareTexture can handle two types of texture:
58  *
59  * - colored texture that stores RGBA channels (see gf::Texture)
60  * - alpha texture that stores a single alpha channel (see gf::FontTexture)
61  *
62  * Generally, you do not manipulated a gf::BareTexture directly but you can
63  * use a gf::Texture.
64  *
65  * @sa gf::Texture, gf::AlphaTexture
66  */
68  public:
69  /**
70  * @brief Format of the texture
71  *
72  * @sa gf::BareTexture
73  */
74  enum class Format {
75  Color, ///< RGBA format
76  Alpha, ///< Alpha format
77  };
78 
79  /**
80  * @brief Constructor
81  *
82  * @param format The format of the texture
83  *
84  * Once set, the format can not be changed.
85  */
86  BareTexture(Format format);
87 
88  /**
89  * @brief Destructor
90  */
91  ~BareTexture();
92 
93  /**
94  * @brief Deleted copy constructor
95  */
96  BareTexture(const BareTexture&) = delete;
97 
98  /**
99  * @brief Deleted copy assignment
100  */
101  BareTexture& operator=(const BareTexture&) = delete;
102 
103  /**
104  * @brief Move constructor
105  */
106  BareTexture(BareTexture&& other);
107 
108  /**
109  * @brief Move assignment
110  */
111  BareTexture& operator=(BareTexture&& other);
112 
113  /**
114  * @brief Get the format of the texture
115  *
116  * @return The format of the texture
117  */
118  Format getFormat() const {
119  return m_format;
120  }
121 
122  /**
123  * @brief Get the internal representation of the texture
124  *
125  * This function is for internal use only.
126  *
127  * @return The OpenGL name of the texture
128  */
129  unsigned getName() const {
130  return m_name;
131  }
132 
133  /**
134  * @brief Return the size of the texture
135  *
136  * @return Size in pixels
137  */
138  Vector2u getSize() const {
139  return m_size;
140  }
141 
142  /**
143  * @brief Enable or disable the smooth filter
144  *
145  * When the filter is activated, the texture appears smoother
146  * so that pixels are less noticeable. However if you want
147  * the texture to look exactly the same as its source file,
148  * you should leave it disabled.
149  *
150  * The smooth filter is disabled by default.
151  *
152  * @param smooth True to enable smoothing, false to disable it
153  *
154  * @see isSmooth()
155  */
156  void setSmooth(bool smooth = true);
157 
158  /**
159  * @brief Check if the smooth filter is enabled or not
160  *
161  * @return True if smoothing is enabled, false if it is disabled
162  *
163  * @see setSmooth()
164  */
165  bool isSmooth() const noexcept {
166  return m_smooth;
167  }
168 
169  /**
170  * @brief Enable or disable repeating
171  *
172  * Repeating is involved when using texture coordinates
173  * outside the texture rectangle @f$ [0, 1] @times [0, 1] @f$.
174  * In this case, if repeat mode is enabled, the whole texture
175  * will be repeated as many times as needed to reach the
176  * coordinate (for example, if the @f$ u @f$ texture coordinate is
177  * 3, the texture will be repeated 3 times).
178  *
179  * If repeat mode is disabled, the "extra space" will instead
180  * be filled with border pixels.
181  *
182  * Repeating is disabled by default.
183  *
184  * @param repeated True to repeat the texture, false to disable repeating
185  *
186  * @see isRepeated()
187  */
188  void setRepeated(bool repeated = true);
189 
190  /**
191  * @brief Check if the texture is repeated or not
192  *
193  * @return True if repeat mode is enabled, false if it is disabled
194  *
195  * @see setRepeated()
196  */
197  bool isRepeated() const noexcept {
198  return m_repeated;
199  }
200 
201  /**
202  * @brief Update the whole texture from an array of pixels
203  *
204  * The `data` array is assumed to be in the right format (4 channels
205  * for colored texture and 1 channel for alpha texture) and have the
206  * right size.
207  *
208  * No additional check is performed on the size of the pixel
209  * array, passing invalid arguments will lead to an undefined
210  * behavior.
211  *
212  * This function does nothing if `data` is `nullptr` or if the
213  * texture was not previously created.
214  *
215  * @param data An array of pixels to copy to the texture
216  */
217  void update(const uint8_t *data);
218 
219  /**
220  * @brief Update a part of the texture from an array of pixels
221  *
222  * The `data` array is assumed to be in the right format (4 channels
223  * for colored texture and 1 channel for alpha texture) and its size
224  * must match the size of the `rect` argument.
225  *
226  * No additional check is performed on the size of the pixel
227  * array or the bounds of the area to update, passing invalid
228  * arguments will lead to an undefined behavior.
229  *
230  * This function does nothing if `data` is `nullptr` or if the
231  * texture was not previously created.
232  *
233  * @param data An array of pixels to copy to the texture
234  * @param rect The region of the texture to update
235  */
236  void update(const uint8_t *data, const RectU& rect);
237 
238  /**
239  * @brief Compute normalized texture coordinates
240  *
241  * @param rect The rectangle in the texture, in pixels
242  * @return Normalized texture coordinates
243  */
244  RectF computeTextureCoords(const RectU& rect) const;
245 
246  /**
247  * @brief Generate a mipmap using the current texture data
248  *
249  * Mipmaps are pre-computed chains of optimized textures. Each
250  * level of texture in a mipmap is generated by halving each of
251  * the previous level's dimensions. This is done until the final
252  * level has the size of 1x1. The textures generated in this process may
253  * make use of more advanced filters which might improve the visual quality
254  * of textures when they are applied to objects much smaller than they are.
255  * This is known as minification. Because fewer texels (texture elements)
256  * have to be sampled from when heavily minified, usage of mipmaps
257  * can also improve rendering performance in certain scenarios.
258  *
259  * Mipmap data is only valid from the time it is generated until the next
260  * time the base level image is modified, at which point this function
261  * will have to be called again to regenerate it.
262  *
263  * @return True if mipmap generation was successful, false if unsuccessful
264  */
265  bool generateMipmap();
266 
267  /**
268  * @brief Bind a texture for rendering
269  *
270  * This function is for internal use only.
271  *
272  * @param texture Pointer to the texture to bind, can be `nullptr` to use no texture
273  */
274  static void bind(const BareTexture *texture);
275 
276  protected:
277  /**
278  * @brief Create the texture
279  *
280  * If this function fails, the texture is left unchanged.
281  *
282  * @param size Size of the texture
283  * @param data Initial pixels of the texture (can be `nullptr`)
284  *
285  * @return True if creation was successful
286  */
287  bool create(Vector2u size, const uint8_t *data);
288 
289  private:
290  Format m_format;
291  unsigned m_name;
292  Vector2u m_size;
293  bool m_smooth;
294  bool m_repeated;
295  bool m_mipmap;
296  };
297 
298 
299  /**
300  * @ingroup graphics
301  * @brief A texture for colored images
302  *
303  * A texture can be loaded from an image, but also directly
304  * from a file/memory/stream. The necessary shortcuts are defined
305  * so that you don't need an image first for the most common cases.
306  * However, if you want to perform some modifications on the pixels
307  * before creating the final texture, you can load your file to a
308  * gf::Image, do whatever you need with the pixels, and then call
309  * Texture::loadFromImage.
310  *
311  * Like gf::Image, gf::Texture can handle a unique internal
312  * representation of pixels, which is RGBA. This means
313  * that a pixel must be composed of 8 bits red, green, blue and
314  * alpha channels.
315  *
316  * Usage example:
317  *
318  * ~~~{.cc}
319  * // This example shows the most common use of gf::Texture:
320  * // drawing a sprite
321  *
322  * // Load a texture from a file
323  * gf::Texture texture;
324  *
325  * if (!texture.loadFromFile("texture.png")) {
326  * return -1;
327  * }
328  *
329  * // Assign it to a sprite
330  * gf::Sprite sprite;
331  * sprite.setTexture(texture);
332  *
333  * // Draw the textured sprite
334  * window.draw(sprite);
335  * ~~~
336  *
337  * @sa gf::Sprite, gf::Image, gf::RenderTexture
338  */
339  class GF_API Texture : public BareTexture {
340  public:
341  /**
342  * @brief Constructor
343  *
344  * No texture is created.
345  */
346  Texture();
347 
348  /**
349  * @brief Create the texture
350  *
351  * If this function fails, the texture is left unchanged.
352  *
353  * @param size Size of the texture
354  *
355  * @return True if creation was successful
356  */
357  bool create(Vector2u size);
358 
359  /**
360  * @brief Load the texture from an image
361  *
362  * If this function fails, the texture is left unchanged.
363  *
364  * @param image Image to load into the texture
365  *
366  * @return True if loading was successful
367  *
368  * @sa loadFromFile(), loadFromMemory(), loadFromStream()
369  */
370  bool loadFromImage(const Image& image);
371 
372  /**
373  * @brief Load the texture from a file on disk
374  *
375  * This function is a shortcut for the following code:
376  *
377  * ~~~{.cc}
378  * gf::Image image;
379  * image.loadFromFile(filename);
380  * texture.loadFromImage(image);
381  * ~~~
382  *
383  * If this function fails, the texture is left unchanged.
384  *
385  * @param filename Path of the image file to load
386  *
387  * @return True if loading was successful
388  *
389  * @sa loadFromMemory(), loadFromStream(), loadFromImage()
390  */
391  bool loadFromFile(const Path& filename);
392 
393  /**
394  * @brief Load the texture from a custom stream
395  *
396  * This function is a shortcut for the following code:
397  *
398  * ~~~{.cc}
399  * gf::Image image;
400  * image.loadFromStream(stream);
401  * texture.loadFromImage(image);
402  * ~~~
403  *
404  * If this function fails, the texture is left unchanged.
405  *
406  * @param stream Source stream to read from
407  * @return True if loading was successful
408  *
409  * @see loadFromFile(), loadFromMemory(), loadFromImage()
410  */
411  bool loadFromStream(InputStream& stream);
412 
413  /**
414  * @brief Load the texture from a file in memory
415  *
416  * This function is a shortcut for the following code:
417  *
418  * ~~~{.cc}
419  * gf::Image image;
420  * image.loadFromMemory(data, length);
421  * texture.loadFromImage(image);
422  * ~~~
423  *
424  * If this function fails, the texture is left unchanged.
425  *
426  * @param data Pointer to the file data in memory
427  * @param length Length of the data to load, in bytes
428  * @return True if loading was successful
429  *
430  * @see loadFromFile(), loadFromStream(), loadFromImage()
431  */
432  bool loadFromMemory(const uint8_t *data, std::size_t length);
433 
434  /**
435  * @brief Update the texture from an image
436  *
437  * Although the source image can be smaller than the texture,
438  * this function is usually used for updating the whole texture.
439  *
440  * No additional check is performed on the size of the image,
441  * passing an image bigger than the texture will lead to an
442  * undefined behavior.
443  *
444  * This function does nothing if the texture was not
445  * previously created.
446  *
447  * @param image Image to copy to the texture
448  */
449  void update(const Image& image);
450 
451  /**
452  * @brief Copy the texture pixels to an image
453  *
454  * This function performs a slow operation that downloads
455  * the texture's pixels from the graphics card and copies
456  * them to a new image, potentially applying transformations
457  * to pixels if necessary (texture may be padded or flipped).
458  *
459  * @return An image containing the texture's pixels
460  *
461  * @sa loadFromImage()
462  */
463  Image copyToImage() const;
464 
465  };
466 
467 
468  /**
469  * @ingroup graphics
470  * @brief A texture with a single alpha channel
471  *
472  * This texture is used internally by gf::Font
473  */
474  class GF_API AlphaTexture : public BareTexture {
475  public:
476  /**
477  * @brief Constructor
478  *
479  * No texture is created
480  */
481  AlphaTexture();
482 
483  /**
484  * @brief Create the texture
485  *
486  * If this function fails, the texture is left unchanged.
487  *
488  * @param size Size of the texture
489  *
490  * @return True if creation was successful
491  */
492  bool create(Vector2u size);
493  };
494 
495 #ifndef DOXYGEN_SHOULD_SKIP_THIS
496 }
497 #endif
498 }
499 
500 #endif // GF_TEXTURE_H
static void bind(const BareTexture *texture)
Bind a texture for rendering.
void update(const Image &image)
Update the texture from an image.
Vector2u getSize() const
Return the size of the texture.
Definition: Texture.h:138
BareTexture & operator=(const BareTexture &)=delete
Deleted copy assignment.
bool create(Vector2u size)
Create the texture.
void update(const uint8_t *data, const RectU &rect)
Update a part of the texture from an array of pixels.
bool loadFromFile(const Path &filename)
Load the texture from a file on disk.
bool create(Vector2u size)
Create the texture.
Image copyToImage() const
Copy the texture pixels to an image.
bool isRepeated() const noexcept
Check if the texture is repeated or not.
Definition: Texture.h:197
bool create(Vector2u size, const uint8_t *data)
Create the texture.
unsigned getName() const
Get the internal representation of the texture.
Definition: Texture.h:129
~BareTexture()
Destructor.
BareTexture & operator=(BareTexture &&other)
Move assignment.
bool loadFromImage(const Image &image)
Load the texture from an image.
A texture for colored images.
Definition: Texture.h:339
bool isSmooth() const noexcept
Check if the smooth filter is enabled or not.
Definition: Texture.h:165
BareTexture(BareTexture &&other)
Move constructor.
BareTexture(const BareTexture &)=delete
Deleted copy constructor.
void setSmooth(bool smooth=true)
Enable or disable the smooth filter.
Class for loading, manipulating and saving images.
Definition: Image.h:92
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(const uint8_t *data, std::size_t length)
Load the texture from a file in memory.
AlphaTexture()
Constructor.
BareTexture(Format format)
Constructor.
Format
Format of the texture.
Definition: Texture.h:74
Format getFormat() const
Get the format of the texture.
Definition: Texture.h:118
RectF computeTextureCoords(const RectU &rect) const
Compute normalized texture coordinates.
Texture()
Constructor.
bool loadFromStream(InputStream &stream)
Load the texture from a custom stream.
A texture with a single alpha channel.
Definition: Texture.h:474
#define GF_API
Definition: Portability.h:35
void update(const uint8_t *data)
Update the whole texture from an array of pixels.
bool generateMipmap()
Generate a mipmap using the current texture data.
void setRepeated(bool repeated=true)
Enable or disable repeating.