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
|
#include "shader.h"
#include "sys.h"
#include <GL/glew.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
shader_t shaders[MAX_SHADERS] = {0};
static u32 compile_shader(GLenum type, const char *dir, const char *filename)
{
char path[512] = {0};
snprintf(path, 512, "%s/%s", (dir ? dir : "."), filename);
const char *src = (const char *)read_entire_file(path);
if (!src) {
info("failed to read the file \"%s\"", path);
return 0;
}
u32 id = glCreateShader(type);
glShaderSource(id, 1, &src, 0);
free((void *)src);
glCompileShader(id);
i32 status;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
char log[512];
glGetShaderInfoLog(id, 512, 0, log);
info("failed to compile \"%s\"\n%s", path, log);
} else {
info("\"%s\" compiled successfully", path);
}
return id;
}
u32 load_shader(const char *dir, const char *vertex_filename, const char *fragment_filename, const char *geometry_filename, const char *name)
{
if (get_shader(name)) {
info("shader \"%s\" already exist", name);
return 0;
}
u32 id = glCreateProgram();
u32 vert = compile_shader(GL_VERTEX_SHADER, dir, vertex_filename);
glAttachShader(id, vert);
u32 frag = compile_shader(GL_FRAGMENT_SHADER, dir, fragment_filename);
glAttachShader(id, frag);
u32 geom = 0;
if (geometry_filename) {
geom = compile_shader(GL_GEOMETRY_SHADER, dir, geometry_filename);
glAttachShader(id, geom);
}
glLinkProgram(id);
i32 success;
glGetProgramiv(id, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
char log[512];
glGetProgramInfoLog(id, 512, 0, log);
info("failed to link shader:\n%s", log);
}
glDeleteShader(vert);
glDeleteShader(frag);
if (geometry_filename)
glDeleteShader(geom);
shader_t shader = {id, name};
i32 i;
for (i = 0; i < MAX_SHADERS; i++) {
if (!shaders[i].id) {
shaders[i] = shader;
return id;
}
}
info("shader limit (%d) reached", MAX_SHADERS);
glDeleteProgram(id);
return 0;
}
u32 get_shader(const char *name)
{
for (i32 i = 0; i < MAX_SHADERS; i++)
if (shaders[i].name && strstr(shaders[i].name, name))
return shaders[i].id;
return 0;
}
void uniform_f32(u32 id, const char *name, f32 v)
{
u32 loc = glGetUniformLocation(id, name);
glUniform1f(loc, v);
}
void uniform_i32(u32 id, const char *name, i32 v)
{
u32 loc = glGetUniformLocation(id, name);
glUniform1i(loc, v);
}
void uniform_v2(u32 id, const char *name, v2 v)
{
u32 loc = glGetUniformLocation(id, name);
glUniform2fv(loc, 1, (const f32 *)&v);
}
void uniform_v3(u32 id, const char *name, v3 v)
{
u32 loc = glGetUniformLocation(id, name);
glUniform3fv(loc, 1, (const f32 *)&v);
}
void uniform_v4(u32 id, const char *name, v4 v)
{
u32 loc = glGetUniformLocation(id, name);
glUniform4fv(loc, 1, (const f32 *)&v);
}
void uniform_mat(u32 id, const char *name, mat m)
{
u32 loc = glGetUniformLocation(id, name);
glUniformMatrix4fv(loc, 1, 0, (const f32 *)&m);
}
|