-
Notifications
You must be signed in to change notification settings - Fork 15
/
program.c
206 lines (169 loc) · 3.94 KB
/
program.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <GL/gl.h>
#include "model.h"
#include "view.h"
#include "program.h"
#include "util.h"
// Define inline data:
#define DATA_DEF(x) \
extern const uint8_t _binary_shaders_## x ##_glsl_start[]; \
extern const uint8_t _binary_shaders_## x ##_glsl_end[];
#define SHADER(x) \
{ .buf = _binary_shaders_ ## x ## _glsl_start \
, .end = _binary_shaders_ ## x ## _glsl_end \
}
// Inline data definitions:
DATA_DEF (bkgd_vertex)
DATA_DEF (bkgd_fragment)
DATA_DEF (cube_vertex)
DATA_DEF (cube_fragment)
// Shader structure:
struct shader {
const uint8_t *buf;
const uint8_t *end;
GLuint id;
};
// Location definitions:
enum loc_type {
UNIFORM,
ATTRIBUTE,
};
struct loc {
const char *name;
enum loc_type type;
GLint id;
};
static struct loc loc_bkgd[] = {
[LOC_BKGD_VERTEX] = { "vertex", ATTRIBUTE },
[LOC_BKGD_TEXTURE] = { "texture", ATTRIBUTE },
};
static struct loc loc_cube[] = {
[LOC_CUBE_VIEW] = { "view_matrix", UNIFORM },
[LOC_CUBE_MODEL] = { "model_matrix", UNIFORM },
[LOC_CUBE_VERTEX] = { "vertex", ATTRIBUTE },
[LOC_CUBE_VCOLOR] = { "vcolor", ATTRIBUTE },
[LOC_CUBE_NORMAL] = { "normal", ATTRIBUTE },
};
// Programs:
enum {
BKGD,
CUBE,
};
// Program structure:
static struct program {
struct {
struct shader vert;
struct shader frag;
} shader;
struct loc *loc;
size_t nloc;
GLuint id;
}
programs[] = {
[BKGD] = {
.shader.vert = SHADER (bkgd_vertex),
.shader.frag = SHADER (bkgd_fragment),
.loc = loc_bkgd,
.nloc = NELEM(loc_bkgd),
},
[CUBE] = {
.shader.vert = SHADER (cube_vertex),
.shader.frag = SHADER (cube_fragment),
.loc = loc_cube,
.nloc = NELEM(loc_cube),
},
};
static void
check_compile (GLuint shader)
{
GLint length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length <= 1)
return;
GLchar *log = calloc(length, sizeof(GLchar));
glGetShaderInfoLog(shader, length, NULL, log);
fprintf(stderr, "glCompileShader failed:\n%s\n", log);
free(log);
}
static void
check_link (GLuint program)
{
GLint status, length;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status != GL_FALSE)
return;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
GLchar *log = calloc(length, sizeof(GLchar));
glGetProgramInfoLog(program, length, NULL, log);
fprintf(stderr, "glLinkProgram failed: %s\n", log);
free(log);
}
static void
create_shader (struct shader *shader, GLenum type)
{
const GLchar *buf = (const GLchar *) shader->buf;
GLint len = shader->end - shader->buf;
shader->id = glCreateShader(type);
glShaderSource(shader->id, 1, &buf, &len);
glCompileShader(shader->id);
check_compile(shader->id);
}
static void
program_init (struct program *p)
{
struct shader *vert = &p->shader.vert;
struct shader *frag = &p->shader.frag;
create_shader(vert, GL_VERTEX_SHADER);
create_shader(frag, GL_FRAGMENT_SHADER);
p->id = glCreateProgram();
glAttachShader(p->id, vert->id);
glAttachShader(p->id, frag->id);
glLinkProgram(p->id);
check_link(p->id);
glDetachShader(p->id, vert->id);
glDetachShader(p->id, frag->id);
glDeleteShader(vert->id);
glDeleteShader(frag->id);
FOREACH_NELEM (p->loc, p->nloc, l) {
switch (l->type)
{
case UNIFORM:
l->id = glGetUniformLocation(p->id, l->name);
break;
case ATTRIBUTE:
l->id = glGetAttribLocation(p->id, l->name);
break;
}
}
}
void
programs_init (void)
{
FOREACH (programs, p)
program_init(p);
}
void
program_cube_use (void)
{
glUseProgram(programs[CUBE].id);
glUniformMatrix4fv(loc_cube[LOC_CUBE_VIEW ].id, 1, GL_FALSE, view_matrix());
glUniformMatrix4fv(loc_cube[LOC_CUBE_MODEL].id, 1, GL_FALSE, model_matrix());
}
void
program_bkgd_use (void)
{
glUseProgram(programs[BKGD].id);
glUniform1i(glGetUniformLocation(programs[BKGD].id, "tex"), 0);
}
GLint
program_bkgd_loc (const enum LocBkgd index)
{
return loc_bkgd[index].id;
}
GLint
program_cube_loc (const enum LocCube index)
{
return loc_cube[index].id;
}