#include "../util/util.h" #include "renderer.h" #include "texture.h" #include #include #include #include #include #define MAX_HASH_TEXTURES 1024 static Texture *texture_hash_table[MAX_HASH_TEXTURES]; Texture *texture_new(const char *path) { return texture_with_name_new(path, path); } Texture *texture_with_name_new(const char *name, const char *path) { if(strlen(name) > MAX_PATH_LENGTH) Util_FatalError("File following texture name is too long: %s", name); Texture *tex; tex = texture_get(name); if(tex != NULL) return tex; if(render.num_textures >= MAX_TEXTURES) return NULL; /** Alloc the new texture **/ tex = malloc( sizeof(Texture) ); memset(tex, 0, sizeof(Texture) ); tex->number_of_rows = 1; tex->type = GL_TEXTURE_2D; SDL_Surface *data = IMG_Load(path); if(data == NULL) Util_FatalError("Texture %s could not be found!\n", path); glGenTextures(1, &tex->tex_id); glBindTexture(GL_TEXTURE_2D, tex->tex_id); SDL_LockSurface(data); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data->w, data->h, GL_FALSE, GL_RGBA, GL_UNSIGNED_BYTE, data->pixels); SDL_UnlockSurface(data); SDL_FreeSurface(data); /** Configure the texture **/ glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.4); glBindTexture(GL_TEXTURE_2D, 0); /** Register inside the resource manager **/ unsigned int hash_ = Util_Hash( name ); hash_ %= MAX_HASH_TEXTURES; render.textures[render.num_textures] = tex; render.num_textures += 1; strcpy(tex->_name, name); tex->_hash_next = texture_hash_table[hash_]; texture_hash_table[hash_] = tex; tex->hash_ = hash_; /** Return the final result **/ return tex; } Texture *texture_cubemap_new(const char *paths[6]) { return texture_cubemap_with_name_new(paths[0], paths); } Texture *texture_cubemap_with_name_new(const char *name, const char *paths[6]) { Texture *tex; tex = texture_get(name); if(tex != NULL) { puts("s"); return tex; } if(render.num_textures >= MAX_TEXTURES) return NULL; /** Alloc the new texture **/ tex = malloc( sizeof(Texture) ); memset(tex, 0, sizeof(Texture) ); tex->number_of_rows = 1; tex->type = GL_TEXTURE_CUBE_MAP; glGenTextures(1, &tex->tex_id); glBindTexture(GL_TEXTURE_CUBE_MAP, tex->tex_id); SDL_Surface *data; int i; for(i = 0; i < 6; i++) { data = IMG_Load(paths[i]); if(data == NULL) Util_FatalError("Texture %s could not be found!\n", paths[i]); SDL_LockSurface(data); /** All the textures sides are linearly stored so we just add "i" **/ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, data->w, data->h, GL_FALSE, GL_RGBA, GL_UNSIGNED_BYTE, data->pixels); SDL_UnlockSurface(data); SDL_FreeSurface(data); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); /** Register inside the resource manager **/ unsigned int hash_ = Util_Hash( name ); hash_ %= MAX_HASH_TEXTURES; render.textures[render.num_textures] = tex; render.num_textures += 1; strcpy(tex->_name, name); tex->_hash_next = texture_hash_table[hash_]; texture_hash_table[hash_] = tex; tex->hash_ = hash_; /** Return the final result **/ return tex; } Texture *texture_get(const char *name) { Texture *tex; unsigned int hash_ = Util_Hash( name ); hash_ %= MAX_HASH_TEXTURES; if(texture_hash_table[hash_] != NULL) { for(tex = texture_hash_table[hash_]; tex; tex = tex->_hash_next) { if( tex->hash_ == hash_ ) return tex; } } return NULL; } void texture_bind(Texture *tex, int slot) { glActiveTexture(GL_TEXTURE0 + slot); if(tex->type != GL_TEXTURE_2D && tex->type != GL_TEXTURE_CUBE_MAP) return; glBindTexture(tex->type, tex->tex_id); } void texture_purge(Texture *tex) { /** Purge the opengl data **/ if(tex->tex_id != 0) { glDeleteTextures(1, &tex->tex_id); tex->tex_id = 0; } }