Ver código fonte

Starting working on FreeType font support

Vinicius Teshima 1 ano atrás
pai
commit
184fb71d3d
5 arquivos alterados com 285 adições e 92 exclusões
  1. 36 0
      shaders/free_font.frag
  2. 41 0
      shaders/free_font.vert
  3. 92 45
      src/free_glyph.h
  4. 7 1
      src/gl_util.h
  5. 109 46
      src/main.c

+ 36 - 0
shaders/free_font.frag

@@ -0,0 +1,36 @@
+#version 330 core
+
+#define FONT_WIDTH 128
+#define FONT_HEIGHT 64
+#define FONT_COLS 18
+#define FONT_ROWS 7
+#define FONT_CH_W (FONT_WIDTH  / FONT_COLS)
+#define FONT_CH_H (FONT_HEIGHT / FONT_ROWS)
+#define FONT_CH_W_UV (float(FONT_CH_W) / float(FONT_WIDTH))
+#define FONT_CH_H_UV (float(FONT_CH_H) / float(FONT_HEIGHT))
+
+uniform sampler2D font;
+uniform float time;
+uniform vec2 resolution;
+
+flat in int glyph_c;
+in vec4 glyph_fg_color;
+in vec4 glyph_bg_color;
+in vec2 uv;
+
+float map01(float x)
+{
+	return (x + 1) / 2;
+}
+
+vec3 hsl2rgb( in vec3 c )
+{
+	vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0,
+			  0.0, 1.0 );
+
+	return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
+}
+
+void main() {
+	gl_FragColor = vec4(1,0,0,1);
+}

+ 41 - 0
shaders/free_font.vert

@@ -0,0 +1,41 @@
+#version 330 core
+
+#define FONT_WIDTH 128
+#define FONT_HEIGHT 64
+#define FONT_COLS 18
+#define FONT_ROWS 7
+#define FONT_CH_W (FONT_WIDTH / FONT_COLS)
+#define FONT_CH_H (FONT_HEIGHT / FONT_ROWS)
+
+uniform float scale;
+uniform vec2 resolution;
+uniform float time;
+uniform vec2 camera;
+
+layout(location = 0) in ivec2 pos;
+layout(location = 1) in ivec2 size;
+layout(location = 2) in int c;
+layout(location = 3) in vec4 fg_color;
+layout(location = 4) in vec4 bg_color;
+
+out vec2 uv;
+flat out int glyph_c;
+out vec4 glyph_fg_color;
+out vec4 glyph_bg_color;
+
+vec2 project_point(vec2 point)
+{
+  return (2.0 * (point - camera)) / resolution;
+}
+
+void main()
+{
+	uv = vec2(float(gl_VertexID & 1),
+		  float((gl_VertexID >> 1) & 1));
+
+	gl_Position = vec4(uv- 0.5, 0.0, 1.0);
+
+	glyph_c = c;
+	glyph_fg_color = fg_color;
+	glyph_bg_color = bg_color;
+}

+ 92 - 45
src/free_glyph.h

@@ -1,46 +1,94 @@
-#ifndef TILE_GLYPH_H
-#define TILE_GLYPH_H
+#ifndef FREE_GLYPH_H
+#define FREE_GLYPH_H
 
 #include "glyph_attr.h"
 
+
 struct free_glyph {
 	struct vec2f pos;
 	struct vec2f size;
-	int32_t ch;
+	int32_t c;
 	struct vec4f fg_color;
 	struct vec4f bg_color;
 };
 
 DA_DEF_STRUCT(struct free_glyph, free_glyph_da);
 
+struct free_glyph_render {
+	struct free_glyph_da glyphs;
+	struct {
+		uint32_t vert;
+		uint32_t frag;
+	} shaders;
+	uint32_t prog;
+	struct {
+		int32_t resolution;
+		int32_t time;
+		int32_t camera;
+	} uniforms;
+	uint32_t vao;
+	uint32_t vbo;
+};
+
+
 enum free_glyph_attr_enum {
 	FREE_GLYPH_ATTR_POS = 0,
-	FREE_GLYPH_ATTR_SIZE = 0,
+	FREE_GLYPH_ATTR_SIZE,
 	FREE_GLYPH_ATTR_C,
 	FREE_GLYPH_ATTR_FG_COLOR,
 	FREE_GLYPH_ATTR_BG_COLOR,
 	FREE_GLYPH_ATTR_TOTAL
 };
 
