8 static int glifmt_from_ifmt(unsigned int ifmt);
9 static int glfmt_from_ifmt(unsigned int ifmt);
10 static int gltype_from_ifmt(unsigned int ifmt);
12 static int glifmt_from_imgfmt(Image::Format fmt);
14 static unsigned int type_to_target(TextureType type);
15 static TextureType target_to_type(unsigned int targ);
17 static unsigned int cur_target[8] = {
18 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
19 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
22 static unsigned int cube_faces[] = {
23 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
24 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
25 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
26 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
27 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
28 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
32 void bind_texture(Texture *tex, int tunit)
37 glActiveTexture(GL_TEXTURE0 + tunit);
38 glBindTexture(cur_target[tunit], 0);
39 assert(glGetError() == GL_NO_ERROR);
40 glActiveTexture(GL_TEXTURE0);
45 Image *Texture::default_img;
50 sz[0] = sz[1] = sz[2] = 0;
54 glGenTextures(1, &id);
60 glDeleteTextures(1, &id);
67 void Texture::set_wrapping(unsigned int wrap)
73 glBindTexture(target, id);
74 assert(glGetError() == GL_NO_ERROR);
75 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
76 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
77 glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap);
80 void Texture::set_filtering(unsigned int filt)
82 unsigned int mag_filter;
89 case GL_LINEAR_MIPMAP_NEAREST:
90 case GL_LINEAR_MIPMAP_LINEAR:
91 mag_filter = GL_LINEAR;
94 case GL_NEAREST_MIPMAP_NEAREST:
95 case GL_NEAREST_MIPMAP_LINEAR:
96 mag_filter = GL_NEAREST;
103 set_filtering(filt, mag_filter);
106 void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt)
108 glBindTexture(target, id);
109 assert(glGetError() == GL_NO_ERROR);
110 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt);
111 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt);
114 unsigned int Texture::get_format() const
119 int Texture::get_size(int dim) const
121 if(dim < 0 || dim >= 3) {
127 unsigned int Texture::get_id() const
132 TextureType Texture::get_type() const
134 return target_to_type(target);
137 void Texture::bind(int tex_unit) const
139 glActiveTexture(GL_TEXTURE0 + tex_unit);
140 glBindTexture(target, id);
141 assert(glGetError() == GL_NO_ERROR);
142 glActiveTexture(GL_TEXTURE0);
144 cur_target[tex_unit] = target;
148 void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
150 if(textype == TEX_CUBE && xsz != ysz) {
151 fprintf(stderr, "trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
155 int fmt = glfmt_from_ifmt(ifmt);
156 int type = gltype_from_ifmt(ifmt);
158 target = type_to_target(textype);
160 glBindTexture(target, id);
161 assert(glGetError() == GL_NO_ERROR);
162 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
163 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
167 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
171 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
172 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
173 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
174 for(int i=0; i<6; i++) {
175 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
185 #define DEF_IMAGE_SIZE 64
186 void Texture::create_default(TextureType type)
189 default_img = new Image;
190 default_img->create(DEF_IMAGE_SIZE, DEF_IMAGE_SIZE, Image::FMT_RGBA);
192 unsigned char *pixels = (unsigned char*)default_img->get_pixels();
193 for(int i=0; i<DEF_IMAGE_SIZE; i++) {
194 for(int j=0; j<DEF_IMAGE_SIZE; j++) {
195 bool chess = ((i >> 3) & 1) == ((j >> 3) & 1);
196 pixels[0] = chess ? 255 : 32;
198 pixels[2] = chess ? 32 : 255;
203 default_img->save("/tmp/foo.png");
208 set_image(*default_img);
212 for(int i=0; i<6; i++) {
213 set_image(*default_img, i);
219 void Texture::set_image(const Image &img, int idx)
221 if(idx >= 0 && idx < 6) {
222 set_image_cube(img, idx);
224 if(!set_image_cube(img)) {
230 void Texture::set_image_2d(const Image &img)
232 texfmt = glifmt_from_imgfmt(img.get_format());
233 unsigned int fmt = glfmt_from_ifmt(texfmt);
234 unsigned int type = gltype_from_ifmt(texfmt);
236 sz[0] = img.get_width();
237 sz[1] = img.get_height();
239 target = GL_TEXTURE_2D;
240 glBindTexture(target, id);
241 assert(glGetError() == GL_NO_ERROR);
242 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
243 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
244 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
245 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
248 if(GLEW_SGIS_generate_mipmap) {
249 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
251 glTexImage2D(target, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
254 gluBuild2DMipmaps(target, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
258 #ifdef GL_ES_VERSION_2_0
259 glGenerateMipmap(target);
263 bool Texture::set_image_cube(const Image &img, int idx)
265 if(idx < 0 || idx >= 6) {
269 texfmt = glifmt_from_imgfmt(img.get_format());
270 unsigned int fmt = glfmt_from_ifmt(texfmt);
271 unsigned int type = gltype_from_ifmt(texfmt);
273 sz[0] = img.get_width();
274 sz[1] = img.get_height();
276 target = GL_TEXTURE_CUBE_MAP;
277 glBindTexture(target, id);
278 assert(glGetError() == GL_NO_ERROR);
279 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
280 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
281 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
282 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
283 glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
285 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
289 bool Texture::set_image_cube(const Image &img)
291 static const float one_third = 1.0 / 3.0;
292 static const float two_thirds = 2.0 / 3.0;
293 static const float hcross[2][6] = {
294 {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} };
295 static const float vcross[2][6] = {
296 {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} };
297 static const float hsix[2][6] = {
298 {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} };
300 int xsz = img.get_width();
301 int ysz = img.get_height();
303 if(xsz / 4 == ysz / 3) {
304 // horizontal cross, assume the vertical bit is center-left
305 return set_cube_multi(img, hcross[0], hcross[1], xsz / 4);
307 if(xsz / 3 == ysz / 4) {
308 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5)
309 return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
311 if(xsz / 3 == ysz / 2) {
312 // horizontal sixpack
313 return set_cube_multi(img, hsix[0], hsix[1], ysz / 2);
320 bool Texture::load(const char *fname)
323 if(!img.load(fname)) {
324 fprintf(stderr, "failed to load 2D texture: %s\n", fname);
329 printf("loaded 2D texture: %s\n", fname);
333 bool Texture::load_cube(const char *fname)
336 if(!img.load(fname)) {
339 return set_image_cube(img);
342 bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
343 unsigned int rotmask)
345 for(int i=0; i<6; i++) {
348 int xoffs = xoffsets[i] * img.get_width();
349 int yoffs = yoffsets[i] * img.get_height();
351 if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) {
355 if(rotmask & (1 << i)) {
358 set_image_cube(face, i);
363 static int glifmt_from_ifmt(unsigned int ifmt)
365 #ifdef GL_ES_VERSION_2_0
367 case GL_LUMINANCE16F_ARB:
368 case GL_LUMINANCE32F_ARB:
386 return ifmt; // by default just pass it through...
389 static int glfmt_from_ifmt(unsigned int ifmt)
392 case GL_LUMINANCE16F_ARB:
393 case GL_LUMINANCE32F_ARB:
413 static int gltype_from_ifmt(unsigned int ifmt)
418 case GL_LUMINANCE16F_ARB:
419 #ifdef GL_ES_VERSION_2_0
420 return GL_HALF_FLOAT_OES;
424 case GL_LUMINANCE32F_ARB:
430 return GL_UNSIGNED_BYTE;
433 static int glifmt_from_imgfmt(Image::Format fmt)
436 case Image::FMT_GREY:
437 return GL_SLUMINANCE;
438 case Image::FMT_GREY_FLOAT:
439 return GL_LUMINANCE16F_ARB;
442 case Image::FMT_RGB_FLOAT:
444 case Image::FMT_RGBA:
445 return GL_SRGB_ALPHA;
446 case Image::FMT_RGBA_FLOAT:
454 static unsigned int type_to_target(TextureType type)
456 return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
459 static TextureType target_to_type(unsigned int targ)
461 return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D;
464 // ---- TextureSet ----
465 TextureSet::TextureSet()
466 : DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex)
470 Texture *TextureSet::get_texture(const char *name, TextureType type) const
472 std::map<std::string, Texture*>::const_iterator iter = data.find(name);
473 if(iter != data.end()) {
477 Texture *res = create();
479 res->create_default(type);
480 resman_lookup(rman, name, res);
486 Texture *TextureSet::create_tex()
491 bool TextureSet::load_tex(Texture *tex, const char *fname)
493 Image *img = new Image;
494 if(!img->load(fname)) {
505 bool TextureSet::done_tex(Texture *tex)
511 tex->set_image(*tex->img);
515 void TextureSet::free_tex(Texture *tex)