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