+struct free_glyph_render free_glyph_render_create(const char *font_path,
+						  const char *vert_path,
+						  const char *frag_path);
+
 struct free_glyph_da free_glyph_da_create(void);
 const struct glyph_attr* free_glyph_get_attrs(void);
 
-struct free_glyph_da free_glyph_da_calc(struct app app,
-					struct free_glyph_da glys,
-					const char *cstr, size_t cstr_size,
-					struct vec2f pos,
-					struct vec2f size,
-					struct vec4f fg_color,
-					struct vec4f bg_color);
-struct free_glyph_da free_glyph_da_calc_buffer(struct app app,
-					       struct free_glyph_da glys,
-					       struct vec2f pos,
-					       struct vec2f size);
-void free_glyph_da_sync(struct app app, struct free_glyph_da glys);
-uint32_t tile_glyph_gen_buffer(struct free_glyph_da glys);
+struct free_glyph_render free_glyph_render_calc(
+	struct free_glyph_render fgr, const char *cstr, size_t cstr_size,
+	struct vec2f pos, struct vec2f size,
+	struct vec4f fg_color, struct vec4f bg_color);
+struct free_glyph_render free_glyph_render_calc_buffer(
+	struct free_glyph_render fgr, struct app app,
+	struct vec2f pos, struct vec2f size);
+
+void free_glyph_render_sync(struct free_glyph_render fgr);
+struct free_glyph_render free_glyph_render_gen_buffer(
+	struct free_glyph_render fgr);
 
 #if defined(FREE_GLYPH_IMP) || defined(IMP)
 
+#include "gl_util.h"
+
+struct free_glyph_render
+free_glyph_render_create(const char *font_path, const char *vert_path,
+			 const char *frag_path)
+{
+	(void) font_path;
+	struct free_glyph_render fgr = {0};
+	/* fgr = free_glyph_render_load_texture_atlas_or_exit(fgr, font_path); */
+	fgr.glyphs = free_glyph_da_create();
+
+	fgr.shaders.vert = shader_compile_file_or_exit(
+		vert_path, GL_VERTEX_SHADER);
+	fgr.shaders.frag = shader_compile_file_or_exit(
+		frag_path, GL_FRAGMENT_SHADER);
+	fgr.prog = program_link_or_exit(fgr.shaders.vert, fgr.shaders.frag);
+
+	glUseProgram(fgr.prog);
+
+	fgr.uniforms.resolution = get_uniform/* _or_exit */(fgr.prog, "resolution");
+	fgr.uniforms.time = get_uniform/* _or_exit */(fgr.prog, "time");
+	fgr.uniforms.camera = get_uniform/* _or_exit */(fgr.prog, "camera");
+
+	fgr = free_glyph_render_gen_buffer(fgr);
+
+	return fgr;
+}
+
 struct free_glyph_da
 free_glyph_da_create(void)
 {
@@ -48,7 +96,7 @@ free_glyph_da_create(void)
 	glys.cap = 1024 * 1024;
 	glys.size = 0;
 	glys.items = calloc(glys.cap, sizeof(struct free_glyph));
-	return gly;
+	return glys;
 }
 
 const struct glyph_attr *
@@ -96,13 +144,12 @@ free_glyph_get_attrs(void)
 	return free_glyph_attr;
 }
 
