summaryrefslogtreecommitdiff
path: root/src/utils.c
blob: a3c878e482b38ed260f41b6ad5382f7ae3ae3f73 (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
106
107
108
109
110
111
112
113
114
#include "utils.h"

// Mostly inspired by CC0 https://gist.github.com/koute/7391344
void gl_mat4x4_ortho(t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar)
{
	#define T(a, b) (a * 4 + b)

	out[T(0,0)] = 2.0f / (right - left);
	out[T(0,1)] = 0.0f;
	out[T(0,2)] = 0.0f;
	out[T(0,3)] = 0.0f;

	out[T(1,1)] = 2.0f / (top - bottom);
	out[T(1,0)] = 0.0f;
	out[T(1,2)] = 0.0f;
	out[T(1,3)] = 0.0f;

	out[T(2,2)] = -2.0f / (zfar - znear);
	out[T(2,0)] = 0.0f;
	out[T(2,1)] = 0.0f;
	out[T(2,3)] = 0.0f;

	out[T(3,0)] = -(right + left) / (right - left);
	out[T(3,1)] = -(top + bottom) / (top - bottom);
	out[T(3,2)] = -(zfar + znear) / (zfar - znear);
	out[T(3,3)] = 1.0f;

	#undef T
}

// Mostly inspired from https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_02

// Store all the file's contents in memory, useful to pass shaders source code to OpenGL.
const GLchar* gl_shaderfile_read(const char* path, Sint64 *out_fsize) {
	GLchar *buf, *cursor;
	SDL_RWops *rw;
	Sint64 fsize;
	size_t read;

	rw = SDL_RWFromFile(path, "rb"); if (rw == NULL) return NULL;
	fsize = SDL_RWsize(rw); if (fsize == -1) return NULL;
	buf = malloc(fsize+1); if (buf == NULL) return NULL;

	cursor = buf;
	read = 0;
	do {
		cursor += read;
		// Read at most to the end of buf
		read = SDL_RWread(rw, cursor, 1, (fsize - (cursor-buf)));
	 } while ( read > 0 );
	*cursor = '\0'; // Where the +1 is used from malloc() call

	SDL_RWclose(rw);

	// Check if we have read the whole thing
	if ( (cursor-buf) != fsize) {
		free(buf);
		return NULL;
	}

	if (out_fsize != NULL) *out_fsize = fsize;
	return buf;
}

/**
 * Display compilation errors from the OpenGL shader compiler
 */
void gl_trace_shader_or_program_log(GLuint object) {
	GLint log_length = 0;
	char *log;

	if (glIsShader(object)) {
		glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
	} else if (glIsProgram(object)) {
		glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
	} else {
		TRACE("not a shader or a program");
		return;
	}

	log = (char*)malloc(log_length);
	if ( log == NULL ) {
		TRACE("malloc failed");
		return;
	}

	if (glIsShader(object))
		glGetShaderInfoLog(object, log_length, NULL, log);
	else if (glIsProgram(object))
		glGetProgramInfoLog(object, log_length, NULL, log);

	TRACE(log);
	free(log);
}

GLint gl_compile_shader_from_file(GLuint shader, const char* path) {
	Sint64 fsize;
	GLint gl_fsize, status;

	const GLchar *source = gl_shaderfile_read(path, &fsize);
	if (source == NULL) return 1;

	gl_fsize = (GLint) fsize;
	glShaderSource(shader, 1, &source, &gl_fsize);
	glCompileShader(shader);
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		gl_trace_shader_or_program_log(shader);
		return 2;
	}

	return 0;
}