tavli
diff src/image.cc @ 4:b41ceead1708
procedural playing field texture mask
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 25 Jun 2015 05:58:35 +0300 |
parents | |
children | c2a2069a49ec |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/image.cc Thu Jun 25 05:58:35 2015 +0300 1.3 @@ -0,0 +1,228 @@ 1.4 +#include <string.h> 1.5 +#include "opengl.h" 1.6 +#include "image.h" 1.7 +#include "imago2.h" 1.8 + 1.9 + 1.10 +static unsigned int next_pow2(unsigned int x); 1.11 + 1.12 +Image::Image() 1.13 +{ 1.14 + width = height = tex_width = tex_height = 0; 1.15 + pixels = 0; 1.16 + tex = 0; 1.17 + tex_valid = false; 1.18 +} 1.19 + 1.20 +Image::~Image() 1.21 +{ 1.22 + destroy(); 1.23 +} 1.24 + 1.25 +Image::Image(const Image &img) 1.26 +{ 1.27 + pixels = 0; 1.28 + create(img.width, img.height, img.pixels); 1.29 +} 1.30 + 1.31 +Image &Image::operator =(const Image &img) 1.32 +{ 1.33 + if(&img != this) { 1.34 + create(img.width, img.height, img.pixels); 1.35 + } 1.36 + return *this; 1.37 +} 1.38 + 1.39 +bool Image::create(int width, int height, unsigned char *pixels) 1.40 +{ 1.41 + destroy(); 1.42 + 1.43 + try { 1.44 + unsigned char *tmp = new unsigned char[width * height * 3]; 1.45 + this->pixels = tmp; 1.46 + this->width = width; 1.47 + this->height = height; 1.48 + } 1.49 + catch(...) { 1.50 + return false; 1.51 + } 1.52 + 1.53 + if(pixels) { 1.54 + memcpy(this->pixels, pixels, width * height * 3); 1.55 + } 1.56 + return true; 1.57 +} 1.58 + 1.59 +void Image::destroy() 1.60 +{ 1.61 + delete [] pixels; 1.62 + pixels = 0; 1.63 + width = height = 0; 1.64 + 1.65 + if(tex) { 1.66 + glDeleteTextures(1, &tex); 1.67 + tex = 0; 1.68 + tex_valid = false; 1.69 + } 1.70 +} 1.71 + 1.72 +bool Image::load(const char *fname) 1.73 +{ 1.74 + int xsz, ysz; 1.75 + unsigned char *pix = (unsigned char*)img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGB24); 1.76 + if(!pix) { 1.77 + return false; 1.78 + } 1.79 + return create(xsz, ysz, pix); 1.80 +} 1.81 + 1.82 +unsigned int Image::texture() const 1.83 +{ 1.84 + if(!pixels) { 1.85 + return 0; 1.86 + } 1.87 + if(!tex) { 1.88 + glGenTextures(1, &tex); 1.89 + } 1.90 + 1.91 + if(!tex_valid) { 1.92 + tex_width = next_pow2(width); 1.93 + tex_height = next_pow2(height); 1.94 + 1.95 + glBindTexture(GL_TEXTURE_2D, tex); 1.96 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1.97 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.98 + 1.99 + if(GLEW_SGIS_generate_mipmap) { 1.100 + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1); 1.101 + 1.102 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 1.103 + width == tex_width && height == tex_height ? pixels : 0); 1.104 + if(width != tex_width || height != tex_height) { 1.105 + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); 1.106 + } 1.107 + } else { 1.108 + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, tex_width, tex_height, GL_RGB, GL_UNSIGNED_BYTE, pixels); 1.109 + } 1.110 + 1.111 + if(GLEW_EXT_texture_filter_anisotropic) { 1.112 + static float max_aniso = -1.0; 1.113 + 1.114 + if(max_aniso < 0.0) { 1.115 + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_aniso); 1.116 + printf("using anisotropic filtering: x%g\n", max_aniso); 1.117 + } 1.118 + 1.119 + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso); 1.120 + } 1.121 + tex_valid = true; 1.122 + } 1.123 + return tex; 1.124 +} 1.125 + 1.126 +int Image::texture_width() const 1.127 +{ 1.128 + return tex_width; 1.129 +} 1.130 + 1.131 +int Image::texture_height() const 1.132 +{ 1.133 + return tex_height; 1.134 +} 1.135 + 1.136 +void Image::invalidate_texture() 1.137 +{ 1.138 + tex_valid = false; 1.139 +} 1.140 + 1.141 + 1.142 +void clear_image(Image *img) 1.143 +{ 1.144 + clear_image(img, 0, 0, 0); 1.145 +} 1.146 + 1.147 +void clear_image(Image *img, float r, float g, float b) 1.148 +{ 1.149 + if(!img->pixels) { 1.150 + return; 1.151 + } 1.152 + 1.153 + unsigned char col[3]; 1.154 + unsigned char *ptr = img->pixels; 1.155 + int npix = img->width * img->height; 1.156 + 1.157 + col[0] = (int)(r * 255.0); 1.158 + col[1] = (int)(g * 255.0); 1.159 + col[2] = (int)(b * 255.0); 1.160 + 1.161 + for(int i=0; i<npix; i++) { 1.162 + for(int j=0; j<3; j++) { 1.163 + ptr[j] = col[j]; 1.164 + } 1.165 + ptr += 3; 1.166 + } 1.167 +} 1.168 + 1.169 +bool combine_image(Image *dest, const Image *aimg, const Image *bimg, ImgCombine op, float t) 1.170 +{ 1.171 + int xsz = dest->width; 1.172 + int ysz = dest->height; 1.173 + int npixels = xsz * ysz; 1.174 + int nbytes = npixels * 3; 1.175 + int tint = (int)(t * 255); 1.176 + 1.177 + if(aimg->width != xsz || bimg->width != xsz || aimg->height != ysz || bimg->height != ysz) { 1.178 + return false; 1.179 + } 1.180 + 1.181 + unsigned char *dptr = dest->pixels; 1.182 + const unsigned char *aptr = aimg->pixels; 1.183 + const unsigned char *bptr = bimg->pixels; 1.184 + 1.185 + switch(op) { 1.186 + case IMG_OP_ADD: 1.187 + for(int i=0; i<nbytes; i++) { 1.188 + unsigned int x = *aptr++ + *bptr++; 1.189 + *dptr++ = x > 255 ? 255 : x; 1.190 + } 1.191 + break; 1.192 + 1.193 + case IMG_OP_SUB: 1.194 + for(int i=0; i<nbytes; i++) { 1.195 + int x = (int)*aptr++ - (int)*bptr++; 1.196 + *dptr++ = x < 0 ? 0 : x; 1.197 + } 1.198 + break; 1.199 + 1.200 + case IMG_OP_MUL: 1.201 + for(int i=0; i<nbytes; i++) { 1.202 + unsigned int x = ((unsigned int)*aptr++ * (unsigned int)*bptr++) >> 8; 1.203 + *dptr++ = x > 255 ? 255 : x; 1.204 + } 1.205 + break; 1.206 + 1.207 + case IMG_OP_LERP: 1.208 + for(int i=0; i<nbytes; i++) { 1.209 + int x = (int)*aptr + ((((int)*bptr - (int)*aptr) * tint) >> 8); 1.210 + *dptr++ = x > 255 ? 255 : (x < 0 ? 0 : x); 1.211 + } 1.212 + break; 1.213 + 1.214 + default: 1.215 + break; 1.216 + } 1.217 + 1.218 + dest->invalidate_texture(); 1.219 + return true; 1.220 +} 1.221 + 1.222 +static unsigned int next_pow2(unsigned int x) 1.223 +{ 1.224 + x--; 1.225 + x = (x >> 1) | x; 1.226 + x = (x >> 2) | x; 1.227 + x = (x >> 4) | x; 1.228 + x = (x >> 8) | x; 1.229 + x = (x >> 16) | x; 1.230 + return x + 1; 1.231 +}