]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/shader.c
0f5b98696c88222ebd12915636b912d0aa3041a8
[dragonblocks_alpha.git] / src / client / shader.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include "client/shader.h"
6
7 static GLuint compile_and_attach_shader(GLenum type, const char *path, const char *name, GLuint program, const char *definitions)
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         const char *version = "#version 460 core\n";
51
52         const char *code_list[3] = {
53                 version,
54                 definitions,
55                 code,
56         };
57
58         int size_list[3] = {
59                 18,
60                 strlen(definitions),
61                 size,
62         };
63
64         glShaderSource(id, 3, code_list, size_list);
65
66         glCompileShader(id);
67
68         GLint success;
69         glGetShaderiv(id, GL_COMPILE_STATUS, &success);
70         if (! success) {
71                 char errbuf[BUFSIZ];
72                 glGetShaderInfoLog(id, BUFSIZ, NULL, errbuf);
73                 fprintf(stderr, "Failed to compile %s shader: %s", name, errbuf);
74                 glDeleteShader(id);
75                 return 0;
76         }
77
78         glAttachShader(program, id);
79
80         return id;
81 }
82
83 bool shader_program_create(const char *path, GLuint *idptr, const char *definitions)
84 {
85         GLuint id = glCreateProgram();
86
87         if (! definitions)
88                 definitions = "";
89
90         GLuint vert, frag;
91
92         if (! (vert = compile_and_attach_shader(GL_VERTEX_SHADER, path, "vertex", id, definitions))) {
93                 glDeleteProgram(id);
94                 return false;
95         }
96
97         if (! (frag = compile_and_attach_shader(GL_FRAGMENT_SHADER, path, "fragment", id, definitions))) {
98                 glDeleteShader(vert);
99                 glDeleteProgram(id);
100                 return false;
101         }
102
103         glLinkProgram(id);
104         glDeleteShader(vert);
105         glDeleteShader(frag);
106
107         GLint success;
108         glGetProgramiv(id, GL_LINK_STATUS, &success);
109         if (! success) {
110                 char errbuf[BUFSIZ];
111                 glGetProgramInfoLog(id, BUFSIZ, NULL, errbuf);
112                 fprintf(stderr, "Failed to link shader program: %s\n", errbuf);
113                 glDeleteProgram(id);
114                 return false;
115         }
116
117         *idptr = id;
118         return true;
119 }