summaryrefslogtreecommitdiff
path: root/prge_shader.c
blob: 96b50f132cd40de1f75b99b7471a1ebd94a262eb (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
U32 compile_shader(GLenum type, Str8 filename)
{
	Arena		*tmp;
	Str8		src;
	U32		id;
	S32		status;
	const char	*csrc;

	tmp = arena_alloc(0);

	src = str8_read_entire_file(tmp, filename);
	if (!src.ptr || !src.length) {
		str8print(str8pushf(tmp, "[ERROR] : Failed to read \"%.*s\"\n", str8expand(filename)));
		arena_release(tmp);
		return 0;
	}

	csrc = str8tocstr(tmp, src);

	id = glCreateShader(type);
	glShaderSource(id, 1, &csrc, 0);
	glCompileShader(id);

	glGetShaderiv(id, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE) {
		char	log[512];
		glGetShaderInfoLog(id, 512, 0, log);
		str8print(str8pushf(tmp, "[ERROR] : Failed to compile : \"%.*s\"\n%s", str8expand(filename), log));
	} else {
		str8print(str8pushf(tmp, "[INFO] : \"%.*s\" compiled successfully.\n", str8expand(filename)));
	}

	arena_release(tmp);

	return id;
}

U32 load_shader(char *vert_filename, char *geom_filename, char *frag_filename)
{
	U32	vert, geom, frag, id;
	Arena	*tmp;
	S32	success;

	if (vert_filename)
		vert = compile_shader(GL_VERTEX_SHADER, str8fromcstr(vert_filename));
	if (geom_filename)
		geom = compile_shader(GL_GEOMETRY_SHADER, str8fromcstr(geom_filename));
	if (frag_filename)
		frag = compile_shader(GL_FRAGMENT_SHADER, str8fromcstr(frag_filename));

	tmp = arena_alloc(0);

	id = glCreateProgram();
	if (vert_filename)
		glAttachShader(id, vert);
	if (geom_filename)
		glAttachShader(id, geom);
	if (frag_filename)
		glAttachShader(id, frag);
	glLinkProgram(id);
	glGetProgramiv(id, GL_LINK_STATUS, &success);
	if (success == GL_FALSE) {
		char	log[512];
		glGetProgramInfoLog(id, 512, 0, log);
		str8print(str8pushf(tmp, "[ERROR] : Failed to link shader program:\n%s", log));
	} else {
		str8print(str8pushf(tmp, "[INFO] : Shader linked successfuly.\n\n"));
	}
	if (vert_filename)
		glDeleteShader(vert);
	if (geom_filename)
		glDeleteShader(geom);
	if (frag_filename)
		glDeleteShader(frag);

	arena_release(tmp);

	return id;
}

void shader_set_3fv(U32 id, char *name, V3 v)
{
	S32	loc;
	loc = glGetUniformLocation(id, name);
	glUniform3fv(loc, 1, (F32 *)&v);
}

void shader_set_4fv(U32 id, char *name, V4 v)
{
	S32	loc;
	loc = glGetUniformLocation(id, name);
	glUniform4fv(loc, 1, (F32 *)&v);
}

void shader_set_mat4fv(U32 id, char *name, MAT4 m)
{
	S32	loc;
	loc = glGetUniformLocation(id, name);
	glUniformMatrix4fv(loc, 1, 0, (F32 *)&m);
}