summaryrefslogtreecommitdiff
path: root/src/render.c
blob: 8220edb69ac4f7b0f73761b4aad4642c5ab33c95 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <stdbool.h>
#include <stdio.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_opengles2.h>

#include "quark.h"
#include "render.h"

/* shader handles */
static GLuint prog = 0;
static GLint u_res;
static GLint u_color;
static GLuint vbo = 0;

/* helpers */
static GLuint compile(GLenum type, const char* src);

static GLuint compile(GLenum type, const char* src)
{
	GLuint s = glCreateShader(type);
	glShaderSource(s, 1, &src, NULL);
	glCompileShader(s);

	GLint ok;
	glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
	if (!ok) {
		char log[512];
		glGetShaderInfoLog(s, sizeof(log), NULL, log);
		LOG_ERROR("renderer: shader error: %s", log);
		glDeleteShader(s);
		return 0;
	}

	return s;
}

void render_begin(int w, int h)
{
	glViewport(0, 0, w, h);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);

	glUseProgram(prog);
	glUniform2f(u_res, w, h);
}

void render_end(SDL_Window* win)
{
	SDL_GL_SwapWindow(win);
}

bool render_init(void)
{
	const char* vs =
		"attribute vec2 a_pos;"
		"uniform vec2 u_res;"
		"void main() {"
		"vec2 p = a_pos / u_res;"
		"p.y = 1.0 - p.y;"
		"p = p * 2.0 - 1.0;"
		"  gl_Position = vec4(p, 0.0, 1.0);"
		"}";

	const char* fs =
		"precision mediump float;"
		"uniform vec4 u_color;"
		"void main()"
		"{"
		"  gl_FragColor = u_color;"
		"}";

	GLuint v = compile(GL_VERTEX_SHADER, vs);
	GLuint f = compile(GL_FRAGMENT_SHADER, fs);
	if (!v || !f)
		return false;

	prog = glCreateProgram();
	glAttachShader(prog, v);
	glAttachShader(prog, f);
	glBindAttribLocation(prog, 0, "a_pos");
	glLinkProgram(prog);

	glDeleteShader(v);
	glDeleteShader(f);

	GLint ok;
	glGetProgramiv(prog, GL_LINK_STATUS, &ok);
	if (!ok) {
		LOG_ERROR("renderer: program link failed");
		return false;
	}

	u_res = glGetUniformLocation(prog, "u_res");
	u_color = glGetUniformLocation(prog, "u_color");

	glGenBuffers(1, &vbo);

	return true;
}

void render_rect(float x, float y, float w, float h, float r, float g, float b, float a)
{
	float verts[12] = {
		x,    y,
		x+w,  y,
		x+w,  y+h,

		x,    y,
		x+w,  y+h,
		x,    y+h
	};

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STREAM_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);

	glUniform4f(u_color, r, g, b, a);

	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void render_shutdown(void)
{
	glDeleteProgram(prog);
	glDeleteBuffers(1, &vbo);
}