]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/texture.c
2fa16803218947a498d7cd9b7a75c3c62773b6fb
[dragonblocks_alpha.git] / src / client / texture.c
1 #define STB_IMAGE_IMPLEMENTATION
2 #include <stb/stb_image.h>
3 #include <stdbool.h>
4 #include <dragontype/list.h>
5 #include "client/texture.h"
6 #include "util.h"
7
8 static List textures;
9
10 __attribute((constructor(101))) static void textures_init()
11 {
12         textures = list_create(&list_compare_string);
13 }
14
15 static void list_delete_texture(unused void *key, void *value, unused void *arg)
16 {
17         texture_delete(value);
18 }
19
20 __attribute((destructor)) static void textures_deinit()
21 {
22         list_clear_func(&textures, &list_delete_texture, NULL);
23 }
24
25 Texture *texture_create(unsigned char *data, int width, int height, GLenum format)
26 {
27         Texture *texture = malloc(sizeof(Texture));
28         texture->width = width;
29         texture->height = height;
30
31         glGenTextures(1, &texture->id);
32
33         glBindTexture(GL_TEXTURE_2D, texture->id);
34
35         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
36         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
37         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
38         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
39
40         glTexImage2D(GL_TEXTURE_2D, 0, format, texture->width, texture->height, 0, format, GL_UNSIGNED_BYTE, data);
41         glGenerateMipmap(GL_TEXTURE_2D);
42
43         glBindTexture(GL_TEXTURE_2D, 0);
44
45         return texture;
46 }
47
48 GLuint texture_create_cubemap(char *path)
49 {
50         GLuint id;
51         glGenTextures(1, &id);
52
53         glBindTexture(GL_TEXTURE_CUBE_MAP, id);
54
55         const char *directions[6] = {
56                 "right",
57                 "left",
58                 "top",
59                 "bottom",
60                 "front",
61                 "back",
62         };
63
64         for (int i = 0; i < 6; i++) {
65                 char filename[strlen(path) + 1 + strlen(directions[i]) + 1 + 3 + 1];
66                 sprintf(filename, "%s/%s.png", path, directions[i]);
67
68                 int width, height, channels;
69                 unsigned char *data = stbi_load(filename, &width, &height, &channels, 0);
70                 if (! data) {
71                         fprintf(stderr, "Failed to load texture %s\n", filename);
72                         return 0;
73                 }
74
75                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
76                 stbi_image_free(data);
77         }
78
79         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
80         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
81         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
82         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
83         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
84
85         return id;
86 }
87
88 void texture_delete(Texture *texture)
89 {
90         glDeleteTextures(1, &texture->id);
91         free(texture);
92 }
93
94 static void *create_image_texture(void *key)
95 {
96         int width, height, channels;
97
98         unsigned char *data = stbi_load(key, &width, &height, &channels, 0);
99         if (! data) {
100                 fprintf(stderr, "Failed to load texture %s\n", (char *) key);
101                 return 0;
102         }
103
104         Texture *texture = texture_create(data, width, height, GL_RGBA);
105
106         stbi_image_free(data);
107
108         return texture;
109 }
110
111 Texture *texture_get(char *path)
112 {
113         return list_get_cached(&textures, path, &create_image_texture);
114 }