goat3dgfx
diff src/texture.cc @ 24:dc5918c62a64
broken: converting to resman
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Mar 2014 22:04:29 +0200 |
parents | 7d6b667821cf |
children | 253542d715f4 |
line diff
1.1 --- a/src/texture.cc Tue Feb 25 23:47:48 2014 +0200 1.2 +++ b/src/texture.cc Sat Mar 01 22:04:29 2014 +0200 1.3 @@ -14,14 +14,25 @@ 1.4 1.5 static int glifmt_from_imgfmt(Image::Format fmt); 1.6 1.7 +static unsigned int type_to_target(TextureType type); 1.8 +static TextureType target_to_type(unsigned int targ); 1.9 + 1.10 static unsigned int cur_target[8] = { 1.11 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, 1.12 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D 1.13 }; 1.14 1.15 -namespace goatgfx { 1.16 +static unsigned int cube_faces[] = { 1.17 + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1.18 + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1.19 + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1.20 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1.21 + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1.22 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 1.23 +}; 1.24 1.25 -void set_texture(Texture *tex, int tunit) 1.26 + 1.27 +void goatgfx::bind_texture(Texture *tex, int tunit) 1.28 { 1.29 if(tex) { 1.30 tex->bind(tunit); 1.31 @@ -32,30 +43,13 @@ 1.32 } 1.33 } 1.34 1.35 -Texture *load_texture(const char *fname) 1.36 -{ 1.37 - TextureCube *texcube = new TextureCube; 1.38 - if(texcube->load(fname)) { 1.39 - return texcube; 1.40 - } 1.41 - delete texcube; 1.42 - 1.43 - Texture2D *tex = new Texture2D; 1.44 - if(tex->load(fname)) { 1.45 - return tex; 1.46 - } 1.47 - delete tex; 1.48 - return 0; 1.49 -} 1.50 - 1.51 -} // namespace goatgfx 1.52 - 1.53 Texture::Texture() 1.54 { 1.55 target = 0; 1.56 sz[0] = sz[1] = sz[2] = 0; 1.57 texfmt = 0; 1.58 1.59 + img = 0; 1.60 glGenTextures(1, &id); 1.61 } 1.62 1.63 @@ -64,6 +58,9 @@ 1.64 if(id) { 1.65 glDeleteTextures(1, &id); 1.66 } 1.67 + if(img) { 1.68 + delete img; 1.69 + } 1.70 } 1.71 1.72 void Texture::set_wrapping(unsigned int wrap) 1.73 @@ -75,6 +72,7 @@ 1.74 glBindTexture(target, id); 1.75 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); 1.76 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); 1.77 + glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap); 1.78 } 1.79 1.80 void Texture::set_filtering(unsigned int filt) 1.81 @@ -128,6 +126,11 @@ 1.82 return id; 1.83 } 1.84 1.85 +TextureType Texture::get_type() const 1.86 +{ 1.87 + return target_to_type(target); 1.88 +} 1.89 + 1.90 void Texture::bind(int tex_unit) const 1.91 { 1.92 glActiveTexture(GL_TEXTURE0 + tex_unit); 1.93 @@ -138,29 +141,55 @@ 1.94 } 1.95 1.96 1.97 -// ---- Texture2D ---- 1.98 +void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt) 1.99 +{ 1.100 + if(textype == TEX_CUBE && xsz != ysz) { 1.101 + error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); 1.102 + return; 1.103 + } 1.104 1.105 -Texture2D::Texture2D() 1.106 -{ 1.107 - target = GL_TEXTURE_2D; 1.108 -} 1.109 - 1.110 -void Texture2D::create(int xsz, int ysz, unsigned int ifmt) 1.111 -{ 1.112 int fmt = glfmt_from_ifmt(ifmt); 1.113 int type = gltype_from_ifmt(ifmt); 1.114 1.115 - glBindTexture(GL_TEXTURE_2D, id); 1.116 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.117 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.118 - glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); 1.119 + target = type_to_target(textype); 1.120 + 1.121 + glBindTexture(target, id); 1.122 + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.123 + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.124 + 1.125 + switch(type) { 1.126 + case TEX_2D: 1.127 + glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); 1.128 + break; 1.129 + 1.130 + case TEX_CUBE: 1.131 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1.132 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1.133 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 1.134 + for(int i=0; i<6; i++) { 1.135 + glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 1.136 + } 1.137 + break; 1.138 + } 1.139 + 1.140 CHECKGLERR; 1.141 sz[0] = xsz; 1.142 sz[1] = ysz; 1.143 texfmt = ifmt; 1.144 } 1.145 1.146 -void Texture2D::set_image(const Image &img, int idx) 1.147 +void Texture::set_image(const Image &img, int idx) 1.148 +{ 1.149 + if(idx >= 0 && idx < 6) { 1.150 + set_image_cube(img, idx); 1.151 + } else { 1.152 + if(!set_image_cube(img)) { 1.153 + set_image_2d(img); 1.154 + } 1.155 + } 1.156 +} 1.157 + 1.158 +void Texture::set_image_2d(const Image &img) 1.159 { 1.160 texfmt = glifmt_from_imgfmt(img.get_format()); 1.161 unsigned int fmt = glfmt_from_ifmt(texfmt); 1.162 @@ -191,79 +220,12 @@ 1.163 #endif 1.164 } 1.165 1.166 -bool Texture2D::load(const char *fname) 1.167 +bool Texture::set_image_cube(const Image &img, int idx) 1.168 { 1.169 - Image img; 1.170 - if(!img.load(fname)) { 1.171 - error_log("failed to load 2D texture: %s\n", fname); 1.172 - return false; 1.173 - } 1.174 - set_image(img); 1.175 - 1.176 - info_log("loaded 2D texture: %s\n", fname); 1.177 - return true; 1.178 -} 1.179 - 1.180 -bool Texture2D::save(const char *fname) const 1.181 -{ 1.182 -#ifndef GL_ES_VERSION_2_0 1.183 - unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4]; 1.184 - 1.185 - glBindTexture(GL_TEXTURE_2D, id); 1.186 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 1.187 - 1.188 - if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) { 1.189 - error_log("failed to save 2D texture: %s\n", fname); 1.190 - delete [] pixels; 1.191 + if(idx < 0 || idx >= 6) { 1.192 return false; 1.193 } 1.194 1.195 - info_log("saved 2D texture: %s\n", fname); 1.196 - delete [] pixels; 1.197 - return true; 1.198 -#else 1.199 - return false; // TODO 1.200 -#endif 1.201 -} 1.202 - 1.203 -// ---- TextureCube ---- 1.204 -static unsigned int cube_faces[] = { 1.205 - GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1.206 - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1.207 - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1.208 - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1.209 - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1.210 - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 1.211 -}; 1.212 - 1.213 -TextureCube::TextureCube() 1.214 -{ 1.215 - target = GL_TEXTURE_CUBE_MAP; 1.216 -} 1.217 - 1.218 -void TextureCube::create(int xsz, int ysz, unsigned int ifmt) 1.219 -{ 1.220 - if(xsz != ysz) { 1.221 - error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); 1.222 - return; 1.223 - } 1.224 - 1.225 - texfmt = ifmt; 1.226 - 1.227 - glBindTexture(GL_TEXTURE_CUBE_MAP, id); 1.228 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.229 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.230 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1.231 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1.232 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 1.233 - 1.234 - for(int i=0; i<6; i++) { 1.235 - glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 1.236 - } 1.237 -} 1.238 - 1.239 -void TextureCube::set_image(const Image &img, int idx) 1.240 -{ 1.241 texfmt = glifmt_from_imgfmt(img.get_format()); 1.242 unsigned int fmt = glfmt_from_ifmt(texfmt); 1.243 unsigned int type = gltype_from_ifmt(texfmt); 1.244 @@ -279,9 +241,10 @@ 1.245 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 1.246 1.247 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); 1.248 + return true; 1.249 } 1.250 1.251 -bool TextureCube::load(const char *fname) 1.252 +bool Texture::set_image_cube(const Image &img) 1.253 { 1.254 static const float one_third = 1.0 / 3.0; 1.255 static const float two_thirds = 2.0 / 3.0; 1.256 @@ -292,37 +255,49 @@ 1.257 static const float hsix[2][6] = { 1.258 {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} }; 1.259 1.260 - Image img; 1.261 - if(!img.load(fname)) { 1.262 - return false; 1.263 - } 1.264 - 1.265 int xsz = img.get_width(); 1.266 int ysz = img.get_height(); 1.267 1.268 if(xsz / 4 == ysz / 3) { 1.269 // horizontal cross, assume the vertical bit is center-left 1.270 - return load_multi(img, hcross[0], hcross[1], xsz / 4); 1.271 + return set_cube_multi(img, hcross[0], hcross[1], xsz / 4); 1.272 } 1.273 if(xsz / 3 == ysz / 4) { 1.274 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) 1.275 - return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); 1.276 + return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); 1.277 } 1.278 if(xsz / 3 == ysz / 2) { 1.279 // horizontal sixpack 1.280 - return load_multi(img, hsix[0], hsix[1], ysz / 2); 1.281 + return set_cube_multi(img, hsix[0], hsix[1], ysz / 2); 1.282 } 1.283 1.284 - error_log("failed to load %s: unknown cubemap configuration\n", fname); 1.285 return false; 1.286 } 1.287 1.288 -bool TextureCube::save(const char *fname) const 1.289 + 1.290 +bool Texture::load(const char *fname) 1.291 { 1.292 - return false; // TODO 1.293 + Image img; 1.294 + if(!img.load(fname)) { 1.295 + error_log("failed to load 2D texture: %s\n", fname); 1.296 + return false; 1.297 + } 1.298 + set_image(img); 1.299 + 1.300 + info_log("loaded 2D texture: %s\n", fname); 1.301 + return true; 1.302 } 1.303 1.304 -bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 1.305 +bool Texture::load_cube(const char *fname) 1.306 +{ 1.307 + Image img; 1.308 + if(!img.load(fname)) { 1.309 + return false; 1.310 + } 1.311 + return set_image_cube(img); 1.312 +} 1.313 + 1.314 +bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 1.315 unsigned int rotmask) 1.316 { 1.317 for(int i=0; i<6; i++) { 1.318 @@ -338,7 +313,7 @@ 1.319 if(rotmask & (1 << i)) { 1.320 face.rotate_180(); 1.321 } 1.322 - set_image(face, i); 1.323 + set_image_cube(face, i); 1.324 } 1.325 return true; 1.326 } 1.327 @@ -431,13 +406,54 @@ 1.328 return 0; 1.329 } 1.330 1.331 +static unsigned int type_to_target(TextureType type) 1.332 +{ 1.333 + return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; 1.334 +} 1.335 + 1.336 +static TextureType target_to_type(unsigned int targ) 1.337 +{ 1.338 + return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D; 1.339 +} 1.340 + 1.341 // ---- TextureSet ---- 1.342 -static void destroy_texture(Texture *tex) 1.343 +TextureSet::TextureSet() 1.344 + : DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex) 1.345 +{ 1.346 +} 1.347 + 1.348 +// static callbacks 1.349 + 1.350 +Texture *TextureSet::create_tex() 1.351 +{ 1.352 + return new Texture; 1.353 +} 1.354 + 1.355 +bool TextureSet::load_tex(Texture *tex, const char *fname) 1.356 +{ 1.357 + Image *img = new Image; 1.358 + if(!img->load(fname)) { 1.359 + delete img; 1.360 + return false; 1.361 + } 1.362 + 1.363 + delete tex->img; 1.364 + tex->img = img; 1.365 + 1.366 + return true; 1.367 +} 1.368 + 1.369 +bool TextureSet::done_tex(Texture *tex) 1.370 +{ 1.371 + if(!tex->img) { 1.372 + return false; 1.373 + } 1.374 + 1.375 + tex->set_image(*tex->img); 1.376 + return true; 1.377 +} 1.378 + 1.379 +void TextureSet::free_tex(Texture *tex) 1.380 { 1.381 delete tex; 1.382 } 1.383 - 1.384 -TextureSet::TextureSet() 1.385 - : DataSet<Texture*>(load_texture, destroy_texture) 1.386 -{ 1.387 -}