]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/shaders.c
Append .zip to ZIP files generated by release script
[dragonblocks_alpha.git] / src / shaders.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include "shaders.h"
6
7 static GLuint compile_and_attach_shader(GLenum type, const char *path, const char *name, GLuint program)
8 {
9         char full_path[strlen(path) + 1 + strlen(name) + 1 + 4 + 1];
10         sprintf(full_path, "%s/%s.glsl", path, name);
11
12         FILE *file = fopen(full_path, "r");
13         if (! file) {
14                 perror("fopen");
15                 return 0;
16         }
17
18         if (fseek(file, 0, SEEK_END) == -1) {
19                 perror("fseek");
20                 fclose(file);
21                 return 0;
22         }
23
24         long size = ftell(file);
25
26         if (size == 1) {
27                 perror("ftell");
28                 fclose(file);
29                 return 0;
30         }
31
32         if (fseek(file, 0, SEEK_SET) == -1) {
33                 perror("fseek");
34                 fclose(file);
35                 return 0;
36         }
37
38         char code[size];
39
40         if (fread(code, 1, size, file) != (size_t) size) {
41                 perror("fread");
42                 fclose(file);
43                 return 0;
44         }
45
46         fclose(file);
47
48         GLuint id = glCreateShader(type);
49
50         char const *codeptr = code;
51         const int isize = (int) size;
52         glShaderSource(id, 1, &codeptr, &isize);
53
54         glCompileShader(id);
55
56         GLint success;
57         glGetShaderiv(id, GL_COMPILE_STATUS, &success);
58         if (! success) {
59                 char errbuf[BUFSIZ];
60                 glGetShaderInfoLog(id, BUFSIZ, NULL, errbuf);
61                 fprintf(stderr, "Failed to compile %s shader: %s\n", name, errbuf);
62                 glDeleteShader(id);
63                 return 0;
64         }
65
66         glAttachShader(program, id);
67
68         return id;
69 }
70
71
72 ShaderProgram *create_shader_program(const char *path)
73 {
74         GLuint id = glCreateProgram();
75
76         GLuint vert, frag;
77
78         if (! (vert = compile_and_attach_shader(GL_VERTEX_SHADER, path, "vertex", id))) {
79                 glDeleteProgram(id);
80                 return NULL;
81         }
82
83         if (! (frag = compile_and_attach_shader(GL_FRAGMENT_SHADER, path, "fragment", id))) {
84                 glDeleteShader(vert);
85                 glDeleteProgram(id);
86                 return NULL;
87         }
88
89         glLinkProgram(id);
90         glDeleteShader(vert);
91         glDeleteShader(frag);
92
93         GLint success;
94         glGetProgramiv(id, GL_LINK_STATUS, &success);
95         if (! success) {
96                 char errbuf[BUFSIZ];
97                 glGetProgramInfoLog(id, BUFSIZ, NULL, errbuf);
98                 fprintf(stderr, "Failed to link shader program: %s\n", errbuf);
99                 glDeleteProgram(id);
100                 return NULL;
101         }
102
103         ShaderProgram *prog = malloc(sizeof(ShaderProgram));
104         prog->id = id;
105         prog->loc_model = glGetUniformLocation(id, "model");
106         prog->loc_view = glGetUniformLocation(id, "view");
107         prog->loc_projection = glGetUniformLocation(id, "projection");
108
109         return prog;
110 }
111
112 void delete_shader_program(ShaderProgram *prog)
113 {
114         glDeleteProgram(prog->id);
115         free(prog);
116 }
117