diff options
| -rw-r--r-- | include/render.h | 11 | ||||
| -rw-r--r-- | src/render.c | 129 |
2 files changed, 140 insertions, 0 deletions
diff --git a/include/render.h b/include/render.h new file mode 100644 index 0000000..7b8a555 --- /dev/null +++ b/include/render.h @@ -0,0 +1,11 @@ +#pragma once + +#include <stdbool.h> + +#include <SDL2/SDL_video.h> + +void render_begin(int w, int h); +void render_end(SDL_Window* win); +bool render_init(void); +void render_rect(float x, float y, float w, float h, float r, float g, float b, float a); +void render_shutdown(void); diff --git a/src/render.c b/src/render.c new file mode 100644 index 0000000..8220edb --- /dev/null +++ b/src/render.c @@ -0,0 +1,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); +} |