-struct free_glyph_da
-free_glyph_da_calc(struct app app, struct free_glyph_da glys,
-		   const char *cstr, size_t cstr_size,
-		   struct vec2f pos, struct vec2f size,
-		   struct vec4f fg_color, struct vec4f bg_color)
+struct free_glyph_render
+free_glyph_render_calc(struct free_glyph_render fgr,
+		       const char *cstr, size_t cstr_size,
+		       struct vec2f pos, struct vec2f size,
+		       struct vec4f fg_color, struct vec4f bg_color)
 {
-	(void) app;
 	for ( size_t i = 0; i < cstr_size; ++i ) {
 		char c = cstr[i];
 		if ( c == '\n' ) {
@@ -115,44 +162,44 @@ free_glyph_da_calc(struct app app, struct free_glyph_da glys,
 			.fg_color = fg_color,
 			.bg_color = bg_color
 		};
-		DA_APPEND(glys, gly);
+		DA_APPEND(fgr.glyphs, gly);
 	}
-	return glys;
+	return fgr;
 }
 
-struct free_glyph_da
-free_glyph_da_calc_buffer(struct app app, struct free_glyph_da glys,
-			  struct vec2f pos, struct vec2f size)
+struct free_glyph_render
+free_glyph_render_calc_buffer(struct free_glyph_render fgr, struct app app,
+			      struct vec2f pos, struct vec2f size)
 {
-	return free_glyph_da_calc(app, glys,
-				  app.buf.data.items, app.buf.data.size,
-				  pos, size, vec4fs(1), vec4fs(0));
+	return free_glyph_render_calc(fgr,
+				      app.buf.data.items, app.buf.data.size,
+				      pos, size, vec4fs(1), vec4fs(0));
 }
 
 void
-free_glyph_da_sync(struct app app, struct free_glyph_da glys)
+free_glyph_render_sync(struct free_glyph_render fgr)
 {
-	(void) app;
 	glBufferSubData(GL_ARRAY_BUFFER, 0,
-			(ssize_t) (glys.size * sizeof(struct free_glyph)),
-			glys.items);
+			(ssize_t) (fgr.glyphs.size * sizeof(struct free_glyph)),
+			fgr.glyphs.items);
 }
 
-uint32_t
-free_glyph_gen_buffer(struct free_glyph_da glys)
+struct free_glyph_render
+free_glyph_render_gen_buffer(struct free_glyph_render fgr)
 {
-	uint32_t id = 0;
-	glGenBuffers(1, &id);
-	glBindBuffer(GL_ARRAY_BUFFER, id);
+	glGenVertexArrays(1, &fgr.vao);
+	glBindVertexArray(fgr.vao);
+
+	glGenBuffers(1, &fgr.vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, fgr.vbo);
 	glBufferData(GL_ARRAY_BUFFER,
-		     (ssize_t)(glys.cap * sizeof(struct tile_glyph)),
-		     glys.items,
+		     (ssize_t)(fgr.glyphs.cap * sizeof(struct free_glyph)),
+		     fgr.glyphs.items,
 		     GL_DYNAMIC_DRAW);
 	glyph_attr_declare(free_glyph_get_attrs(), FREE_GLYPH_ATTR_TOTAL);
-	return id;
+	return fgr;
 }
 
-
 #endif /* defined(FREE_GLYPH_IMP) || defined(IMP) */
 
 #endif

+ 7 - 1
src/gl_util.h

@@ -1,14 +1,20 @@
 #ifndef GL_UTIL_H
 #define GL_UTIL_H
 
+int32_t get_uniform(uint32_t prog, const char *name);
 int32_t get_uniform_or_exit(uint32_t prog, const char *name);
 
 #if defined(GL_UTIL_IMP) || defined(IMP)
 
