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 -}