-
Notifications
You must be signed in to change notification settings - Fork 0
/
shader.c
139 lines (104 loc) · 2.97 KB
/
shader.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "panic.h"
#include "shader.h"
static GLuint
install_shader(const GLchar **source, GLenum type, GLint size)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, source, &size);
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
static GLchar log[512];
glGetShaderInfoLog(shader, sizeof log, NULL, log);
panic("Shader compilation failed: %s", log);
}
return shader;
}
static GLuint
load_shader(const char *path, GLenum type)
{
GLchar *buf;
GLuint rc;
int fd;
ssize_t nbytes;
ssize_t bytes_read;
struct stat s;
if ((fd = open(path, O_RDONLY)) == -1)
panic("Cannot open shader file: %s", strerror(errno));
if (fstat(fd, &s) == -1)
panic("Cannot get file size: %s", strerror(errno));
buf = malloc(s.st_size);
memset(buf, 0 , s.st_size);
bytes_read = 0;
do {
nbytes = read(fd, (buf + bytes_read), s.st_size);
bytes_read += nbytes;
} while (nbytes > 0 && bytes_read < s.st_size);
assert(bytes_read == s.st_size);
close(fd);
rc = install_shader((const GLchar **)&buf, type, s.st_size);
free(buf);
return rc;
}
static inline GLuint
load_vertex_shader(void)
{
return load_shader("vertex.glsl", GL_VERTEX_SHADER);
}
static inline GLuint
load_fragment_shader(void)
{
return load_shader("fragment.glsl", GL_FRAGMENT_SHADER);
}
GLuint
load_shaders(void)
{
GLuint vertex_shader = load_vertex_shader();
GLuint fragment_shader = load_fragment_shader();
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
GLint success;
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
static GLchar log[512];
glGetProgramInfoLog(shader_program, sizeof log, NULL, log);
panic("Shader program linking failed: %s", log);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
void
shader_set_uniform_m4(GLuint shader_program, const char *uniform, mat4x4 m)
{
GLint location = glGetUniformLocation(shader_program, uniform);
glUniformMatrix4fv(location, 1, GL_FALSE, (const GLfloat *) m);
}
void
shader_set_uniform_i(GLuint shader_program, const char *uniform, GLint i)
{
GLint location = glGetUniformLocation(shader_program, uniform);
glUniform1i(location, i);
}
void
shader_set_uniform_3f(GLuint shader_program, const char *uniform,
GLfloat x, GLfloat y, GLfloat z)
{
GLint location = glGetUniformLocation(shader_program, uniform);
glUniform3f(location, x, y, z);
}