diff options
| author | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:02:32 +0100 |
|---|---|---|
| committer | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:02:32 +0100 |
| commit | 6b8af9cf83851c075c6c9514b1deaa931c2b19a4 (patch) | |
| tree | 428986b49c32e21d3f7a3c2dfa41858ae0153209 /09-september/tomcat/renderer/texture.c | |
Initial commit
Diffstat (limited to '09-september/tomcat/renderer/texture.c')
| -rw-r--r-- | 09-september/tomcat/renderer/texture.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/09-september/tomcat/renderer/texture.c b/09-september/tomcat/renderer/texture.c new file mode 100644 index 0000000..e653c5a --- /dev/null +++ b/09-september/tomcat/renderer/texture.c @@ -0,0 +1,188 @@ +#include "../util/util.h" +#include "renderer.h" +#include "texture.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <SDL2/SDL.h> +#include <SDL2/SDL_image.h> + +#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; + } +} |
