summaryrefslogtreecommitdiff
path: root/shader.h
blob: 189225aecb52e9aca7523859035c376018d56036 (plain)
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
shader_t compile_gl_shader(u32 type, char **src)
{
	shader_t shader = {0};
	shader.id = glCreateShader(type);
	glShaderSource(shader.id, 1, (const char **)src, 0);
	glCompileShader(shader.id);

	i32 status;
	glGetShaderiv(shader.id, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE)
		glGetShaderInfoLog(shader.id, MAX_SHADER_LOG, 0, shader.log);
	else
		snprintf(shader.log, MAX_SHADER_LOG, "compiled successfully");

	return shader;
}

shader_t compile_gl_shader_file(u32 type, const char *filename)
{
	char *src;
	shader_t shader = {0};

	arena_t tmp = alloc_arena(0);
	if (!sys_read_file(&tmp, &src, filename)) {
		printf("error: failed to read: \"%s\"\n", filename);
		release_arena(&tmp);
		return shader;
	}
	shader = compile_gl_shader(type, &src);
	release_arena(&tmp);

	if (!shader.id)
		printf("error: \"%s\": ", filename);
	else
		printf("info: \"%s\": ", filename);
	printf("%s", shader.log);
	printf("\n");

	return shader;
}

shader_t load_gl_shader(const char *dir, const char *vert_filename, const char *geom_filename, const char *frag_filename)
{
	shader_t shader = {0};
	shader.id = glCreateProgram();

	char full_path[MAX_PATH];
	shader_t vert;
	if (vert_filename) {
		snprintf(full_path, sizeof(full_path), "%s/%s", dir, vert_filename);
		vert = compile_gl_shader_file(GL_VERTEX_SHADER, full_path);
		glAttachShader(shader.id, vert.id);
	}

	shader_t geom;
	if (geom_filename) {
		snprintf(full_path, sizeof(full_path), "%s/%s", dir, geom_filename);
		geom = compile_gl_shader_file(GL_GEOMETRY_SHADER, full_path);
		glAttachShader(shader.id, geom.id);
	}

	shader_t frag;
	if (frag_filename) {
		snprintf(full_path, sizeof(full_path), "%s/%s", dir, frag_filename);
		frag = compile_gl_shader_file(GL_FRAGMENT_SHADER, full_path);
		glAttachShader(shader.id, frag.id);
	}

	i32 status;
	glLinkProgram(shader.id);
	glGetProgramiv(shader.id, GL_LINK_STATUS, &status);
	if (status == GL_FALSE) {
		glGetProgramInfoLog(shader.id, MAX_SHADER_LOG, 0, shader.log);
		printf("error: failed to link shader program:\n%s", shader.log);
	} else {
		printf("info: shader linked successfuly\n\n");
	}

	if (vert_filename)
		glDeleteShader(vert.id);
	if (geom_filename)
		glDeleteShader(geom.id);
	if (frag_filename)
		glDeleteShader(frag.id);

	return shader;
}

void shader_set_v3(shader_t shader, const char *name, v3 vec)
{
	i32 location = glGetUniformLocation(shader.id, name);
	glUniform3fv(location, 1, (f32 *)&vec);
}

void shader_set_v4(shader_t shader, const char *name, v4 vec)
{
	i32 location = glGetUniformLocation(shader.id, name);
	glUniform4fv(location, 1, (f32 *)&vec);
}

void shader_set_mat4(shader_t shader, const char *name, mat4 mat)
{
	i32 location = glGetUniformLocation(shader.id, name);
	glUniformMatrix4fv(location, 1, 0, (f32 *)&mat);
}