8 #if defined(GL_ES_VERSION_2_0) || defined(GL_VERSION_3_0)
9 #define USE_GL_GENERATE_MIPMAP
10 #elif defined(__GLEW_H__)
11 #define USE_SGIS_GENERATE_MIPMAP
14 static int glifmt_from_ifmt(unsigned int ifmt);
15 static int glfmt_from_ifmt(unsigned int ifmt);
16 static int gltype_from_ifmt(unsigned int ifmt);
18 static int glifmt_from_imgfmt(Image::Format fmt);
19 static Image::Format imgfmt_from_glifmt(unsigned int ifmt);
21 static unsigned int cur_target[8] = {
22 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
23 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
26 void bind_texture(Texture *tex, int tunit)
31 glActiveTexture(GL_TEXTURE0 + tunit);
32 glBindTexture(cur_target[tunit], 0);
33 glActiveTexture(GL_TEXTURE0);
37 Texture *load_texture(const char *fname)
39 TextureCube *texcube = new TextureCube;
40 if(texcube->load(fname)) {
45 Texture2D *tex = new Texture2D;
46 if(tex->load(fname)) {
57 sz[0] = sz[1] = sz[2] = 0;
60 glGenTextures(1, &id);
66 glDeleteTextures(1, &id);
70 void Texture::set_wrapping(unsigned int wrap)
76 glBindTexture(target, id);
77 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
78 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
81 void Texture::set_filtering(unsigned int filt)
83 unsigned int mag_filter;
90 case GL_LINEAR_MIPMAP_NEAREST:
91 case GL_LINEAR_MIPMAP_LINEAR:
92 mag_filter = GL_LINEAR;
95 case GL_NEAREST_MIPMAP_NEAREST:
96 case GL_NEAREST_MIPMAP_LINEAR:
97 mag_filter = GL_NEAREST;
104 set_filtering(filt, mag_filter);
107 void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt)
109 glBindTexture(target, id);
110 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt);
111 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt);
114 void Texture::set_anisotropy(int aniso)
116 if(GLEW_EXT_texture_filter_anisotropic) {
117 glBindTexture(target, id);
118 glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
122 unsigned int Texture::get_format() const
127 int Texture::get_size(int dim) const
129 if(dim < 0 || dim >= 3) {
135 unsigned int Texture::get_id() const
140 void Texture::bind(int tex_unit) const
142 glActiveTexture(GL_TEXTURE0 + tex_unit);
143 glBindTexture(target, id);
144 glActiveTexture(GL_TEXTURE0);
146 cur_target[tex_unit] = target;
150 // ---- Texture2D ----
152 Texture2D::Texture2D()
154 target = GL_TEXTURE_2D;
157 TextureType Texture2D::get_type() const
162 void Texture2D::create(int xsz, int ysz, unsigned int ifmt)
164 int fmt = glfmt_from_ifmt(ifmt);
165 int type = gltype_from_ifmt(ifmt);
167 glBindTexture(GL_TEXTURE_2D, id);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
170 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
176 void Texture2D::set_image(const Image &img, int idx)
178 texfmt = glifmt_from_imgfmt(img.get_format());
179 unsigned int fmt = glfmt_from_ifmt(texfmt);
180 unsigned int type = gltype_from_ifmt(texfmt);
182 sz[0] = img.get_width();
183 sz[1] = img.get_height();
185 glBindTexture(GL_TEXTURE_2D, id);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
191 #ifdef USE_SGIS_GENERATE_MIPMAP
192 if(GLEW_SGIS_generate_mipmap) {
193 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
195 glTexImage2D(GL_TEXTURE_2D, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
196 #ifdef USE_SGIS_GENERATE_MIPMAP
198 gluBuild2DMipmaps(GL_TEXTURE_2D, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
202 #ifdef USE_GL_GENERATE_MIPMAP
203 glGenerateMipmap(GL_TEXTURE_2D);
207 void Texture2D::get_image(Image *img, int idx) const
209 #ifndef GL_ES_VERSION_2_0
210 glBindTexture(GL_TEXTURE_2D, id);
212 Image::Format img_fmt = imgfmt_from_glifmt(texfmt);
213 img->create(sz[0], sz[1], img_fmt);
215 unsigned int fmt = glfmt_from_ifmt(texfmt);
216 unsigned int type = gltype_from_ifmt(texfmt);
217 glGetTexImage(GL_TEXTURE_2D, 0, fmt, type, img->get_pixels());
218 #endif // GL_ES_VERSION_2_0
221 void Texture2D::set_subimage(const Image &img, int xoffs, int yoffs)
223 unsigned int ifmt = glifmt_from_imgfmt(img.get_format());
225 glBindTexture(GL_TEXTURE_2D, id);
226 glTexSubImage2D(GL_TEXTURE_2D, 0, xoffs, yoffs, img.get_width(), img.get_height(),
227 glfmt_from_ifmt(ifmt), gltype_from_ifmt(ifmt), img.get_pixels());
230 bool Texture2D::load(const char *fname)
233 if(!img.load(fname)) {
234 fprintf(stderr, "failed to load 2D texture: %s\n", fname);
239 printf("loaded 2D texture: %s\n", fname);
243 bool Texture2D::save(const char *fname) const
245 #ifndef GL_ES_VERSION_2_0
246 unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4];
248 glBindTexture(GL_TEXTURE_2D, id);
249 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
251 if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) {
252 fprintf(stderr, "failed to save 2D texture: %s\n", fname);
257 printf("saved 2D texture: %s\n", fname);
261 return false; // TODO
265 // ---- TextureCube ----
266 static unsigned int cube_faces[] = {
267 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
268 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
269 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
270 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
271 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
272 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
275 TextureCube::TextureCube()
277 target = GL_TEXTURE_CUBE_MAP;
280 TextureType TextureCube::get_type() const
286 void TextureCube::create(int xsz, int ysz, unsigned int ifmt)
289 fprintf(stderr, "trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
295 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
301 for(int i=0; i<6; i++) {
302 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
306 void TextureCube::set_image(const Image &img, int idx)
311 void TextureCube::get_image(Image *img, int idx) const
316 bool TextureCube::load(const char *fname)
318 return false; // TODO
321 bool TextureCube::save(const char *fname) const
323 return false; // TODO
326 static int glifmt_from_ifmt(unsigned int ifmt)
328 #ifdef GL_ES_VERSION_2_0
330 case GL_LUMINANCE16F:
331 case GL_LUMINANCE32F:
349 return ifmt; // by default just pass it through...
352 static int glfmt_from_ifmt(unsigned int ifmt)
355 case GL_LUMINANCE16F:
356 case GL_LUMINANCE32F:
376 static int gltype_from_ifmt(unsigned int ifmt)
381 case GL_LUMINANCE16F:
382 #ifdef GL_ES_VERSION_2_0
383 return GL_HALF_FLOAT_OES;
387 case GL_LUMINANCE32F:
393 return GL_UNSIGNED_BYTE;
396 static int glifmt_from_imgfmt(Image::Format fmt)
398 bool use_srgb = GLEW_EXT_texture_sRGB && opt.srgb;
401 case Image::FMT_GREY:
402 return use_srgb ? GL_SLUMINANCE : GL_LUMINANCE;
404 case Image::FMT_GREY_FLOAT:
405 return GL_LUMINANCE16F;
408 return use_srgb ? GL_SRGB : GL_RGB;
410 case Image::FMT_RGB_FLOAT:
413 case Image::FMT_RGBA:
414 return use_srgb ? GL_SRGB_ALPHA : GL_RGBA;
416 case Image::FMT_RGBA_FLOAT:
425 static Image::Format imgfmt_from_glifmt(unsigned int ifmt)
430 return Image::FMT_GREY;
431 case GL_LUMINANCE16F:
432 return Image::FMT_GREY_FLOAT;
435 return Image::FMT_RGB;
437 return Image::FMT_RGB_FLOAT;
440 return Image::FMT_RGBA;
442 return Image::FMT_RGBA_FLOAT;
447 fprintf(stderr, "imgfmt_from_glifmt: unknown internal format: %x\n", ifmt);
451 return Image::FMT_RGBA; // ... whatever