+int32_t get_uniform(uint32_t prog, const char *name)
+{
+	return glGetUniformLocation(prog, name);
+}
+
 int32_t
 get_uniform_or_exit(uint32_t prog, const char *name)
 {
-	int32_t uni = glGetUniformLocation(prog, name);
+	int32_t uni = get_uniform(prog, name);
 	if ( uni == -1 ) {
 		fprintf(stderr, "Failed getting %s uniform location\n", name);
 		exit(EXIT_FAILURE);

+ 109 - 46
src/main.c

@@ -10,6 +10,9 @@
 #define GL_GLEXT_PROTOTYPES
 #include <SDL2/SDL_opengl.h>
 
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wall"
 #pragma GCC diagnostic ignored "-Wsign-conversion"
@@ -33,8 +36,18 @@
 #include "shader.h"
 #include "tile_glyph.h"
 #include "gl_util.h"
+#include "free_glyph.h"
 
 struct app handle_events(struct app app, int32_t resolution_uniform);
+struct tile_glyph_render render_buffer_into_tgr(struct tile_glyph_render tgr,
+						struct app app,
+						struct vec2 cpos);
+
+struct free_glyph_render render_buffer_into_fgr(struct free_glyph_render fgr,
+						struct app app,
+						struct vec2 cpos);
+
+FT_Library library;
 
 int32_t
 main(int32_t argc, char **argv)
@@ -46,6 +59,37 @@ main(int32_t argc, char **argv)
 		exit(EXIT_FAILURE);
 	}
 
+	const char *ffont_path = "./fonts/VictorMono-Regular.ttf";
+
+	{
+		FT_Error error = FT_Init_FreeType( &library );
+		if ( error ) {
+			fprintf(stderr,
+				"[ERROR] Failed to load FreeType2 library\n");
+			exit(EXIT_FAILURE);
+		}
+
+		FT_Face face;
+		error = FT_New_Face(library, ffont_path, 0, &face);
+		if ( error == FT_Err_Unknown_File_Format ) {
+			fprintf(stderr, "[ERROR] Font %s has unknown format\n",
+				ffont_path);
+			exit(EXIT_FAILURE);
+		} else if ( error ) {
+			fprintf(stderr, "[ERROR] Failed to load font: %s\n",
+				ffont_path);
+			exit(EXIT_FAILURE);
+		}
+
+		FT_UInt pixel_size = 64;
+		error = FT_Set_Pixel_Sizes(face, 0, pixel_size);
+		if ( error ) {
+			fprintf(stderr, "[ERROR] Failed to set font size: %u\n",
+				pixel_size);
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	struct app app = app_create("ged");
 	const char *font_path = "./fonts/charmap-oldschool_white.png";
 	app.font = font_create(app.rdr, font_path, 7, 18);
@@ -59,10 +103,16 @@ main(int32_t argc, char **argv)
 		exit(EXIT_FAILURE);
 	}
 
-	struct tile_glyph_render tgr = tile_glyph_render_create(
-		font_path,
-		"./shaders/tile_font.vert",
-		"./shaders/tile_font.frag");
+	/* struct tile_glyph_render tgr = tile_glyph_render_create( */
+	/* 	font_path, */
+	/* 	"./shaders/tile_font.vert", */
+	/* 	"./shaders/tile_font.frag"); */
+	struct free_glyph_render fgr = free_glyph_render_create(
+		ffont_path,
+		"./shaders/free_font.vert",
+		"./shaders/free_font.frag");
+
+	struct vec2 cpos;	/* camera pos */
 
 	double dt = (1.0 / (double)app.target_fps) * 3;
 	uint32_t frame_target_dur = (uint32_t)(1000 / app.target_fps);
@@ -76,10 +126,9 @@ main(int32_t argc, char **argv)
 
 	while ( app.running ) {
 		fr_start = SDL_GetTicks();
-		glUniform1f(tgr.uniforms.scale,(float) app.font.scale);
 
-		struct buffer *buf = &app.buf;
-		app = handle_events(app, tgr.uniforms.resolution);
+		/* app = handle_events(app, tgr.uniforms.resolution); */
+		app = handle_events(app, -1);
 
 		if ( app.show_fps == true ) {
 			fps_text_size = (size_t) snprintf(fps_text, 128,
@@ -93,49 +142,15 @@ main(int32_t argc, char **argv)
 		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 		glClear(GL_COLOR_BUFFER_BIT);
 
-		/* Calc Camera */
-		{
-			struct vec2 cpos;
-			RET_UNWRAP2(app, cpos,
-				    struct ret_app_vec2,
-				    app_calc_buffer_cam(app, dt));
-			glUniform2f(tgr.uniforms.camera,
-				    (float)cpos.x,
-				    (float)cpos.y);
-		}
-
-		tgr.glyphs.size = 0;
-		tgr = tile_glyph_render_calc_buffer(tgr, app.buf, vec2is(0));
-		tile_glyph_render_sync(tgr);
-		glDrawArraysInstanced(GL_TRIANGLE_STRIP,
-				      0, 4,
-				      (int32_t) tgr.glyphs.size);
+		RET_UNWRAP2(app, cpos,
+			    struct ret_app_vec2,
+			    app_calc_buffer_cam(app, dt));
 
-		{
-			size_t col = 0;
-			size_t row = 0;
-			RET_UNWRAP2(col, row,
-				    struct ret_size_t_size_t,
-				    buffer_calc_cur_pos(app.buf));
-
-			const char *c = buf->data.items + buf->cur;
-			tgr.glyphs.size = 0;
-			tgr = tile_glyph_render_calc(tgr,
-						     ( *c == '\n' ) ? " " : c, 1,
-						     vec2i((int32_t)col,
-							   -(int32_t)row),
-						     vec4fs(0), vec4fs(1));
-			tile_glyph_render_sync(tgr);
-			glDrawArraysInstanced(GL_TRIANGLE_STRIP,
-					      0, 4,
-					      (int32_t) tgr.glyphs.size);
-		}
+		/* tgr = render_buffer_into_tgr(tgr, app, cpos); */
+		fgr = render_buffer_into_fgr(fgr, app, cpos);
 
 		SDL_GL_SwapWindow(app.win.ptr);
 
-		glUniform1f(tgr.uniforms.time,
-			    (float) (SDL_GetTicks() / 1000));
-
 		fr_end = SDL_GetTicks();
 		fr_dur = (fr_end - fr_start);
 		if ( fr_dur < frame_target_dur ) {
@@ -200,3 +215,51 @@ handle_events(struct app app, int32_t resolution_uniform)
 
 	return app;
 }
+
+struct tile_glyph_render
+render_buffer_into_tgr(struct tile_glyph_render tgr, struct app app,
+		       struct vec2 cpos)
+{
+	glUniform1f(tgr.uniforms.scale,(float) app.font.scale);
+	glUniform2f(tgr.uniforms.camera,
+		    (float)cpos.x,
+		    (float)cpos.y);
+
+	tgr.glyphs.size = 0;
+	tgr = tile_glyph_render_calc_buffer(tgr, app.buf, vec2is(0));
+	tile_glyph_render_sync(tgr);
+	glDrawArraysInstanced(GL_TRIANGLE_STRIP,
+			      0, 4,
+			      (int32_t) tgr.glyphs.size);
+
+	{
+		size_t col = 0;
+		size_t row = 0;
+		RET_UNWRAP2(col, row,
+			    struct ret_size_t_size_t,
+			    buffer_calc_cur_pos(app.buf));
+
+		const char *c = app.buf.data.items + app.buf.cur;
+		tgr.glyphs.size = 0;
+		tgr = tile_glyph_render_calc(tgr,
+					     ( *c == '\n' ) ? " " : c, 1,
+					     vec2i((int32_t)col,
+						   -(int32_t)row),
+					     vec4fs(0), vec4fs(1));
+		tile_glyph_render_sync(tgr);
+		glDrawArraysInstanced(GL_TRIANGLE_STRIP,
+				      0, 4,
+				      (int32_t) tgr.glyphs.size);
+	}
+	glUniform1f(tgr.uniforms.time,
+		    (float) (SDL_GetTicks() / 1000));
+	return tgr;
+}
+
+struct free_glyph_render
+render_buffer_into_fgr(struct free_glyph_render fgr, struct app app,
+		       struct vec2 cpos)
+{
+	(void) fgr; (void) app; (void) cpos;
+	return fgr;
+}