1 #define STB_IMAGE_IMPLEMENTATION
2 #include <stb/stb_image.h>
4 #include <dragonstd/tree.h>
5 #include "client/client_config.h"
6 #include "client/texture.h"
15 static int cmp_texture(TextureLookup *texture, char *path)
17 return strcmp(texture->path, path);
20 static bool lookup_texture(char *path, Texture **texture)
22 TreeNode **node = tree_nfd(&textures, path, &cmp_texture);
25 *texture = &((TextureLookup *) &(*node)->dat)->texture;
29 TextureLookup *lookup = malloc(sizeof *lookup);
30 lookup->path = strdup(path);
31 *texture = &lookup->texture;
33 tree_nmk(&textures, node, lookup);
37 static void delete_texture(TextureLookup *lookup)
40 texture_destroy(&lookup->texture);
44 __attribute__((constructor(101))) static void textures_init()
49 __attribute__((destructor)) static void textures_deinit()
51 tree_clr(&textures, &delete_texture, NULL, NULL, 0);
54 Texture *texture_load(char *path, bool mipmap)
57 if (lookup_texture(path, &texture))
60 unsigned char *data = stbi_load(path,
61 &texture->width, &texture->height, &texture->channels, 0);
63 fprintf(stderr, "[error] failed to load texture %s\n", path);
67 texture_upload(texture, data, GL_RGBA, mipmap);
68 stbi_image_free(data);
73 Texture *texture_load_cubemap(char *path)
76 if (lookup_texture(path, &texture))
79 glGenTextures(1, &texture->txo);
80 glBindTexture(GL_TEXTURE_CUBE_MAP, texture->txo);
82 const char *directions[6] = {
91 for (int i = 0; i < 6; i++) {
92 char filename[strlen(path) + 1 + strlen(directions[i]) + 1 + 3 + 1];
93 sprintf(filename, "%s/%s.png", path, directions[i]);
95 unsigned char *data = stbi_load(filename,
96 &texture->width, &texture->height, &texture->channels, 0);
98 fprintf(stderr, "[error] failed to load texture %s\n", filename);
102 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA,
103 texture->width, texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
104 stbi_image_free(data);
107 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
108 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
109 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
110 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
111 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
116 void texture_upload(Texture *texture, unsigned char *data, GLenum format, bool mipmap)
118 glGenTextures(1, &texture->txo);
119 glBindTexture(GL_TEXTURE_2D, texture->txo);
121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mipmap && client_config.mipmap)
122 ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
127 glTexImage2D(GL_TEXTURE_2D, 0, format,
128 texture->width, texture->height, 0, format, GL_UNSIGNED_BYTE, data);
129 glGenerateMipmap(GL_TEXTURE_2D);
132 void texture_destroy(Texture *texture)
134 glDeleteTextures(1, &texture->txo);