]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/shader.c
fcf358a6b0152938323e45378f5e9648b34c8f72
[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/gl_debug.h"
6 #include "client/shader.h"
7
8 static GLuint compile_shader(GLenum type, const char *path, const char *name, GLuint program, const char *definitions)
9 {
10         char full_path[strlen(path) + 1 + strlen(name) + 1 + 4 + 1];
11         sprintf(full_path, "%s/%s.glsl", path, name);
12
13         FILE *file = fopen(full_path, "r");
14         if (!file) {
15                 perror("fopen");
16                 return 0;
17         }
18
19         if (fseek(file, 0, SEEK_END) == -1) {
20                 perror("fseek");
21                 fclose(file);
22                 return 0;
23         }
24
25         long size = ftell(file);
26
27         if (size == 1) {
28                 perror("ftell");
29                 fclose(file);
30                 return 0;
31         }
32
33         if (fseek(file, 0, SEEK_SET) == -1) {
34                 perror("fseek");
35                 fclose(file);
36                 return 0;
37         }
38
39         char code[size];
40
41         if (fread(code, 1, size, file) != (size_t) size) {
42                 perror("fread");
43                 fclose(file);
44                 return 0;
45         }
46
47         fclose(file);
48
49         GLuint id = glCreateShader(type); GL_DEBUG
50
51         // Minimum OpenGL version is 4.2.0 (idk some shader feature from that version is required)
52         const char *version = "#version 420 core\n"; // 420 blaze it
53
54         const char *code_list[3] = {
55                 version,
56                 definitions,
57                 code,
58         };
59
60         int size_list[3] = {
61                 18,
62                 strlen(definitions),
63                 size,
64         };
65
66         glShaderSource(id, 3, code_list, size_list); GL_DEBUG
67
68         glCompileShader(id); GL_DEBUG
69
70         GLint success;
71         glGetShaderiv(id, GL_COMPILE_STATUS, &success); GL_DEBUG
72         if (!success) {
73                 char errbuf[BUFSIZ];
74                 glGetShaderInfoLog(id, BUFSIZ, NULL, errbuf); GL_DEBUG
75                 fprintf(stderr, "[error] failed to compile %s shader: %s", name, errbuf);
76                 glDeleteShader(id); GL_DEBUG
77                 return 0;
78         }
79
80         glAttachShader(program, id); GL_DEBUG
81
82         return id;
83 }
84
85 bool shader_program_create(const char *path, GLuint *idptr, const char *definitions)
86 {
87         GLuint id = glCreateProgram(); GL_DEBUG
88
89         if (!definitions)
90                 definitions = "";
91
92         GLuint vert, frag;
93
94         if (!(vert = compile_shader(GL_VERTEX_SHADER, path, "vertex", id, definitions))) {
95                 glDeleteProgram(id); GL_DEBUG
96                 return false;
97         }
98
99         if (!(frag = compile_shader(GL_FRAGMENT_SHADER, path, "fragment", id, definitions))) {
100                 glDeleteShader(vert); GL_DEBUG
101                 glDeleteProgram(id); GL_DEBUG
102                 return false;
103         }
104
105         glLinkProgram(id); GL_DEBUG
106         glDeleteShader(vert); GL_DEBUG
107         glDeleteShader(frag); GL_DEBUG
108
109         GLint success;
110         glGetProgramiv(id, GL_LINK_STATUS, &success); GL_DEBUG
111         if (!success) {
112                 char errbuf[BUFSIZ];
113                 glGetProgramInfoLog(id, BUFSIZ, NULL, errbuf); GL_DEBUG
114                 fprintf(stderr, "[error] failed to link shader program: %s\n", errbuf);
115                 glDeleteProgram(id); GL_DEBUG
116                 return false;
117         }
118
119         *idptr = id;
120         return true;
121 }