1 // Copyright 2013-2018 the openage authors. See copying.md for legal info.
2 
3 #pragma once
4 
5 #include <epoxy/gl.h>
6 #include <vector>
7 #include <memory>
8 
9 #include "gamedata/texture.gen.h"
10 #include "coord/pixel.h"
11 #include "coord/tile.h"
12 #include "shader/program.h"
13 #include "shader/shader.h"
14 #include "util/path.h"
15 
16 
17 namespace openage {
18 class Terrain;
19 
20 namespace util {
21 class Path;
22 }
23 
24 namespace coord {
25 class CoordManager;
26 }
27 
28 namespace texture_shader {
29 extern shader::Program *program;
30 extern GLint texture, tex_coord;
31 } // namespace texture_shader
32 
33 namespace teamcolor_shader {
34 extern shader::Program *program;
35 extern GLint texture, tex_coord;
36 extern GLint player_id_var, alpha_marker_var, player_color_var;
37 } // namespace teamcolor_shader
38 
39 namespace alphamask_shader {
40 extern shader::Program *program;
41 extern GLint base_texture, mask_texture, base_coord, mask_coord, show_mask;
42 } // namespace alphamask_shader
43 
44 // bitmasks for shader modes
45 constexpr int PLAYERCOLORED = 1 << 0;
46 constexpr int ALPHAMASKED   = 1 << 1;
47 
48 /**
49  * enables transfer of data to opengl
50  */
51 struct gl_texture_buffer {
52 	GLuint id, vertbuf;
53 
54 	// this requires loading on the main thread
55 	bool transferred;
56 	int texture_format_in;
57 	int texture_format_out;
58 	std::unique_ptr<uint32_t[]> data;
59 };
60 
61 
62 /**
63  * A texture for rendering graphically.
64  *
65  * You may believe it or not, but this class represents a single texture,
66  * which can be drawn on the screen.
67  *
68  * The class supports subtextures, so that one big texture can contain
69  * several small images. These are the ones actually to be rendered.
70  */
71 class Texture {
72 public:
73 	int w;
74 	int h;
75 
76 	/**
77 	 * Create a texture from a rgba8 array.
78 	 * It will have w * h * 32bit storage.
79 	 */
80 	Texture(int width, int height, std::unique_ptr<uint32_t[]> data);
81 
82 	/**
83 	 * Create a texture from a existing image file.
84 	 * For supported image file types, see the SDL_Image initialization in the engine.
85 	 */
86 	Texture(const util::Path &filename, bool use_metafile=false);
87 	~Texture();
88 
89 	/**
90 	 * Draws the texture at hud coordinates.
91 	 */
92 	void draw(const coord::CoordManager &mgr, coord::camhud pos, unsigned int mode=0, bool mirrored=false, int subid=0, unsigned player=0) const;
93 
94 	/**
95 	 * Draws the texture at game coordinates.
96 	 */
97 	void draw(const coord::CoordManager &mgr, coord::camgame pos, unsigned int mode=0, bool mirrored=false, int subid=0, unsigned player=0) const;
98 
99 	/**
100 	 * Draws the texture at phys coordinates.
101 	 */
102 	void draw(const coord::CoordManager &mgr, coord::phys3 pos, unsigned int mode=0,  bool mirrored=false, int subid=0, unsigned player=0) const;
103 
104 	/**
105 	 * Draws the texture at tile coordinates.
106 	 */
107 	void draw(const coord::CoordManager &mgr, const Terrain &terrain, coord::tile pos, unsigned int mode, int subid, Texture *alpha_texture, int alpha_subid) const;
108 
109 	/**
110 	 * Draws the texture at window coordinates.
111 	 */
112 	void draw(coord::viewport pos, unsigned int mode, bool mirrored, int subid, unsigned player, Texture *alpha_texture, int alpha_subid) const;
113 
114 	/**
115 	 * Reload the image file. Used for inotify refreshing.
116 	 */
117 	void reload();
118 
119 	/**
120 	 * Get the subtexture coordinates by its id.
121 	 */
122 	const gamedata::subtexture *get_subtexture(uint64_t subid) const;
123 
124 	/**
125 	 * @return the number of available subtextures
126 	 */
127 	size_t get_subtexture_count() const;
128 
129 	/**
130 	 * Fetch the size of the given subtexture.
131 	 * @param subid: index of the requested subtexture
132 	 * @param w: the subtexture width
133 	 * @param h: the subtexture height
134 	 */
135 	void get_subtexture_size(uint64_t subid, int *w, int *h) const;
136 
137 	/**
138 	 * get atlas subtexture coordinates.
139 	 *
140 	 * left, right, top and bottom bounds as coordinates
141 	 * these pick the requested area out of the big texture.
142 	 * returned as floats in range 0.0 to 1.0
143 	 */
144 	void get_subtexture_coordinates(uint64_t subid, float *txl, float *txr, float *txt, float *txb) const;
145 	void get_subtexture_coordinates(const gamedata::subtexture *subtex, float *txl, float *txr, float *txt, float *txb) const;
146 
147 	/**
148 	 * fixes the hotspots of all subtextures to (x,y).
149 	 * this is a temporary workaround; such fixes should actually be done in the
150 	 * convert script.
151 	 */
152 	void fix_hotspots(unsigned x, unsigned y);
153 
154 	/**
155 	 * activates the influence of a given alpha mask to this texture.
156 	 */
157 	void activate_alphamask(Texture *mask, uint64_t subid);
158 
159 	/**
160 	 * disable a previously activated alpha mask.
161 	 */
162 	void disable_alphamask();
163 
164 	/**
165 	 * returns the opengl texture id of this texture.
166 	 */
167 	GLuint get_texture_id() const;
168 
169 private:
170 	std::unique_ptr<gl_texture_buffer> buffer;
171 	std::vector<gamedata::subtexture> subtextures;
172 	bool use_metafile;
173 
174 	util::Path filename;
175 
176 	void load();
177 
178 	/**
179 	 * The texture loadin must occur on the thread that manages the gl context.
180 	 */
181 	void load_in_glthread() const;
182 	GLuint make_gl_texture(int iformat, int oformat, int w, int h, void *) const;
183 	void unload();
184 
185 };
186 
187 } // namespace openage
188