rev |
line source |
nuclear@9
|
1 #include <math.h>
|
nuclear@0
|
2 #include "texture.h"
|
nuclear@0
|
3 #include "image.h"
|
nuclear@0
|
4 #include "opengl.h"
|
nuclear@0
|
5 #include "imago2.h"
|
nuclear@0
|
6 #include "logger.h"
|
nuclear@0
|
7 #include "datapath.h"
|
nuclear@0
|
8
|
nuclear@15
|
9 using namespace goatgfx;
|
nuclear@15
|
10
|
nuclear@0
|
11 static int glifmt_from_ifmt(unsigned int ifmt);
|
nuclear@0
|
12 static int glfmt_from_ifmt(unsigned int ifmt);
|
nuclear@0
|
13 static int gltype_from_ifmt(unsigned int ifmt);
|
nuclear@0
|
14
|
nuclear@0
|
15 static int glifmt_from_imgfmt(Image::Format fmt);
|
nuclear@0
|
16
|
nuclear@24
|
17 static unsigned int type_to_target(TextureType type);
|
nuclear@24
|
18 static TextureType target_to_type(unsigned int targ);
|
nuclear@24
|
19
|
nuclear@0
|
20 static unsigned int cur_target[8] = {
|
nuclear@0
|
21 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
|
nuclear@0
|
22 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
|
nuclear@0
|
23 };
|
nuclear@0
|
24
|
nuclear@24
|
25 static unsigned int cube_faces[] = {
|
nuclear@24
|
26 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
nuclear@24
|
27 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
nuclear@24
|
28 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
nuclear@24
|
29 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
nuclear@24
|
30 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
nuclear@24
|
31 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
|
nuclear@24
|
32 };
|
nuclear@15
|
33
|
nuclear@24
|
34
|
nuclear@24
|
35 void goatgfx::bind_texture(Texture *tex, int tunit)
|
nuclear@0
|
36 {
|
nuclear@0
|
37 if(tex) {
|
nuclear@0
|
38 tex->bind(tunit);
|
nuclear@0
|
39 } else {
|
nuclear@0
|
40 glActiveTexture(GL_TEXTURE0 + tunit);
|
nuclear@0
|
41 glBindTexture(cur_target[tunit], 0);
|
nuclear@0
|
42 glActiveTexture(GL_TEXTURE0);
|
nuclear@0
|
43 }
|
nuclear@0
|
44 }
|
nuclear@0
|
45
|
nuclear@33
|
46
|
nuclear@33
|
47 Image *Texture::default_img;
|
nuclear@33
|
48
|
nuclear@0
|
49 Texture::Texture()
|
nuclear@0
|
50 {
|
nuclear@0
|
51 target = 0;
|
nuclear@0
|
52 sz[0] = sz[1] = sz[2] = 0;
|
nuclear@0
|
53 texfmt = 0;
|
nuclear@0
|
54
|
nuclear@24
|
55 img = 0;
|
nuclear@0
|
56 glGenTextures(1, &id);
|
nuclear@0
|
57 }
|
nuclear@0
|
58
|
nuclear@0
|
59 Texture::~Texture()
|
nuclear@0
|
60 {
|
nuclear@0
|
61 if(id) {
|
nuclear@0
|
62 glDeleteTextures(1, &id);
|
nuclear@0
|
63 }
|
nuclear@24
|
64 if(img) {
|
nuclear@24
|
65 delete img;
|
nuclear@24
|
66 }
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 void Texture::set_wrapping(unsigned int wrap)
|
nuclear@0
|
70 {
|
nuclear@0
|
71 if(!target) {
|
nuclear@0
|
72 return;
|
nuclear@0
|
73 }
|
nuclear@0
|
74
|
nuclear@0
|
75 glBindTexture(target, id);
|
nuclear@0
|
76 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
|
nuclear@0
|
77 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
|
nuclear@24
|
78 glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap);
|
nuclear@0
|
79 }
|
nuclear@0
|
80
|
nuclear@0
|
81 void Texture::set_filtering(unsigned int filt)
|
nuclear@0
|
82 {
|
nuclear@0
|
83 unsigned int mag_filter;
|
nuclear@0
|
84
|
nuclear@0
|
85 if(!target) {
|
nuclear@0
|
86 return;
|
nuclear@0
|
87 }
|
nuclear@0
|
88
|
nuclear@0
|
89 switch(filt) {
|
nuclear@0
|
90 case GL_LINEAR_MIPMAP_NEAREST:
|
nuclear@0
|
91 case GL_LINEAR_MIPMAP_LINEAR:
|
nuclear@0
|
92 mag_filter = GL_LINEAR;
|
nuclear@0
|
93 break;
|
nuclear@0
|
94
|
nuclear@0
|
95 case GL_NEAREST_MIPMAP_NEAREST:
|
nuclear@0
|
96 case GL_NEAREST_MIPMAP_LINEAR:
|
nuclear@0
|
97 mag_filter = GL_NEAREST;
|
nuclear@0
|
98 break;
|
nuclear@0
|
99
|
nuclear@0
|
100 default:
|
nuclear@0
|
101 mag_filter = filt;
|
nuclear@0
|
102 }
|
nuclear@0
|
103
|
nuclear@0
|
104 set_filtering(filt, mag_filter);
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt)
|
nuclear@0
|
108 {
|
nuclear@0
|
109 glBindTexture(target, id);
|
nuclear@0
|
110 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt);
|
nuclear@0
|
111 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt);
|
nuclear@0
|
112 }
|
nuclear@0
|
113
|
nuclear@0
|
114 unsigned int Texture::get_format() const
|
nuclear@0
|
115 {
|
nuclear@0
|
116 return texfmt;
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 int Texture::get_size(int dim) const
|
nuclear@0
|
120 {
|
nuclear@0
|
121 if(dim < 0 || dim >= 3) {
|
nuclear@0
|
122 return 0;
|
nuclear@0
|
123 }
|
nuclear@0
|
124 return sz[dim];
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 unsigned int Texture::get_id() const
|
nuclear@0
|
128 {
|
nuclear@0
|
129 return id;
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@24
|
132 TextureType Texture::get_type() const
|
nuclear@24
|
133 {
|
nuclear@24
|
134 return target_to_type(target);
|
nuclear@24
|
135 }
|
nuclear@24
|
136
|
nuclear@0
|
137 void Texture::bind(int tex_unit) const
|
nuclear@0
|
138 {
|
nuclear@0
|
139 glActiveTexture(GL_TEXTURE0 + tex_unit);
|
nuclear@0
|
140 glBindTexture(target, id);
|
nuclear@0
|
141 glActiveTexture(GL_TEXTURE0);
|
nuclear@0
|
142
|
nuclear@0
|
143 cur_target[tex_unit] = target;
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146
|
nuclear@24
|
147 void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
|
nuclear@24
|
148 {
|
nuclear@24
|
149 if(textype == TEX_CUBE && xsz != ysz) {
|
nuclear@24
|
150 error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
|
nuclear@24
|
151 return;
|
nuclear@24
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 int fmt = glfmt_from_ifmt(ifmt);
|
nuclear@0
|
155 int type = gltype_from_ifmt(ifmt);
|
nuclear@0
|
156
|
nuclear@24
|
157 target = type_to_target(textype);
|
nuclear@24
|
158
|
nuclear@24
|
159 glBindTexture(target, id);
|
nuclear@24
|
160 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@24
|
161 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@24
|
162
|
nuclear@24
|
163 switch(type) {
|
nuclear@24
|
164 case TEX_2D:
|
nuclear@24
|
165 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
|
nuclear@24
|
166 break;
|
nuclear@24
|
167
|
nuclear@24
|
168 case TEX_CUBE:
|
nuclear@24
|
169 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
nuclear@24
|
170 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
nuclear@24
|
171 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
nuclear@24
|
172 for(int i=0; i<6; i++) {
|
nuclear@24
|
173 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
nuclear@24
|
174 }
|
nuclear@24
|
175 break;
|
nuclear@24
|
176 }
|
nuclear@24
|
177
|
nuclear@0
|
178 CHECKGLERR;
|
nuclear@0
|
179 sz[0] = xsz;
|
nuclear@0
|
180 sz[1] = ysz;
|
nuclear@0
|
181 texfmt = ifmt;
|
nuclear@0
|
182 }
|
nuclear@0
|
183
|
nuclear@33
|
184 #define DEF_IMAGE_SIZE 64
|
nuclear@33
|
185 void Texture::create_default(TextureType type)
|
nuclear@33
|
186 {
|
nuclear@33
|
187 if(!default_img) {
|
nuclear@33
|
188 default_img = new Image;
|
nuclear@33
|
189 default_img->create(DEF_IMAGE_SIZE, DEF_IMAGE_SIZE, Image::FMT_RGBA);
|
nuclear@33
|
190
|
nuclear@33
|
191 unsigned char *pixels = (unsigned char*)default_img->get_pixels();
|
nuclear@33
|
192 for(int i=0; i<DEF_IMAGE_SIZE; i++) {
|
nuclear@33
|
193 for(int j=0; j<DEF_IMAGE_SIZE; j++) {
|
nuclear@33
|
194 bool chess = ((i >> 3) & 1) == ((j >> 3) & 1);
|
nuclear@33
|
195 pixels[0] = chess ? 255 : 32;
|
nuclear@33
|
196 pixels[1] = 64;
|
nuclear@33
|
197 pixels[2] = chess ? 32 : 255;
|
nuclear@33
|
198 pixels[3] = 255;
|
nuclear@33
|
199 }
|
nuclear@33
|
200 }
|
nuclear@33
|
201 }
|
nuclear@33
|
202
|
nuclear@33
|
203 switch(type) {
|
nuclear@33
|
204 case TEX_2D:
|
nuclear@33
|
205 set_image(*default_img);
|
nuclear@33
|
206 break;
|
nuclear@33
|
207
|
nuclear@33
|
208 case TEX_CUBE:
|
nuclear@33
|
209 for(int i=0; i<6; i++) {
|
nuclear@33
|
210 set_image(*default_img, i);
|
nuclear@33
|
211 }
|
nuclear@33
|
212 break;
|
nuclear@33
|
213 }
|
nuclear@33
|
214 }
|
nuclear@33
|
215
|
nuclear@24
|
216 void Texture::set_image(const Image &img, int idx)
|
nuclear@24
|
217 {
|
nuclear@24
|
218 if(idx >= 0 && idx < 6) {
|
nuclear@24
|
219 set_image_cube(img, idx);
|
nuclear@24
|
220 } else {
|
nuclear@24
|
221 if(!set_image_cube(img)) {
|
nuclear@24
|
222 set_image_2d(img);
|
nuclear@24
|
223 }
|
nuclear@24
|
224 }
|
nuclear@24
|
225 }
|
nuclear@24
|
226
|
nuclear@24
|
227 void Texture::set_image_2d(const Image &img)
|
nuclear@0
|
228 {
|
nuclear@0
|
229 texfmt = glifmt_from_imgfmt(img.get_format());
|
nuclear@0
|
230 unsigned int fmt = glfmt_from_ifmt(texfmt);
|
nuclear@0
|
231 unsigned int type = gltype_from_ifmt(texfmt);
|
nuclear@0
|
232
|
nuclear@0
|
233 sz[0] = img.get_width();
|
nuclear@0
|
234 sz[1] = img.get_height();
|
nuclear@0
|
235
|
nuclear@0
|
236 glBindTexture(GL_TEXTURE_2D, id);
|
nuclear@0
|
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
nuclear@0
|
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@0
|
239 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
nuclear@0
|
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
nuclear@0
|
241
|
nuclear@0
|
242 #ifdef __GLEW_H__
|
nuclear@0
|
243 if(GLEW_SGIS_generate_mipmap) {
|
nuclear@0
|
244 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
nuclear@0
|
245 #endif
|
nuclear@0
|
246 glTexImage2D(GL_TEXTURE_2D, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
|
nuclear@0
|
247 #ifdef __GLEW_H__
|
nuclear@0
|
248 } else {
|
nuclear@0
|
249 gluBuild2DMipmaps(GL_TEXTURE_2D, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
|
nuclear@0
|
250 }
|
nuclear@0
|
251 #endif
|
nuclear@0
|
252
|
nuclear@0
|
253 #ifdef GL_ES_VERSION_2_0
|
nuclear@0
|
254 glGenerateMipmap(GL_TEXTURE_2D);
|
nuclear@0
|
255 #endif
|
nuclear@0
|
256 }
|
nuclear@0
|
257
|
nuclear@24
|
258 bool Texture::set_image_cube(const Image &img, int idx)
|
nuclear@0
|
259 {
|
nuclear@24
|
260 if(idx < 0 || idx >= 6) {
|
nuclear@0
|
261 return false;
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@6
|
264 texfmt = glifmt_from_imgfmt(img.get_format());
|
nuclear@6
|
265 unsigned int fmt = glfmt_from_ifmt(texfmt);
|
nuclear@6
|
266 unsigned int type = gltype_from_ifmt(texfmt);
|
nuclear@6
|
267
|
nuclear@6
|
268 sz[0] = img.get_width();
|
nuclear@6
|
269 sz[1] = img.get_height();
|
nuclear@6
|
270
|
nuclear@6
|
271 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
nuclear@6
|
272 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@6
|
273 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@6
|
274 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
nuclear@6
|
275 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
nuclear@9
|
276 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
nuclear@6
|
277
|
nuclear@6
|
278 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
|
nuclear@24
|
279 return true;
|
nuclear@0
|
280 }
|
nuclear@0
|
281
|
nuclear@24
|
282 bool Texture::set_image_cube(const Image &img)
|
nuclear@0
|
283 {
|
nuclear@6
|
284 static const float one_third = 1.0 / 3.0;
|
nuclear@6
|
285 static const float two_thirds = 2.0 / 3.0;
|
nuclear@6
|
286 static const float hcross[2][6] = {
|
nuclear@6
|
287 {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} };
|
nuclear@6
|
288 static const float vcross[2][6] = {
|
nuclear@6
|
289 {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} };
|
nuclear@6
|
290 static const float hsix[2][6] = {
|
nuclear@6
|
291 {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} };
|
nuclear@6
|
292
|
nuclear@6
|
293 int xsz = img.get_width();
|
nuclear@6
|
294 int ysz = img.get_height();
|
nuclear@6
|
295
|
nuclear@6
|
296 if(xsz / 4 == ysz / 3) {
|
nuclear@6
|
297 // horizontal cross, assume the vertical bit is center-left
|
nuclear@24
|
298 return set_cube_multi(img, hcross[0], hcross[1], xsz / 4);
|
nuclear@6
|
299 }
|
nuclear@6
|
300 if(xsz / 3 == ysz / 4) {
|
nuclear@6
|
301 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5)
|
nuclear@24
|
302 return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
|
nuclear@6
|
303 }
|
nuclear@6
|
304 if(xsz / 3 == ysz / 2) {
|
nuclear@6
|
305 // horizontal sixpack
|
nuclear@24
|
306 return set_cube_multi(img, hsix[0], hsix[1], ysz / 2);
|
nuclear@6
|
307 }
|
nuclear@6
|
308
|
nuclear@6
|
309 return false;
|
nuclear@0
|
310 }
|
nuclear@0
|
311
|
nuclear@24
|
312
|
nuclear@24
|
313 bool Texture::load(const char *fname)
|
nuclear@0
|
314 {
|
nuclear@24
|
315 Image img;
|
nuclear@24
|
316 if(!img.load(fname)) {
|
nuclear@24
|
317 error_log("failed to load 2D texture: %s\n", fname);
|
nuclear@24
|
318 return false;
|
nuclear@24
|
319 }
|
nuclear@24
|
320 set_image(img);
|
nuclear@24
|
321
|
nuclear@24
|
322 info_log("loaded 2D texture: %s\n", fname);
|
nuclear@24
|
323 return true;
|
nuclear@0
|
324 }
|
nuclear@0
|
325
|
nuclear@24
|
326 bool Texture::load_cube(const char *fname)
|
nuclear@24
|
327 {
|
nuclear@24
|
328 Image img;
|
nuclear@24
|
329 if(!img.load(fname)) {
|
nuclear@24
|
330 return false;
|
nuclear@24
|
331 }
|
nuclear@24
|
332 return set_image_cube(img);
|
nuclear@24
|
333 }
|
nuclear@24
|
334
|
nuclear@24
|
335 bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
|
nuclear@6
|
336 unsigned int rotmask)
|
nuclear@6
|
337 {
|
nuclear@6
|
338 for(int i=0; i<6; i++) {
|
nuclear@6
|
339 Image face;
|
nuclear@6
|
340
|
nuclear@6
|
341 int xoffs = xoffsets[i] * img.get_width();
|
nuclear@6
|
342 int yoffs = yoffsets[i] * img.get_height();
|
nuclear@6
|
343
|
nuclear@6
|
344 if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) {
|
nuclear@6
|
345 return false;
|
nuclear@6
|
346 }
|
nuclear@6
|
347
|
nuclear@6
|
348 if(rotmask & (1 << i)) {
|
nuclear@6
|
349 face.rotate_180();
|
nuclear@6
|
350 }
|
nuclear@24
|
351 set_image_cube(face, i);
|
nuclear@6
|
352 }
|
nuclear@6
|
353 return true;
|
nuclear@6
|
354 }
|
nuclear@6
|
355
|
nuclear@0
|
356 static int glifmt_from_ifmt(unsigned int ifmt)
|
nuclear@0
|
357 {
|
nuclear@0
|
358 #ifdef GL_ES_VERSION_2_0
|
nuclear@0
|
359 switch(ifmt) {
|
nuclear@0
|
360 case GL_LUMINANCE16F:
|
nuclear@0
|
361 case GL_LUMINANCE32F:
|
nuclear@0
|
362 ifmt = GL_LUMINANCE;
|
nuclear@0
|
363 break;
|
nuclear@0
|
364
|
nuclear@0
|
365 case GL_RGB16F:
|
nuclear@0
|
366 case GL_RGB32F:
|
nuclear@0
|
367 ifmt = GL_RGB;
|
nuclear@0
|
368 break;
|
nuclear@0
|
369
|
nuclear@0
|
370 case GL_RGBA16F:
|
nuclear@0
|
371 case GL_RGBA32F:
|
nuclear@0
|
372 ifmt = GL_RGBA;
|
nuclear@0
|
373 break;
|
nuclear@0
|
374
|
nuclear@0
|
375 default:
|
nuclear@0
|
376 break;
|
nuclear@0
|
377 }
|
nuclear@0
|
378 #endif
|
nuclear@0
|
379 return ifmt; // by default just pass it through...
|
nuclear@0
|
380 }
|
nuclear@0
|
381
|
nuclear@0
|
382 static int glfmt_from_ifmt(unsigned int ifmt)
|
nuclear@0
|
383 {
|
nuclear@0
|
384 switch(ifmt) {
|
nuclear@0
|
385 case GL_LUMINANCE16F:
|
nuclear@0
|
386 case GL_LUMINANCE32F:
|
nuclear@0
|
387 return GL_LUMINANCE;
|
nuclear@0
|
388
|
nuclear@0
|
389 case GL_RGB16F:
|
nuclear@0
|
390 case GL_RGB32F:
|
nuclear@0
|
391 return GL_RGB;
|
nuclear@0
|
392
|
nuclear@0
|
393 case GL_RGBA16F:
|
nuclear@0
|
394 case GL_RGBA32F:
|
nuclear@0
|
395 return GL_RGBA;
|
nuclear@0
|
396
|
nuclear@0
|
397 default:
|
nuclear@0
|
398 break;
|
nuclear@0
|
399 }
|
nuclear@0
|
400 return ifmt;
|
nuclear@0
|
401 }
|
nuclear@0
|
402
|
nuclear@0
|
403 static int gltype_from_ifmt(unsigned int ifmt)
|
nuclear@0
|
404 {
|
nuclear@0
|
405 switch(ifmt) {
|
nuclear@0
|
406 case GL_RGB16F:
|
nuclear@0
|
407 case GL_RGBA16F:
|
nuclear@0
|
408 case GL_LUMINANCE16F:
|
nuclear@0
|
409 #ifdef GL_ES_VERSION_2_0
|
nuclear@0
|
410 return GL_HALF_FLOAT_OES;
|
nuclear@0
|
411 #endif
|
nuclear@0
|
412 case GL_RGB32F:
|
nuclear@0
|
413 case GL_RGBA32F:
|
nuclear@0
|
414 case GL_LUMINANCE32F:
|
nuclear@0
|
415 return GL_FLOAT;
|
nuclear@0
|
416
|
nuclear@0
|
417 default:
|
nuclear@0
|
418 break;
|
nuclear@0
|
419 }
|
nuclear@0
|
420 return GL_UNSIGNED_BYTE;
|
nuclear@0
|
421 }
|
nuclear@0
|
422
|
nuclear@0
|
423 static int glifmt_from_imgfmt(Image::Format fmt)
|
nuclear@0
|
424 {
|
nuclear@0
|
425 switch(fmt) {
|
nuclear@0
|
426 case Image::FMT_GREY:
|
nuclear@0
|
427 return GL_LUMINANCE;
|
nuclear@0
|
428 case Image::FMT_GREY_FLOAT:
|
nuclear@0
|
429 return GL_LUMINANCE16F;
|
nuclear@0
|
430 case Image::FMT_RGB:
|
nuclear@0
|
431 return GL_RGB;
|
nuclear@0
|
432 case Image::FMT_RGB_FLOAT:
|
nuclear@0
|
433 return GL_RGB16F;
|
nuclear@0
|
434 case Image::FMT_RGBA:
|
nuclear@0
|
435 return GL_RGBA;
|
nuclear@0
|
436 case Image::FMT_RGBA_FLOAT:
|
nuclear@0
|
437 return GL_RGBA16F;
|
nuclear@0
|
438 default:
|
nuclear@0
|
439 break;
|
nuclear@0
|
440 }
|
nuclear@0
|
441 return 0;
|
nuclear@0
|
442 }
|
nuclear@0
|
443
|
nuclear@24
|
444 static unsigned int type_to_target(TextureType type)
|
nuclear@24
|
445 {
|
nuclear@24
|
446 return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
|
nuclear@24
|
447 }
|
nuclear@24
|
448
|
nuclear@24
|
449 static TextureType target_to_type(unsigned int targ)
|
nuclear@24
|
450 {
|
nuclear@24
|
451 return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D;
|
nuclear@24
|
452 }
|
nuclear@24
|
453
|
nuclear@0
|
454 // ---- TextureSet ----
|
nuclear@24
|
455 TextureSet::TextureSet()
|
nuclear@24
|
456 : DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex)
|
nuclear@24
|
457 {
|
nuclear@24
|
458 }
|
nuclear@24
|
459
|
nuclear@33
|
460 Texture *TextureSet::get_texture(const char *name, TextureType type) const
|
nuclear@33
|
461 {
|
nuclear@33
|
462 typename std::map<std::string, Texture*>::const_iterator iter = data.find(name);
|
nuclear@33
|
463 if(iter != data.end()) {
|
nuclear@33
|
464 return iter->second;
|
nuclear@33
|
465 }
|
nuclear@33
|
466
|
nuclear@33
|
467 const char *fname, *slash;
|
nuclear@33
|
468 if((slash = strrchr(name, '/'))) {
|
nuclear@33
|
469 fname = slash + 1;
|
nuclear@33
|
470 } else {
|
nuclear@33
|
471 fname = name;
|
nuclear@33
|
472 }
|
nuclear@33
|
473
|
nuclear@33
|
474 std::string path = datafile_path(fname);
|
nuclear@33
|
475 if(path.empty()) {
|
nuclear@33
|
476 fprintf(stderr, "can't find data file: %s\n", name);
|
nuclear@33
|
477 return 0;
|
nuclear@33
|
478 }
|
nuclear@33
|
479
|
nuclear@33
|
480 Texture *res = create();
|
nuclear@33
|
481 res->create_default(type);
|
nuclear@33
|
482 resman_lookup(rman, path.c_str(), res);
|
nuclear@33
|
483 return res;
|
nuclear@33
|
484 }
|
nuclear@33
|
485
|
nuclear@24
|
486 // static callbacks
|
nuclear@24
|
487
|
nuclear@24
|
488 Texture *TextureSet::create_tex()
|
nuclear@24
|
489 {
|
nuclear@24
|
490 return new Texture;
|
nuclear@24
|
491 }
|
nuclear@24
|
492
|
nuclear@24
|
493 bool TextureSet::load_tex(Texture *tex, const char *fname)
|
nuclear@24
|
494 {
|
nuclear@24
|
495 Image *img = new Image;
|
nuclear@24
|
496 if(!img->load(fname)) {
|
nuclear@24
|
497 delete img;
|
nuclear@24
|
498 return false;
|
nuclear@24
|
499 }
|
nuclear@24
|
500
|
nuclear@24
|
501 delete tex->img;
|
nuclear@24
|
502 tex->img = img;
|
nuclear@24
|
503
|
nuclear@24
|
504 return true;
|
nuclear@24
|
505 }
|
nuclear@24
|
506
|
nuclear@24
|
507 bool TextureSet::done_tex(Texture *tex)
|
nuclear@24
|
508 {
|
nuclear@24
|
509 if(!tex->img) {
|
nuclear@24
|
510 return false;
|
nuclear@24
|
511 }
|
nuclear@24
|
512
|
nuclear@24
|
513 tex->set_image(*tex->img);
|
nuclear@24
|
514 return true;
|
nuclear@24
|
515 }
|
nuclear@24
|
516
|
nuclear@24
|
517 void TextureSet::free_tex(Texture *tex)
|
nuclear@0
|
518 {
|
nuclear@0
|
519 delete tex;
|
nuclear@0
|
520 }
|