goat3dgfx
changeset 24:dc5918c62a64
broken: converting to resman
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Mar 2014 22:04:29 +0200 |
parents | 0ac499409edd |
children | 9d581abd0bfb |
files | src/dataset.h src/dataset.inl src/gfxutil.cc src/gfxutil.h src/psyspp.cc src/rtarg.cc src/shader.cc src/shader.h src/texture.cc src/texture.h |
diffstat | 10 files changed, 338 insertions(+), 234 deletions(-) [+] |
line diff
1.1 --- a/src/dataset.h Tue Feb 25 23:47:48 2014 +0200 1.2 +++ b/src/dataset.h Sat Mar 01 22:04:29 2014 +0200 1.3 @@ -21,6 +21,7 @@ 1.4 1.5 #include <string> 1.6 #include <map> 1.7 +#include <resman.h> 1.8 1.9 namespace goatgfx { 1.10 1.11 @@ -28,15 +29,23 @@ 1.12 class DataSet { 1.13 protected: 1.14 mutable std::map<std::string, T> data; 1.15 + mutable struct resman *rman; 1.16 1.17 - T (*load)(const char*); 1.18 + T (*create)(); 1.19 + bool (*load)(T, const char*); 1.20 + bool (*done)(T); 1.21 void (*destroy)(T); 1.22 1.23 + static int dataset_load_func(const char *fname, int id, void *cls); 1.24 + static int dataset_done_func(int id, void *cls); 1.25 + static void dataset_destroy_func(int id, void *cls); 1.26 + 1.27 public: 1.28 - DataSet(T (*load_func)(const char*), void (*destr_func)(T) = 0); 1.29 + DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T) = 0, void (*destr_func)(T) = 0); 1.30 ~DataSet(); 1.31 1.32 void clear(); 1.33 + void update(); 1.34 1.35 T get(const char *name) const; 1.36 };
2.1 --- a/src/dataset.inl Tue Feb 25 23:47:48 2014 +0200 2.2 +++ b/src/dataset.inl Sat Mar 01 22:04:29 2014 +0200 2.3 @@ -5,28 +5,38 @@ 2.4 namespace goatgfx { 2.5 2.6 template <typename T> 2.7 -DataSet<T>::DataSet(T (*load_func)(const char*), void (*destr_func)(T)) 2.8 +DataSet<T>::DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T), void (*destr_func)(T)) 2.9 { 2.10 + create = create_func; 2.11 load = load_func; 2.12 + done = done_func; 2.13 destroy = destr_func; 2.14 + 2.15 + rman = resman_create(); 2.16 + resman_set_load_func(rman, dataset_load_func, this); 2.17 + resman_set_done_func(rman, dataset_done_func, this); 2.18 + resman_set_destroy_func(rman, dataset_destroy_func, this); 2.19 } 2.20 2.21 template <typename T> 2.22 DataSet<T>::~DataSet() 2.23 { 2.24 - clear(); 2.25 + resman_free(rman); 2.26 } 2.27 2.28 template <typename T> 2.29 void DataSet<T>::clear() 2.30 { 2.31 - if(destroy) { 2.32 - typename std::map<std::string, T>::iterator it = data.begin(); 2.33 - while(it != data.end()) { 2.34 - destroy(it++->second); 2.35 - } 2.36 - } 2.37 + resman_free(rman); 2.38 data.clear(); 2.39 + 2.40 + rman = resman_create(); 2.41 +} 2.42 + 2.43 +template <typename T> 2.44 +void DataSet<T>::update() 2.45 +{ 2.46 + resman_poll(rman); 2.47 } 2.48 2.49 template <typename T> 2.50 @@ -37,17 +47,68 @@ 2.51 return iter->second; 2.52 } 2.53 2.54 - std::string path = goatgfx::datafile_path(name); 2.55 + const char *fname, *slash; 2.56 + if((slash = strrchr(name, '/'))) { 2.57 + fname = slash + 1; 2.58 + } else { 2.59 + fname = name; 2.60 + } 2.61 + 2.62 + std::string path = datafile_path(fname); 2.63 if(path.empty()) { 2.64 fprintf(stderr, "can't find data file: %s\n", name); 2.65 return 0; 2.66 } 2.67 2.68 - T res = load(path.c_str()); 2.69 - if(res) { 2.70 - data[name] = res; 2.71 - } 2.72 + T res = create(); 2.73 + resman_lookup(rman, path.c_str(), res); 2.74 return res; 2.75 } 2.76 2.77 + 2.78 +// --- static functions to pass as callback to resman --- 2.79 + 2.80 +template <typename T> 2.81 +int DataSet<T>::dataset_load_func(const char *fname, int id, void *cls) 2.82 +{ 2.83 + DataSet<T> *dset = (DataSet<T>*)cls; 2.84 + T data = (T)resman_get_res_data(dset->rman, id); 2.85 + 2.86 + if(!dset->load(data, fname)) { 2.87 + return -1; 2.88 + } 2.89 + return 0; 2.90 +} 2.91 + 2.92 +template <typename T> 2.93 +int DataSet<T>::dataset_done_func(int id, void *cls) 2.94 +{ 2.95 + DataSet<T> *dset = (DataSet<T>*)cls; 2.96 + 2.97 + T data = (T)resman_get_res_data(dset->rman, id); 2.98 + int load_res = resman_get_res_result(dset->rman, id); 2.99 + 2.100 + if(load_res != 0) { 2.101 + fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(dset->rman, id)); 2.102 + } else { 2.103 + printf("done loading resource %d (%s)\n", id, resman_get_res_name(dset->rman, id)); 2.104 + } 2.105 + 2.106 + if(dset->done) { 2.107 + dset->done(data); 2.108 + } 2.109 + return 0; 2.110 +} 2.111 + 2.112 +template <typename T> 2.113 +void DataSet<T>::dataset_destroy_func(int id, void *cls) 2.114 +{ 2.115 + DataSet<T> *dset = (DataSet<T>*)cls; 2.116 + T data = (T)resman_get_res_data(dset->rman, id); 2.117 + 2.118 + if(dset->destroy) { 2.119 + dset->destroy(data); 2.120 + } 2.121 +} 2.122 + 2.123 } // namespace goatgfx
3.1 --- a/src/gfxutil.cc Tue Feb 25 23:47:48 2014 +0200 3.2 +++ b/src/gfxutil.cc Sat Mar 01 22:04:29 2014 +0200 3.3 @@ -10,7 +10,7 @@ 3.4 3.5 using namespace goatgfx; 3.6 3.7 -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex, ShaderProg *sdr) 3.8 +void goatgfx::draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex, ShaderProg *sdr) 3.9 { 3.10 static ShaderProg *defsdr; 3.11 3.12 @@ -29,7 +29,7 @@ 3.13 3.14 3.15 if(tex) { 3.16 - set_texture(tex); 3.17 + bind_texture(tex); 3.18 } 3.19 if(sdr) { 3.20 sdr->bind(); 3.21 @@ -62,5 +62,5 @@ 3.22 glDisableVertexAttribArray(MESH_ATTR_VERTEX); 3.23 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD); 3.24 3.25 - set_texture(0); 3.26 + bind_texture(0); 3.27 }
4.1 --- a/src/gfxutil.h Tue Feb 25 23:47:48 2014 +0200 4.2 +++ b/src/gfxutil.h Sat Mar 01 22:04:29 2014 +0200 4.3 @@ -5,10 +5,10 @@ 4.4 4.5 namespace goatgfx { 4.6 4.7 -class Texture2D; 4.8 +class Texture; 4.9 class ShaderProg; 4.10 4.11 -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex = 0, ShaderProg *sdr = 0); 4.12 +void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex = 0, ShaderProg *sdr = 0); 4.13 4.14 } // namespace goatgfx 4.15
5.1 --- a/src/psyspp.cc Tue Feb 25 23:47:48 2014 +0200 5.2 +++ b/src/psyspp.cc Sat Mar 01 22:04:29 2014 +0200 5.3 @@ -263,7 +263,7 @@ 5.4 unsigned int *pvidx; 5.5 5.6 static ShaderProg *psdr; // particle shader 5.7 -static Texture2D *blank_tex; 5.8 +static Texture *blank_tex; 5.9 5.10 static inline void init_particle_draw() 5.11 { 5.12 @@ -312,7 +312,7 @@ 5.13 5.14 // create empty texture 5.15 Image *img = texgen_solid(8, 8, Vector4(1, 1, 1, 1)); 5.16 - blank_tex = new Texture2D; 5.17 + blank_tex = new Texture; 5.18 blank_tex->set_image(*img); 5.19 delete img; 5.20
6.1 --- a/src/rtarg.cc Tue Feb 25 23:47:48 2014 +0200 6.2 +++ b/src/rtarg.cc Sat Mar 01 22:04:29 2014 +0200 6.3 @@ -40,7 +40,7 @@ 6.4 int tex_height = next_pow2(height); 6.5 6.6 CHECKGLERR; 6.7 - color_tex = new Texture2D; 6.8 + color_tex = new Texture; 6.9 color_tex->create(tex_width, tex_height, fmt); 6.10 CHECKGLERR; 6.11 tex_face = 0;
7.1 --- a/src/shader.cc Tue Feb 25 23:47:48 2014 +0200 7.2 +++ b/src/shader.cc Sat Mar 01 22:04:29 2014 +0200 7.3 @@ -6,7 +6,6 @@ 7.4 #include "shader.h" 7.5 #include "logger.h" 7.6 #include "unistate.h" 7.7 -#include "mesh.h" 7.8 7.9 #ifdef _MSC_VER 7.10 #include <malloc.h> 7.11 @@ -21,8 +20,7 @@ 7.12 #define HAVE_TESSELATION_SHADER 7.13 #endif 7.14 7.15 -static void bind_standard_attr(const ShaderProg *prog); 7.16 -static const char *strtype(unsigned int type); 7.17 +static std::string read_source(const char *fname); 7.18 7.19 ShaderProg *ShaderProg::current; 7.20 7.21 @@ -43,11 +41,9 @@ 7.22 return ShaderProg::current; 7.23 } 7.24 7.25 - 7.26 Shader::Shader() 7.27 { 7.28 sdr = type = 0; 7.29 - name = 0; 7.30 } 7.31 7.32 Shader::~Shader() 7.33 @@ -62,14 +58,12 @@ 7.34 7.35 void Shader::set_name(const char *name) 7.36 { 7.37 - delete [] this->name; 7.38 - this->name = new char[strlen(name) + 1]; 7.39 - strcpy(this->name, name); 7.40 + this->name = std::string(name); 7.41 } 7.42 7.43 const char *Shader::get_name() const 7.44 { 7.45 - return name; 7.46 + return name.c_str(); 7.47 } 7.48 7.49 bool Shader::create(const char *src, unsigned int type) 7.50 @@ -80,11 +74,14 @@ 7.51 const char *src_arr[] = { "precision mediump float; ", src }; 7.52 #endif 7.53 7.54 + // keep a copy of the source code 7.55 + this->src = std::string(src); 7.56 + 7.57 if(!sdr) { 7.58 sdr = glCreateShader(type); 7.59 } 7.60 7.61 - info_log("compiling shader: %s... ", name ? name : ""); 7.62 + info_log("compiling shader: %s... ", name.c_str()); 7.63 7.64 glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0); 7.65 glCompileShader(sdr); 7.66 @@ -118,17 +115,17 @@ 7.67 } 7.68 sdr = type = 0; 7.69 7.70 - delete [] name; 7.71 - name = 0; 7.72 + src.clear(); 7.73 + name.clear(); 7.74 } 7.75 7.76 -bool Shader::load(const char *fname, unsigned int type) 7.77 +static std::string read_source(const char *fname) 7.78 { 7.79 FILE *fp; 7.80 7.81 - if(!(fp = fopen(fname, "rb"))) { 7.82 - error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); 7.83 - return false; 7.84 + if(!(fp = fopen(datafile_path(fname).c_str(), "rb"))) { 7.85 + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); 7.86 + return std::string(); 7.87 } 7.88 7.89 fseek(fp, 0, SEEK_END); 7.90 @@ -137,15 +134,25 @@ 7.91 7.92 char *src = (char*)alloca(sz + 1); 7.93 if(fread(src, 1, sz, fp) < (size_t)sz) { 7.94 - error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); 7.95 + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); 7.96 fclose(fp); 7.97 - return false; 7.98 + delete [] src; 7.99 + return std::string(); 7.100 } 7.101 src[sz] = 0; 7.102 fclose(fp); 7.103 7.104 + return std::string(src); 7.105 +} 7.106 + 7.107 +bool Shader::load(const char *fname, unsigned int type) 7.108 +{ 7.109 + std::string src = read_source(fname); 7.110 + if(src.empty()) { 7.111 + return false; 7.112 + } 7.113 set_name(fname); 7.114 - return create(src, type); 7.115 + return create(src.c_str(), type); 7.116 } 7.117 7.118 // ---- shader program ---- 7.119 @@ -191,6 +198,7 @@ 7.120 src = va_arg(ap, const char*); 7.121 type = va_arg(ap, unsigned int); 7.122 } 7.123 + 7.124 return link(); 7.125 } 7.126 7.127 @@ -309,7 +317,6 @@ 7.128 if(status) { 7.129 must_link = false; 7.130 cache_state_uniforms(); 7.131 - 7.132 return true; 7.133 } 7.134 return false; 7.135 @@ -524,78 +531,89 @@ 7.136 } 7.137 } 7.138 7.139 -// ---- ShaderSet ---- 7.140 -static Shader *load_shader(const char *fname, unsigned int type) 7.141 +// Static functions to use with ShaderSet 7.142 +Shader *Shader::create_shader() 7.143 { 7.144 - Shader *sdr = new Shader; 7.145 - if(!sdr->load(fname, type)) { 7.146 - delete sdr; 7.147 - return 0; 7.148 - } 7.149 - return sdr; 7.150 + return new Shader; 7.151 } 7.152 7.153 -static Shader *load_vertex_shader(const char *fname) 7.154 +bool Shader::load_shader(Shader *sdr, const char *fname) 7.155 { 7.156 - return load_shader(fname, GL_VERTEX_SHADER); 7.157 + std::string src = read_source(fname); 7.158 + if(src.empty()) { 7.159 + return false; 7.160 + } 7.161 + 7.162 + sdr->src = src; 7.163 + return true; 7.164 } 7.165 7.166 -static Shader *load_pixel_shader(const char *fname) 7.167 +bool Shader::done_shader(Shader *sdr, unsigned int type) 7.168 { 7.169 - return load_shader(fname, GL_FRAGMENT_SHADER); 7.170 + return sdr->create(sdr->src.c_str(), type); 7.171 +} 7.172 + 7.173 +static bool done_vertex_shader(Shader *sdr) 7.174 +{ 7.175 + return Shader::done_shader(sdr, GL_VERTEX_SHADER); 7.176 +} 7.177 + 7.178 +static bool done_pixel_shader(Shader *sdr) 7.179 +{ 7.180 + return Shader::done_shader(sdr, GL_FRAGMENT_SHADER); 7.181 } 7.182 7.183 #ifdef HAVE_GEOMETRY_SHADER 7.184 -static Shader *load_geom_shader(const char *fname) 7.185 +static bool done_geom_shader(Shader *sdr) 7.186 { 7.187 - return load_shader(fname, GL_GEOMETRY_SHADER); 7.188 + return Shader::done_shader(sdr, GL_GEOMETRY_SHADER); 7.189 } 7.190 #endif 7.191 7.192 #ifdef HAVE_TESSELATION_SHADER 7.193 -static Shader *load_tc_shader(const char *fname) 7.194 +static bool done_tc_shader(Shader *sdr) 7.195 { 7.196 - return load_shader(fname, GL_TESS_CONTROL_SHADER); 7.197 + return Shader::done_shader(sdr, GL_TESS_CONTROL_SHADER); 7.198 } 7.199 7.200 -static Shader *load_te_shader(const char *fname) 7.201 +static bool done_te_shader(Shader *sdr) 7.202 { 7.203 - return load_shader(fname, GL_TESS_EVALUATION_SHADER); 7.204 + return Shader::done_shader(sdr, GL_TESS_EVALUATION_SHADER); 7.205 } 7.206 #endif 7.207 7.208 -static void destroy_shader(Shader *sdr) 7.209 +void Shader::destroy_shader(Shader *sdr) 7.210 { 7.211 delete sdr; 7.212 } 7.213 7.214 +// ---- ShaderSet ---- 7.215 + 7.216 ShaderSet::ShaderSet(unsigned int type) 7.217 - : DataSet<Shader*>(0, destroy_shader) 7.218 + : DataSet<Shader*>(Shader::create_shader, Shader::load_shader, 0, Shader::destroy_shader) 7.219 { 7.220 - this->type = type; 7.221 - 7.222 switch(type) { 7.223 case GL_VERTEX_SHADER: 7.224 - load = load_vertex_shader; 7.225 + done = done_vertex_shader; 7.226 break; 7.227 7.228 case GL_FRAGMENT_SHADER: 7.229 - load = load_pixel_shader; 7.230 + done = done_pixel_shader; 7.231 break; 7.232 7.233 #ifdef HAVE_GEOMETRY_SHADER 7.234 case GL_GEOMETRY_SHADER: 7.235 - load = load_geom_shader; 7.236 + done = done_geom_shader; 7.237 break; 7.238 #endif 7.239 7.240 #ifdef HAVE_TESSELATION_SHADER 7.241 case GL_TESS_CONTROL_SHADER: 7.242 - load = load_tc_shader; 7.243 + done = done_tc_shader; 7.244 break; 7.245 7.246 case GL_TESS_EVALUATION_SHADER: 7.247 - load = load_te_shader; 7.248 + done = done_te_shader; 7.249 break; 7.250 #endif 7.251 7.252 @@ -637,6 +655,7 @@ 7.253 } 7.254 7.255 7.256 +/* 7.257 static const char *strtype(unsigned int type) 7.258 { 7.259 switch(type) { 7.260 @@ -659,3 +678,4 @@ 7.261 } 7.262 return "<unknown>"; 7.263 } 7.264 +*/
8.1 --- a/src/shader.h Tue Feb 25 23:47:48 2014 +0200 8.2 +++ b/src/shader.h Sat Mar 01 22:04:29 2014 +0200 8.3 @@ -2,6 +2,7 @@ 8.4 #define SHADER_H_ 8.5 8.6 #include <vector> 8.7 +#include <string> 8.8 #include "vmath/vmath.h" 8.9 #include "opengl.h" 8.10 #include "dataset.h" 8.11 @@ -19,7 +20,7 @@ 8.12 private: 8.13 unsigned int sdr; 8.14 unsigned int type; 8.15 - char *name; 8.16 + std::string name, src; 8.17 8.18 public: 8.19 Shader(); 8.20 @@ -34,6 +35,13 @@ 8.21 void destroy(); 8.22 8.23 bool load(const char *fname, unsigned int type); 8.24 + 8.25 + 8.26 + // these functions are only meant to be used by the ShaderSet 8.27 + static Shader *create_shader(); 8.28 + static bool load_shader(Shader *sdr, const char *fname); 8.29 + static bool done_shader(Shader *sdr, unsigned int type); 8.30 + static void destroy_shader(Shader *sdr); 8.31 }; 8.32 8.33 #define VSDR(s) s, GL_VERTEX_SHADER
9.1 --- a/src/texture.cc Tue Feb 25 23:47:48 2014 +0200 9.2 +++ b/src/texture.cc Sat Mar 01 22:04:29 2014 +0200 9.3 @@ -14,14 +14,25 @@ 9.4 9.5 static int glifmt_from_imgfmt(Image::Format fmt); 9.6 9.7 +static unsigned int type_to_target(TextureType type); 9.8 +static TextureType target_to_type(unsigned int targ); 9.9 + 9.10 static unsigned int cur_target[8] = { 9.11 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, 9.12 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D 9.13 }; 9.14 9.15 -namespace goatgfx { 9.16 +static unsigned int cube_faces[] = { 9.17 + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 9.18 + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 9.19 + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 9.20 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 9.21 + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 9.22 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 9.23 +}; 9.24 9.25 -void set_texture(Texture *tex, int tunit) 9.26 + 9.27 +void goatgfx::bind_texture(Texture *tex, int tunit) 9.28 { 9.29 if(tex) { 9.30 tex->bind(tunit); 9.31 @@ -32,30 +43,13 @@ 9.32 } 9.33 } 9.34 9.35 -Texture *load_texture(const char *fname) 9.36 -{ 9.37 - TextureCube *texcube = new TextureCube; 9.38 - if(texcube->load(fname)) { 9.39 - return texcube; 9.40 - } 9.41 - delete texcube; 9.42 - 9.43 - Texture2D *tex = new Texture2D; 9.44 - if(tex->load(fname)) { 9.45 - return tex; 9.46 - } 9.47 - delete tex; 9.48 - return 0; 9.49 -} 9.50 - 9.51 -} // namespace goatgfx 9.52 - 9.53 Texture::Texture() 9.54 { 9.55 target = 0; 9.56 sz[0] = sz[1] = sz[2] = 0; 9.57 texfmt = 0; 9.58 9.59 + img = 0; 9.60 glGenTextures(1, &id); 9.61 } 9.62 9.63 @@ -64,6 +58,9 @@ 9.64 if(id) { 9.65 glDeleteTextures(1, &id); 9.66 } 9.67 + if(img) { 9.68 + delete img; 9.69 + } 9.70 } 9.71 9.72 void Texture::set_wrapping(unsigned int wrap) 9.73 @@ -75,6 +72,7 @@ 9.74 glBindTexture(target, id); 9.75 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); 9.76 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); 9.77 + glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap); 9.78 } 9.79 9.80 void Texture::set_filtering(unsigned int filt) 9.81 @@ -128,6 +126,11 @@ 9.82 return id; 9.83 } 9.84 9.85 +TextureType Texture::get_type() const 9.86 +{ 9.87 + return target_to_type(target); 9.88 +} 9.89 + 9.90 void Texture::bind(int tex_unit) const 9.91 { 9.92 glActiveTexture(GL_TEXTURE0 + tex_unit); 9.93 @@ -138,29 +141,55 @@ 9.94 } 9.95 9.96 9.97 -// ---- Texture2D ---- 9.98 +void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt) 9.99 +{ 9.100 + if(textype == TEX_CUBE && xsz != ysz) { 9.101 + error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); 9.102 + return; 9.103 + } 9.104 9.105 -Texture2D::Texture2D() 9.106 -{ 9.107 - target = GL_TEXTURE_2D; 9.108 -} 9.109 - 9.110 -void Texture2D::create(int xsz, int ysz, unsigned int ifmt) 9.111 -{ 9.112 int fmt = glfmt_from_ifmt(ifmt); 9.113 int type = gltype_from_ifmt(ifmt); 9.114 9.115 - glBindTexture(GL_TEXTURE_2D, id); 9.116 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 9.117 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 9.118 - glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); 9.119 + target = type_to_target(textype); 9.120 + 9.121 + glBindTexture(target, id); 9.122 + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 9.123 + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 9.124 + 9.125 + switch(type) { 9.126 + case TEX_2D: 9.127 + glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); 9.128 + break; 9.129 + 9.130 + case TEX_CUBE: 9.131 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 9.132 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 9.133 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 9.134 + for(int i=0; i<6; i++) { 9.135 + glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 9.136 + } 9.137 + break; 9.138 + } 9.139 + 9.140 CHECKGLERR; 9.141 sz[0] = xsz; 9.142 sz[1] = ysz; 9.143 texfmt = ifmt; 9.144 } 9.145 9.146 -void Texture2D::set_image(const Image &img, int idx) 9.147 +void Texture::set_image(const Image &img, int idx) 9.148 +{ 9.149 + if(idx >= 0 && idx < 6) { 9.150 + set_image_cube(img, idx); 9.151 + } else { 9.152 + if(!set_image_cube(img)) { 9.153 + set_image_2d(img); 9.154 + } 9.155 + } 9.156 +} 9.157 + 9.158 +void Texture::set_image_2d(const Image &img) 9.159 { 9.160 texfmt = glifmt_from_imgfmt(img.get_format()); 9.161 unsigned int fmt = glfmt_from_ifmt(texfmt); 9.162 @@ -191,79 +220,12 @@ 9.163 #endif 9.164 } 9.165 9.166 -bool Texture2D::load(const char *fname) 9.167 +bool Texture::set_image_cube(const Image &img, int idx) 9.168 { 9.169 - Image img; 9.170 - if(!img.load(fname)) { 9.171 - error_log("failed to load 2D texture: %s\n", fname); 9.172 - return false; 9.173 - } 9.174 - set_image(img); 9.175 - 9.176 - info_log("loaded 2D texture: %s\n", fname); 9.177 - return true; 9.178 -} 9.179 - 9.180 -bool Texture2D::save(const char *fname) const 9.181 -{ 9.182 -#ifndef GL_ES_VERSION_2_0 9.183 - unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4]; 9.184 - 9.185 - glBindTexture(GL_TEXTURE_2D, id); 9.186 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 9.187 - 9.188 - if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) { 9.189 - error_log("failed to save 2D texture: %s\n", fname); 9.190 - delete [] pixels; 9.191 + if(idx < 0 || idx >= 6) { 9.192 return false; 9.193 } 9.194 9.195 - info_log("saved 2D texture: %s\n", fname); 9.196 - delete [] pixels; 9.197 - return true; 9.198 -#else 9.199 - return false; // TODO 9.200 -#endif 9.201 -} 9.202 - 9.203 -// ---- TextureCube ---- 9.204 -static unsigned int cube_faces[] = { 9.205 - GL_TEXTURE_CUBE_MAP_POSITIVE_X, 9.206 - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 9.207 - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 9.208 - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 9.209 - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 9.210 - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 9.211 -}; 9.212 - 9.213 -TextureCube::TextureCube() 9.214 -{ 9.215 - target = GL_TEXTURE_CUBE_MAP; 9.216 -} 9.217 - 9.218 -void TextureCube::create(int xsz, int ysz, unsigned int ifmt) 9.219 -{ 9.220 - if(xsz != ysz) { 9.221 - error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); 9.222 - return; 9.223 - } 9.224 - 9.225 - texfmt = ifmt; 9.226 - 9.227 - glBindTexture(GL_TEXTURE_CUBE_MAP, id); 9.228 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 9.229 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 9.230 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 9.231 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 9.232 - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 9.233 - 9.234 - for(int i=0; i<6; i++) { 9.235 - glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 9.236 - } 9.237 -} 9.238 - 9.239 -void TextureCube::set_image(const Image &img, int idx) 9.240 -{ 9.241 texfmt = glifmt_from_imgfmt(img.get_format()); 9.242 unsigned int fmt = glfmt_from_ifmt(texfmt); 9.243 unsigned int type = gltype_from_ifmt(texfmt); 9.244 @@ -279,9 +241,10 @@ 9.245 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 9.246 9.247 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); 9.248 + return true; 9.249 } 9.250 9.251 -bool TextureCube::load(const char *fname) 9.252 +bool Texture::set_image_cube(const Image &img) 9.253 { 9.254 static const float one_third = 1.0 / 3.0; 9.255 static const float two_thirds = 2.0 / 3.0; 9.256 @@ -292,37 +255,49 @@ 9.257 static const float hsix[2][6] = { 9.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} }; 9.259 9.260 - Image img; 9.261 - if(!img.load(fname)) { 9.262 - return false; 9.263 - } 9.264 - 9.265 int xsz = img.get_width(); 9.266 int ysz = img.get_height(); 9.267 9.268 if(xsz / 4 == ysz / 3) { 9.269 // horizontal cross, assume the vertical bit is center-left 9.270 - return load_multi(img, hcross[0], hcross[1], xsz / 4); 9.271 + return set_cube_multi(img, hcross[0], hcross[1], xsz / 4); 9.272 } 9.273 if(xsz / 3 == ysz / 4) { 9.274 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) 9.275 - return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); 9.276 + return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); 9.277 } 9.278 if(xsz / 3 == ysz / 2) { 9.279 // horizontal sixpack 9.280 - return load_multi(img, hsix[0], hsix[1], ysz / 2); 9.281 + return set_cube_multi(img, hsix[0], hsix[1], ysz / 2); 9.282 } 9.283 9.284 - error_log("failed to load %s: unknown cubemap configuration\n", fname); 9.285 return false; 9.286 } 9.287 9.288 -bool TextureCube::save(const char *fname) const 9.289 + 9.290 +bool Texture::load(const char *fname) 9.291 { 9.292 - return false; // TODO 9.293 + Image img; 9.294 + if(!img.load(fname)) { 9.295 + error_log("failed to load 2D texture: %s\n", fname); 9.296 + return false; 9.297 + } 9.298 + set_image(img); 9.299 + 9.300 + info_log("loaded 2D texture: %s\n", fname); 9.301 + return true; 9.302 } 9.303 9.304 -bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 9.305 +bool Texture::load_cube(const char *fname) 9.306 +{ 9.307 + Image img; 9.308 + if(!img.load(fname)) { 9.309 + return false; 9.310 + } 9.311 + return set_image_cube(img); 9.312 +} 9.313 + 9.314 +bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 9.315 unsigned int rotmask) 9.316 { 9.317 for(int i=0; i<6; i++) { 9.318 @@ -338,7 +313,7 @@ 9.319 if(rotmask & (1 << i)) { 9.320 face.rotate_180(); 9.321 } 9.322 - set_image(face, i); 9.323 + set_image_cube(face, i); 9.324 } 9.325 return true; 9.326 } 9.327 @@ -431,13 +406,54 @@ 9.328 return 0; 9.329 } 9.330 9.331 +static unsigned int type_to_target(TextureType type) 9.332 +{ 9.333 + return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; 9.334 +} 9.335 + 9.336 +static TextureType target_to_type(unsigned int targ) 9.337 +{ 9.338 + return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D; 9.339 +} 9.340 + 9.341 // ---- TextureSet ---- 9.342 -static void destroy_texture(Texture *tex) 9.343 +TextureSet::TextureSet() 9.344 + : DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex) 9.345 +{ 9.346 +} 9.347 + 9.348 +// static callbacks 9.349 + 9.350 +Texture *TextureSet::create_tex() 9.351 +{ 9.352 + return new Texture; 9.353 +} 9.354 + 9.355 +bool TextureSet::load_tex(Texture *tex, const char *fname) 9.356 +{ 9.357 + Image *img = new Image; 9.358 + if(!img->load(fname)) { 9.359 + delete img; 9.360 + return false; 9.361 + } 9.362 + 9.363 + delete tex->img; 9.364 + tex->img = img; 9.365 + 9.366 + return true; 9.367 +} 9.368 + 9.369 +bool TextureSet::done_tex(Texture *tex) 9.370 +{ 9.371 + if(!tex->img) { 9.372 + return false; 9.373 + } 9.374 + 9.375 + tex->set_image(*tex->img); 9.376 + return true; 9.377 +} 9.378 + 9.379 +void TextureSet::free_tex(Texture *tex) 9.380 { 9.381 delete tex; 9.382 } 9.383 - 9.384 -TextureSet::TextureSet() 9.385 - : DataSet<Texture*>(load_texture, destroy_texture) 9.386 -{ 9.387 -}
10.1 --- a/src/texture.h Tue Feb 25 23:47:48 2014 +0200 10.2 +++ b/src/texture.h Sat Mar 01 22:04:29 2014 +0200 10.3 @@ -8,19 +8,32 @@ 10.4 10.5 class Image; 10.6 10.7 +enum TextureType { TEX_2D, TEX_CUBE }; 10.8 + 10.9 class Texture { 10.10 -protected: 10.11 +private: 10.12 unsigned int id; 10.13 unsigned int target; 10.14 unsigned int texfmt; 10.15 int sz[3]; 10.16 + Image *img; 10.17 10.18 Texture(const Texture &tex) {} 10.19 Texture &operator =(const Texture &tex) { return *this; } 10.20 10.21 + void set_image_2d(const Image &img); 10.22 + bool set_image_cube(const Image &img, int idx); 10.23 + bool set_image_cube(const Image &img); 10.24 + 10.25 + bool load_cube(const char *fname); 10.26 + 10.27 + /* for loading multiple cubemap faces from a single image */ 10.28 + bool set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 10.29 + unsigned int rotmask = 0); 10.30 + 10.31 public: 10.32 Texture(); 10.33 - virtual ~Texture(); 10.34 + ~Texture(); 10.35 10.36 void set_wrapping(unsigned int wrap); 10.37 void set_filtering(unsigned int filt); 10.38 @@ -28,53 +41,30 @@ 10.39 10.40 unsigned int get_format() const; 10.41 10.42 - virtual int get_size(int dim) const; 10.43 + int get_size(int dim) const; 10.44 10.45 - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA) = 0; 10.46 - virtual void set_image(const Image &img, int idx = 0) = 0; 10.47 + void create(int xsz, int ysz, TextureType type = TEX_2D, unsigned int ifmt = GL_RGBA); 10.48 + void set_image(const Image &img, int idx = -1); 10.49 10.50 - virtual bool load(const char *fname) = 0; 10.51 - virtual bool save(const char *fname) const = 0; 10.52 + bool load(const char *fname); 10.53 10.54 - virtual unsigned int get_id() const; 10.55 + unsigned int get_id() const; 10.56 + TextureType get_type() const; 10.57 10.58 - virtual void bind(int tex_unit = 0) const; 10.59 + void bind(int tex_unit = 0) const; 10.60 + 10.61 + friend class TextureSet; 10.62 }; 10.63 10.64 -class Texture2D : public Texture { 10.65 -public: 10.66 - Texture2D(); 10.67 - 10.68 - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); 10.69 - virtual void set_image(const Image &img, int idx = 0); 10.70 - 10.71 - virtual bool load(const char *fname); 10.72 - virtual bool save(const char *fname) const; 10.73 -}; 10.74 - 10.75 -class TextureCube : public Texture { 10.76 -private: 10.77 - bool load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 10.78 - unsigned int rotmask = 0); 10.79 - 10.80 -public: 10.81 - TextureCube(); 10.82 - 10.83 - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); 10.84 - virtual void set_image(const Image &img, int idx = 0); 10.85 - 10.86 - virtual bool load(const char *fname); 10.87 - virtual bool save(const char *fname) const; 10.88 -}; 10.89 - 10.90 -void set_texture(Texture *tex, int tunit = 0); 10.91 - 10.92 -/** loads a texture autodetecting whether it's a 2D texture or 10.93 - * cubemap and creating the correct Texture subclass instance. 10.94 - */ 10.95 -Texture *load_texture(const char *fname); 10.96 +void bind_texture(Texture *tex, int tunit = 0); 10.97 10.98 class TextureSet : public DataSet<Texture*> { 10.99 +private: 10.100 + static Texture *create_tex(); 10.101 + static bool load_tex(Texture *tex, const char *fname); 10.102 + static bool done_tex(Texture *tex); 10.103 + static void free_tex(Texture *tex); 10.104 + 10.105 public: 10.106 TextureSet(); 10.107 };