|
|
@@ -24,6 +24,7 @@
|
|
|
#define IMP
|
|
|
#include "app.h"
|
|
|
#include "vec2.h"
|
|
|
+#include "vec4.h"
|
|
|
#include "da.h"
|
|
|
#include "unwrap.h"
|
|
|
#include "file.h"
|
|
|
@@ -33,64 +34,263 @@
|
|
|
|
|
|
struct app handle_events(struct app app);
|
|
|
|
|
|
+struct glyph {
|
|
|
+ struct vec2i tile;
|
|
|
+ int32_t c;
|
|
|
+ struct vec4f color;
|
|
|
+};
|
|
|
+
|
|
|
+DA_DEF_STRUCT(struct glyph, glyphs);
|
|
|
+
|
|
|
+struct glyph_attr {
|
|
|
+ GLint size;
|
|
|
+ GLenum type;
|
|
|
+ GLboolean norm;
|
|
|
+ GLsizei stride;
|
|
|
+ size_t offset;
|
|
|
+};
|
|
|
+
|
|
|
+enum glyph_attr_enum {
|
|
|
+ GLYPH_ATTR_TILE = 0,
|
|
|
+ GLYPH_ATTR_C,
|
|
|
+ GLYPH_ATTR_COLOR,
|
|
|
+ GLYPH_ATTR_TOTAL
|
|
|
+};
|
|
|
+
|
|
|
+static const struct glyph_attr glyph_attr[GLYPH_ATTR_TOTAL] = {
|
|
|
+ [GLYPH_ATTR_TILE] = {
|
|
|
+ .size = 2,
|
|
|
+ .type = GL_INT,
|
|
|
+ .norm = GL_FALSE,
|
|
|
+ .stride = sizeof(struct glyph),
|
|
|
+ .offset = offsetof(struct glyph, tile)
|
|
|
+ },
|
|
|
+ [GLYPH_ATTR_C] = {
|
|
|
+ .size = 1,
|
|
|
+ .type = GL_INT,
|
|
|
+ .norm = GL_FALSE,
|
|
|
+ .stride = sizeof(struct glyph),
|
|
|
+ .offset = offsetof(struct glyph, c)
|
|
|
+ },
|
|
|
+ [GLYPH_ATTR_COLOR] = {
|
|
|
+ .size = 4,
|
|
|
+ .type = GL_FLOAT,
|
|
|
+ .norm = GL_FALSE,
|
|
|
+ .stride = sizeof(struct glyph),
|
|
|
+ .offset = offsetof(struct glyph, color)
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+struct glyphs gl_render_text(struct app app, struct glyphs glys,
|
|
|
+ struct vec2i tile);
|
|
|
+void glyphs_sync(struct app app, struct glyphs glys);
|
|
|
+
|
|
|
+int32_t get_uniform(uint32_t prog, const char *name);
|
|
|
+
|
|
|
int32_t
|
|
|
main(int32_t argc, char **argv)
|
|
|
{
|
|
|
(void) argc; (void) argv;
|
|
|
|
|
|
struct app app = app_create("ged");
|
|
|
- /* const char *font_path = "./charmap-oldschool_white.png"; */
|
|
|
- /* app.font = font_create(app.rdr, font_path, 7, 18); */
|
|
|
- /* app.font.scale = 2.0; */
|
|
|
+ const char *font_path = "./charmap-oldschool_white.png";
|
|
|
+ app.font = font_create(app.rdr, font_path, 7, 18);
|
|
|
+ app.font.scale = 2.0;
|
|
|
+
|
|
|
+ struct glyphs glys;
|
|
|
+ glys.cap = 1024;
|
|
|
+ glys.size = 0;
|
|
|
+ glys.items = calloc(glys.cap, sizeof(struct glyph));
|
|
|
|
|
|
enum shader_err err;
|
|
|
|
|
|
+ uint32_t prog;
|
|
|
uint32_t vert_shader;
|
|
|
uint32_t frag_shader;
|
|
|
|
|
|
- RET_UNWRAP2(vert_shader, err, struct ret_uint32_t_err,
|
|
|
- shader_compile_file("./shaders/font.vert",
|
|
|
- GL_VERTEX_SHADER));
|
|
|
- if ( err != SHADER_ERR_OK ) {
|
|
|
- fprintf(stderr, "Failed to compile shader font.vert\n");
|
|
|
- exit(EXIT_FAILURE);
|
|
|
+ /* Loading shaders and linking prog */
|
|
|
+ {
|
|
|
+ RET_UNWRAP2(vert_shader, err, struct ret_uint32_t_err,
|
|
|
+ shader_compile_file("./shaders/font.vert",
|
|
|
+ GL_VERTEX_SHADER));
|
|
|
+ if ( err != SHADER_ERR_OK ) {
|
|
|
+ fprintf(stderr, "Failed to compile shader font.vert\n");
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+
|
|
|
+ RET_UNWRAP2(frag_shader, err, struct ret_uint32_t_err,
|
|
|
+ shader_compile_file("./shaders/font.frag",
|
|
|
+ GL_FRAGMENT_SHADER));
|
|
|
+ if ( err != SHADER_ERR_OK ) {
|
|
|
+ fprintf(stderr, "Failed to compile shader font.frag\n");
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+
|
|
|
+ RET_UNWRAP2(prog, err, struct ret_uint32_t_err,
|
|
|
+ program_link(vert_shader, frag_shader));
|
|
|
+ if ( err != SHADER_ERR_OK ) {
|
|
|
+ fprintf(stderr, "Failed to link program\n");
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- RET_UNWRAP2(frag_shader, err, struct ret_uint32_t_err,
|
|
|
- shader_compile_file("./shaders/font.frag",
|
|
|
- GL_FRAGMENT_SHADER));
|
|
|
- if ( err != SHADER_ERR_OK ) {
|
|
|
- fprintf(stderr, "Failed to compile shader font.frag\n");
|
|
|
- exit(EXIT_FAILURE);
|
|
|
+ glUseProgram(prog);
|
|
|
+
|
|
|
+ uint32_t font_tex = 0;
|
|
|
+ /* Init Font Texture */
|
|
|
+ {
|
|
|
+ int32_t w, h, n;
|
|
|
+ uint8_t *data = stbi_load(font_path,
|
|
|
+ &w, &h, &n,
|
|
|
+ STBI_rgb_alpha);
|
|
|
+
|
|
|
+ if ( data == NULL ) {
|
|
|
+ fprintf(stderr, "ERROR loading file %s: %s",
|
|
|
+ font_path, stbi_failure_reason());
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+
|
|
|
+ glActiveTexture(GL_TEXTURE0);
|
|
|
+ glGenTextures(1, &font_tex);
|
|
|
+ glBindTexture(GL_TEXTURE_2D, font_tex);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
|
+ GL_NEAREST);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
|
|
+ GL_NEAREST);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
|
|
+ GL_CLAMP_TO_EDGE);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
|
|
+ GL_CLAMP_TO_EDGE);
|
|
|
+
|
|
|
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
|
|
|
+ 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
|
|
+ data);
|
|
|
}
|
|
|
|
|
|
- uint32_t prog;
|
|
|
- RET_UNWRAP2(prog, err, struct ret_uint32_t_err,
|
|
|
- program_link(vert_shader, frag_shader));
|
|
|
- if ( err != SHADER_ERR_OK ) {
|
|
|
- fprintf(stderr, "Failed to link program\n");
|
|
|
+ /* Getting the uniforms */
|
|
|
+ /* app.uniforms.time = get_uniform(prog, "time"); */
|
|
|
+ app.uniforms.resolution = get_uniform(prog, "resolution");
|
|
|
+ app.uniforms.scale = get_uniform(prog, "scale");
|
|
|
+ app.uniforms.cursor = get_uniform(prog, "cursor");
|
|
|
+
|
|
|
+ uint32_t vao = 0;
|
|
|
+ uint32_t vbo = 0;
|
|
|
+
|
|
|
+ /* Initialized array */
|
|
|
+ {
|
|
|
+ glGenVertexArrays(1, &vao);
|
|
|
+ glBindVertexArray(vao);
|
|
|
+
|
|
|
+ glGenBuffers(1, &vbo);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
+ glBufferData(GL_ARRAY_BUFFER,
|
|
|
+ (ssize_t)(glys.cap * sizeof(struct glyph)),
|
|
|
+ glys.items,
|
|
|
+ GL_DYNAMIC_DRAW);
|
|
|
+
|
|
|
+ for ( size_t i = 0; i < GLYPH_ATTR_TOTAL; ++i ) {
|
|
|
+ struct glyph_attr ga = glyph_attr[i];
|
|
|
+ glEnableVertexAttribArray((uint32_t) i);
|
|
|
+ switch ( ga.type ) {
|
|
|
+ case GL_FLOAT: {
|
|
|
+ glVertexAttribPointer((uint32_t) i,
|
|
|
+ ga.size, ga.type,
|
|
|
+ ga.norm, ga.stride,
|
|
|
+ (void*)ga.offset);
|
|
|
+ } break;
|
|
|
+ case GL_INT: {
|
|
|
+ glVertexAttribIPointer((uint32_t) i,
|
|
|
+ ga.size, ga.type,
|
|
|
+ ga.stride,
|
|
|
+ (void*)ga.offset);
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+ glVertexAttribDivisor((uint32_t) i, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ enum buffer_err err_;
|
|
|
+ RET_UNWRAP2(app.buf, err_,
|
|
|
+ struct ret_buffer_err,
|
|
|
+ buffer_load_from_file(app.buf, "./m.c"));
|
|
|
+ if ( err_ != BUFFER_ERR_OK ) {
|
|
|
+ fprintf(stderr, "Failed to read load buffer: %d\n", err_);
|
|
|
exit(EXIT_FAILURE);
|
|
|
}
|
|
|
|
|
|
- glUseProgram(prog);
|
|
|
- uint32_t vao = 0;
|
|
|
- glGenVertexArrays(1, &vao);
|
|
|
- glBindVertexArray(vao);
|
|
|
+ glys = gl_render_text(app, glys, vec2is(0));
|
|
|
+ glyphs_sync(app, glys);
|
|
|
|
|
|
+ struct vec2i cur = app_calc_cursor(app);
|
|
|
+ glUniform1f(app.uniforms.scale, 5.0);
|
|
|
while ( app.running ) {
|
|
|
app = handle_events(app);
|
|
|
|
|
|
- glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
|
+ glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
+
|
|
|
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP,
|
|
|
+ 0, 4,
|
|
|
+ (int32_t) glys.size);
|
|
|
+
|
|
|
+ /* glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); */
|
|
|
|
|
|
SDL_GL_SwapWindow(app.win.ptr);
|
|
|
+ /* glUniform1f(app.uniforms.time, */
|
|
|
+ /* (float) (SDL_GetTicks() / 1000)); */
|
|
|
+ cur = app_calc_cursor(app);
|
|
|
+ glUniform2i(app.uniforms.cursor, cur.x, cur.y);
|
|
|
}
|
|
|
|
|
|
app_destroy(app);
|
|
|
exit(EXIT_SUCCESS);
|
|
|
}
|
|
|
|
|
|
+struct glyphs
|
|
|
+gl_render_text(struct app app, struct glyphs glys, struct vec2i tile)
|
|
|
+{
|
|
|
+ struct vec2i pen = tile;
|
|
|
+ int32_t row = 0;
|
|
|
+ for ( size_t i = 0; i < app.buf.data.size; ++i ) {
|
|
|
+ char c = app.buf.data.items[i];
|
|
|
+ if ( c == '\n' ) {
|
|
|
+ pen.y -= 1;
|
|
|
+ row = 0;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ struct glyph gly = {
|
|
|
+ .tile = vec2i_add(pen, vec2i(row, 0)),
|
|
|
+ .c = c,
|
|
|
+ .color = vec4fs(1)
|
|
|
+ };
|
|
|
+ DA_APPEND(glys, gly);
|
|
|
+ ++row;
|
|
|
+ }
|
|
|
+ return glys;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+glyphs_sync(struct app app, struct glyphs glys)
|
|
|
+{
|
|
|
+ (void) app;
|
|
|
+ glBufferSubData(GL_ARRAY_BUFFER,
|
|
|
+ 0,
|
|
|
+ (ssize_t) (glys.size * sizeof(struct glyph)),
|
|
|
+ glys.items);
|
|
|
+}
|
|
|
+
|
|
|
+int32_t
|
|
|
+get_uniform(uint32_t prog, const char *name)
|
|
|
+{
|
|
|
+ int32_t uni = glGetUniformLocation(prog, name);
|
|
|
+ if ( uni == -1 ) {
|
|
|
+ fprintf(stderr, "Failed getting %s uniform location\n", name);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+ return uni;
|
|
|
+}
|
|
|
+
|
|
|
int32_t main2(int32_t argc, char **argv);
|
|
|
int32_t
|
|
|
main2(int32_t argc, char **argv)
|
|
|
@@ -224,6 +424,10 @@ handle_events(struct app app)
|
|
|
} break;
|
|
|
case SDL_WINDOWEVENT: {
|
|
|
WINDOW_UP_SIZE(app.win);
|
|
|
+ glUniform2f(app.uniforms.resolution,
|
|
|
+ (float) app.win.w,
|
|
|
+ (float) app.win.h);
|
|
|
+ glViewport(0, 0 ,app.win.w, app.win.h);
|
|
|
} break;
|
|
|
}
|
|
|
}
|