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