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);
44 Image *Texture::default_img;
49 sz[0] = sz[1] = sz[2] = 0;
53 glGenTextures(1, &id);
59 glDeleteTextures(1, &id);
66 void Texture::set_wrapping(unsigned int wrap)
72 glBindTexture(target, id);
73 assert(glGetError() == GL_NO_ERROR);
74 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
75 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
76 glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap);
79 void Texture::set_filtering(unsigned int filt)
81 unsigned int mag_filter;
88 case GL_LINEAR_MIPMAP_NEAREST:
89 case GL_LINEAR_MIPMAP_LINEAR:
90 mag_filter = GL_LINEAR;
93 case GL_NEAREST_MIPMAP_NEAREST:
94 case GL_NEAREST_MIPMAP_LINEAR:
95 mag_filter = GL_NEAREST;
102 set_filtering(filt, mag_filter);
105 void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt)
107 glBindTexture(target, id);
108 assert(glGetError() == GL_NO_ERROR);
109 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt);
110 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt);
113 void Texture::set_anisotropy(int aniso)
115 if(aniso > glcaps.max_aniso) {
116 aniso = glcaps.max_aniso;
119 glBindTexture(target, id);
120 glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
123 unsigned int Texture::get_format() const
128 int Texture::get_size(int dim) const
130 if(dim < 0 || dim >= 3) {
136 int Texture::get_width() const
141 int Texture::get_height() const
146 unsigned int Texture::get_id() const
151 TextureType Texture::get_type() const
153 return target_to_type(target);
156 void Texture::bind(int tex_unit) const
158 glActiveTexture(GL_TEXTURE0 + tex_unit);
159 glBindTexture(target, id);
160 assert(glGetError() == GL_NO_ERROR);
161 glActiveTexture(GL_TEXTURE0);
163 cur_target[tex_unit] = target;
167 void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
169 if(textype == TEX_CUBE && xsz != ysz) {
170 fprintf(stderr, "trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
174 int fmt = glfmt_from_ifmt(ifmt);
175 int type = gltype_from_ifmt(ifmt);
177 target = type_to_target(textype);
179 glBindTexture(target, id);
180 assert(glGetError() == GL_NO_ERROR);
181 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
182 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
186 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
190 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
192 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
193 for(int i=0; i<6; i++) {
194 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
204 #define DEF_IMAGE_SIZE 64
205 void Texture::create_default(TextureType type)
208 default_img = new Image;
209 default_img->create(DEF_IMAGE_SIZE, DEF_IMAGE_SIZE, Image::FMT_RGBA);
211 unsigned char *pixels = (unsigned char*)default_img->get_pixels();
212 for(int i=0; i<DEF_IMAGE_SIZE; i++) {
213 for(int j=0; j<DEF_IMAGE_SIZE; j++) {
214 bool chess = ((i >> 3) & 1) == ((j >> 3) & 1);
215 pixels[0] = chess ? 255 : 32;
217 pixels[2] = chess ? 32 : 255;
226 set_image(*default_img);
230 for(int i=0; i<6; i++) {
231 set_image(*default_img, i);
237 void Texture::set_image(const Image &img, int idx)
239 if(idx >= 0 && idx < 6) {
240 set_image_cube(img, idx);
242 if(!set_image_cube(img)) {
248 void Texture::set_image_2d(const Image &img)
250 texfmt = glifmt_from_imgfmt(img.get_format());
251 unsigned int fmt = glfmt_from_ifmt(texfmt);
252 unsigned int type = gltype_from_ifmt(texfmt);
254 sz[0] = img.get_width();
255 sz[1] = img.get_height();
257 target = GL_TEXTURE_2D;
258 glBindTexture(target, id);
259 assert(glGetError() == GL_NO_ERROR);
260 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
261 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
262 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
263 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
265 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
268 if(GLEW_SGIS_generate_mipmap) {
269 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
271 glTexImage2D(target, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
274 gluBuild2DMipmaps(target, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
278 #ifdef GL_ES_VERSION_2_0
279 glGenerateMipmap(target);
283 bool Texture::set_image_cube(const Image &img, int idx)
286 if(idx < 0 || idx >= 6) {
290 texfmt = glifmt_from_imgfmt(img.get_format());
291 unsigned int fmt = glfmt_from_ifmt(texfmt);
292 unsigned int type = gltype_from_ifmt(texfmt);
294 sz[0] = img.get_width();
295 sz[1] = img.get_height();
297 target = GL_TEXTURE_CUBE_MAP;
298 glBindTexture(target, id);
299 if((err = glGetError()) == GL_INVALID_OPERATION) {
300 return false; // probably not a cubemap
302 assert(err == GL_NO_ERROR);
303 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
304 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
305 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
306 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
307 glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
309 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
313 bool Texture::set_image_cube(const Image &img)
315 static const float one_third = 1.0 / 3.0;
316 static const float two_thirds = 2.0 / 3.0;
317 static const float hcross[2][6] = {
318 {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} };
319 static const float vcross[2][6] = {
320 {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} };
321 static const float hsix[2][6] = {
322 {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} };
324 int xsz = img.get_width();
325 int ysz = img.get_height();
327 if((xsz << 8) / 4 == (ysz << 8) / 3) {
328 // horizontal cross, assume the vertical bit is center-left
329 return set_cube_multi(img, hcross[0], hcross[1], xsz / 4);
331 if((xsz << 8) / 3 == (ysz << 8) / 4) {
332 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5)
333 return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
335 if((xsz << 8) / 3 == (ysz << 8) / 2) {
336 // horizontal sixpack
337 return set_cube_multi(img, hsix[0], hsix[1], ysz / 2);
344 bool Texture::load(const char *fname)
347 if(!img.load(fname)) {
348 fprintf(stderr, "failed to load 2D texture: %s\n", fname);
353 printf("loaded 2D texture: %s\n", fname);
357 bool Texture::load_cube(const char *fname)
360 if(!img.load(fname)) {
363 return set_image_cube(img);
366 bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
367 unsigned int rotmask)
369 for(int i=0; i<6; i++) {
372 int xoffs = xoffsets[i] * img.get_width();
373 int yoffs = yoffsets[i] * img.get_height();
375 if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) {
379 if(rotmask & (1 << i)) {
382 set_image_cube(face, i);
387 static int glifmt_from_ifmt(unsigned int ifmt)
389 #ifdef GL_ES_VERSION_2_0
391 case GL_LUMINANCE16F_ARB:
392 case GL_LUMINANCE32F_ARB:
410 return ifmt; // by default just pass it through...
413 static int glfmt_from_ifmt(unsigned int ifmt)
416 case GL_LUMINANCE16F_ARB:
417 case GL_LUMINANCE32F_ARB:
437 static int gltype_from_ifmt(unsigned int ifmt)
442 case GL_LUMINANCE16F_ARB:
443 #ifdef GL_ES_VERSION_2_0
444 return GL_HALF_FLOAT_OES;
448 case GL_LUMINANCE32F_ARB:
454 return GL_UNSIGNED_BYTE;
457 static int glifmt_from_imgfmt(Image::Format fmt)
460 case Image::FMT_GREY:
461 return GL_SLUMINANCE;
462 case Image::FMT_GREY_FLOAT:
463 return GL_LUMINANCE16F_ARB;
466 case Image::FMT_RGB_FLOAT:
468 case Image::FMT_RGBA:
469 return GL_SRGB_ALPHA;
470 case Image::FMT_RGBA_FLOAT:
478 static unsigned int type_to_target(TextureType type)
480 return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
483 static TextureType target_to_type(unsigned int targ)
485 return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D;