aboutsummaryrefslogtreecommitdiff
path: root/09-september/tomcat/renderer/texture.c
diff options
context:
space:
mode:
Diffstat (limited to '09-september/tomcat/renderer/texture.c')
-rw-r--r--09-september/tomcat/renderer/texture.c188
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;
+ }
+}