7 #if defined(GL_ES_VERSION_2_0) || defined(GL_VERSION_3_0)
8 #define USE_GL_GENERATE_MIPMAP
9 #elif defined(__GLEW_H__)
10 #define USE_SGIS_GENERATE_MIPMAP
13 static int glifmt_from_ifmt(unsigned int ifmt);
14 static int glfmt_from_ifmt(unsigned int ifmt);
15 static int gltype_from_ifmt(unsigned int ifmt);
17 static int glifmt_from_imgfmt(Image::Format fmt);
18 static Image::Format imgfmt_from_glifmt(unsigned int ifmt);
20 static unsigned int cur_target[8] = {
21 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
22 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
25 void bind_texture(Texture *tex, int tunit)
30 glActiveTexture(GL_TEXTURE0 + tunit);
31 glBindTexture(cur_target[tunit], 0);
32 glActiveTexture(GL_TEXTURE0);
36 Texture *load_texture(const char *fname)
38 TextureCube *texcube = new TextureCube;
39 if(texcube->load(fname)) {
44 Texture2D *tex = new Texture2D;
45 if(tex->load(fname)) {
56 sz[0] = sz[1] = sz[2] = 0;
59 glGenTextures(1, &id);
65 glDeleteTextures(1, &id);
69 void Texture::set_wrapping(unsigned int wrap)
75 glBindTexture(target, id);
76 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
77 glTexParameteri(target, GL_TEXTURE_WRAP_T, 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 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(GLEW_EXT_texture_filter_anisotropic) {
116 glBindTexture(target, id);
117 glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
121 unsigned int Texture::get_format() const
126 int Texture::get_size(int dim) const
128 if(dim < 0 || dim >= 3) {
134 unsigned int Texture::get_id() const
139 void Texture::bind(int tex_unit) const
141 glActiveTexture(GL_TEXTURE0 + tex_unit);
142 glBindTexture(target, id);
143 glActiveTexture(GL_TEXTURE0);
145 cur_target[tex_unit] = target;
149 // ---- Texture2D ----
151 Texture2D::Texture2D()
153 target = GL_TEXTURE_2D;
156 TextureType Texture2D::get_type() const
161 void Texture2D::create(int xsz, int ysz, unsigned int ifmt)
163 int fmt = glfmt_from_ifmt(ifmt);
164 int type = gltype_from_ifmt(ifmt);
166 glBindTexture(GL_TEXTURE_2D, id);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
169 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
175 void Texture2D::set_image(const Image &img, int idx)
177 texfmt = glifmt_from_imgfmt(img.get_format());
178 unsigned int fmt = glfmt_from_ifmt(texfmt);
179 unsigned int type = gltype_from_ifmt(texfmt);
181 sz[0] = img.get_width();
182 sz[1] = img.get_height();
184 glBindTexture(GL_TEXTURE_2D, id);
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
190 #ifdef USE_SGIS_GENERATE_MIPMAP
191 if(GLEW_SGIS_generate_mipmap) {
192 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
194 glTexImage2D(GL_TEXTURE_2D, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
195 #ifdef USE_SGIS_GENERATE_MIPMAP
197 gluBuild2DMipmaps(GL_TEXTURE_2D, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
201 #ifdef USE_GL_GENERATE_MIPMAP
202 glGenerateMipmap(GL_TEXTURE_2D);
206 void Texture2D::get_image(Image *img, int idx) const
208 #ifndef GL_ES_VERSION_2_0
209 glBindTexture(GL_TEXTURE_2D, id);
211 Image::Format img_fmt = imgfmt_from_glifmt(texfmt);
212 img->create(sz[0], sz[1], img_fmt);
214 unsigned int fmt = glfmt_from_ifmt(texfmt);
215 unsigned int type = gltype_from_ifmt(texfmt);
216 glGetTexImage(GL_TEXTURE_2D, 0, fmt, type, img->get_pixels());
217 #endif // GL_ES_VERSION_2_0
220 void Texture2D::set_subimage(const Image &img, int xoffs, int yoffs)
222 unsigned int ifmt = glifmt_from_imgfmt(img.get_format());
224 glBindTexture(GL_TEXTURE_2D, id);
225 glTexSubImage2D(GL_TEXTURE_2D, 0, xoffs, yoffs, img.get_width(), img.get_height(),
226 glfmt_from_ifmt(ifmt), gltype_from_ifmt(ifmt), img.get_pixels());
229 bool Texture2D::load(const char *fname)
232 if(!img.load(fname)) {
233 fprintf(stderr, "failed to load 2D texture: %s\n", fname);
238 printf("loaded 2D texture: %s\n", fname);
242 bool Texture2D::save(const char *fname) const
244 #ifndef GL_ES_VERSION_2_0
245 unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4];
247 glBindTexture(GL_TEXTURE_2D, id);
248 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
250 if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) {
251 fprintf(stderr, "failed to save 2D texture: %s\n", fname);
256 printf("saved 2D texture: %s\n", fname);
260 return false; // TODO
264 // ---- TextureCube ----
265 static unsigned int cube_faces[] = {
266 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
267 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
268 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
269 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
270 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
271 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
274 TextureCube::TextureCube()
276 target = GL_TEXTURE_CUBE_MAP;
279 TextureType TextureCube::get_type() const
285 void TextureCube::create(int xsz, int ysz, unsigned int ifmt)
288 fprintf(stderr, "trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
294 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
300 for(int i=0; i<6; i++) {
301 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
305 void TextureCube::set_image(const Image &img, int idx)
310 void TextureCube::get_image(Image *img, int idx) const
315 bool TextureCube::load(const char *fname)
317 return false; // TODO
320 bool TextureCube::save(const char *fname) const
322 return false; // TODO
325 static int glifmt_from_ifmt(unsigned int ifmt)
327 #ifdef GL_ES_VERSION_2_0
329 case GL_LUMINANCE16F:
330 case GL_LUMINANCE32F:
348 return ifmt; // by default just pass it through...
351 static int glfmt_from_ifmt(unsigned int ifmt)
354 case GL_LUMINANCE16F:
355 case GL_LUMINANCE32F:
375 static int gltype_from_ifmt(unsigned int ifmt)
380 case GL_LUMINANCE16F:
381 #ifdef GL_ES_VERSION_2_0
382 return GL_HALF_FLOAT_OES;
386 case GL_LUMINANCE32F:
392 return GL_UNSIGNED_BYTE;
395 static int glifmt_from_imgfmt(Image::Format fmt)
398 case Image::FMT_GREY:
399 return GLEW_EXT_texture_sRGB ? GL_SLUMINANCE : GL_LUMINANCE;
401 case Image::FMT_GREY_FLOAT:
402 return GL_LUMINANCE16F;
405 return GLEW_EXT_texture_sRGB ? GL_SRGB : GL_RGB;
407 case Image::FMT_RGB_FLOAT:
410 case Image::FMT_RGBA:
411 return GLEW_EXT_texture_sRGB ? GL_SRGB_ALPHA : GL_RGBA;
413 case Image::FMT_RGBA_FLOAT:
422 static Image::Format imgfmt_from_glifmt(unsigned int ifmt)
427 return Image::FMT_GREY;
428 case GL_LUMINANCE16F:
429 return Image::FMT_GREY_FLOAT;
432 return Image::FMT_RGB;
434 return Image::FMT_RGB_FLOAT;
437 return Image::FMT_RGBA;
439 return Image::FMT_RGBA_FLOAT;
444 fprintf(stderr, "imgfmt_from_glifmt: unknown internal format: %x\n", ifmt);
448 return Image::FMT_RGBA; // ... whatever