commit f813754dd2e9c32b55adc4837dbf6b5ff1c2684d
parent 983c71135214353f6c6b7544ea112cd3afd696a9
Author: rexim <reximkut@gmail.com>
Date: Sun, 15 Jan 2023 00:23:02 +0700
Introduce SHADER_FOR_TEXT
Diffstat:
7 files changed, 69 insertions(+), 74 deletions(-)
diff --git a/shaders/simple_text.frag b/shaders/simple_text.frag
@@ -0,0 +1,10 @@
+#version 330 core
+
+uniform sampler2D image;
+
+in vec4 out_color;
+in vec2 out_uv;
+
+void main() {
+ gl_FragColor = texture(image, out_uv).x*out_color;
+}
diff --git a/src/editor.c b/src/editor.c
@@ -184,16 +184,14 @@ void editor_render(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Renderer
if (select_begin_chr <= select_end_chr) {
Vec2f select_begin_scr = vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE);
- free_glyph_atlas_render_line_sized(
- atlas, sr, editor->data.items + line_chr.begin, select_begin_chr - line_chr.begin,
- &select_begin_scr,
- false);
+ free_glyph_atlas_measure_line_sized(
+ atlas, editor->data.items + line_chr.begin, select_begin_chr - line_chr.begin,
+ &select_begin_scr);
Vec2f select_end_scr = select_begin_scr;
- free_glyph_atlas_render_line_sized(
- atlas, sr, editor->data.items + select_begin_chr, select_end_chr - select_begin_chr,
- &select_end_scr,
- false);
+ free_glyph_atlas_measure_line_sized(
+ atlas, editor->data.items + select_begin_chr, select_end_chr - select_begin_chr,
+ &select_end_scr);
Vec4f selection_color = vec4f(.25, .25, .25, 1);
simple_renderer_solid_rect(sr, select_begin_scr, vec2f(select_end_scr.x - select_begin_scr.x, FREE_GLYPH_FONT_SIZE), selection_color);
@@ -202,7 +200,7 @@ void editor_render(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Renderer
}
simple_renderer_flush(sr);
- simple_renderer_set_shader(sr, SHADER_FOR_EPICNESS);
+ simple_renderer_set_shader(sr, SHADER_FOR_TEXT);
for (size_t row = 0; row < editor->lines.count; ++row) {
Line line = editor->lines.items[row];
@@ -211,7 +209,7 @@ void editor_render(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Renderer
free_glyph_atlas_render_line_sized(
atlas, sr, editor->data.items + line.begin, line.end - line.begin,
&end,
- true);
+ vec4fs(1));
// TODO: the max_line_len should be calculated based on what's visible on the screen right now
float line_len = fabsf(end.x - begin.x);
if (line_len > max_line_len) {
diff --git a/src/free_glyph.c b/src/free_glyph.c
@@ -92,7 +92,22 @@ float free_glyph_atlas_cursor_pos(const Free_Glyph_Atlas *atlas, const char *tex
return pos.x;
}
-void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer *sr, const char *text, size_t text_size, Vec2f *pos, bool render)
+void free_glyph_atlas_measure_line_sized(Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f *pos)
+{
+ for (size_t i = 0; i < text_size; ++i) {
+ size_t glyph_index = text[i];
+ // TODO: support for glyphs outside of ASCII range
+ if (glyph_index >= GLYPH_METRICS_CAPACITY) {
+ glyph_index = '?';
+ }
+ Glyph_Metric metric = atlas->metrics[glyph_index];
+
+ pos->x += metric.ax;
+ pos->y += metric.ay;
+ }
+}
+
+void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer *sr, const char *text, size_t text_size, Vec2f *pos, Vec4f color)
{
for (size_t i = 0; i < text_size; ++i) {
size_t glyph_index = text[i];
@@ -109,13 +124,12 @@ void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer
pos->x += metric.ax;
pos->y += metric.ay;
- if (render) {
- simple_renderer_image_rect(
- sr,
- vec2f(x2, -y2),
- vec2f(w, -h),
- vec2f(metric.tx, 0.0f),
- vec2f(metric.bw / (float) atlas->atlas_width, metric.bh / (float) atlas->atlas_height));
- }
+ simple_renderer_image_rect(
+ sr,
+ vec2f(x2, -y2),
+ vec2f(w, -h),
+ vec2f(metric.tx, 0.0f),
+ vec2f(metric.bw / (float) atlas->atlas_width, metric.bh / (float) atlas->atlas_height),
+ color);
}
}
diff --git a/src/free_glyph.h b/src/free_glyph.h
@@ -43,6 +43,7 @@ typedef struct {
void free_glyph_atlas_init(Free_Glyph_Atlas *atlas, FT_Face face);
float free_glyph_atlas_cursor_pos(const Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f pos, size_t col);
-void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer *sr, const char *text, size_t text_size, Vec2f *pos, bool render);
+void free_glyph_atlas_measure_line_sized(Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f *pos);
+void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer *sr, const char *text, size_t text_size, Vec2f *pos, Vec4f color);
#endif // FREE_GLYPH_H_
diff --git a/src/main.c b/src/main.c
@@ -66,10 +66,9 @@ void render_file_browser(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Ren
if (fb->cursor < fb->files.count) {
const Vec2f begin = vec2f(0, -(float)fb->cursor * FREE_GLYPH_FONT_SIZE);
Vec2f end = begin;
- free_glyph_atlas_render_line_sized(
- atlas, sr, fb->files.items[fb->cursor], strlen(fb->files.items[fb->cursor]),
- &end,
- false);
+ free_glyph_atlas_measure_line_sized(
+ atlas, fb->files.items[fb->cursor], strlen(fb->files.items[fb->cursor]),
+ &end);
simple_renderer_solid_rect(sr, begin, vec2f(end.x - begin.x, FREE_GLYPH_FONT_SIZE), vec4f(.25, .25, .25, 1));
}
simple_renderer_flush(sr);
@@ -81,7 +80,7 @@ void render_file_browser(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Ren
free_glyph_atlas_render_line_sized(
atlas, sr, fb->files.items[row], strlen(fb->files.items[row]),
&end,
- true);
+ vec4fs(0));
// TODO: the max_line_len should be calculated based on what's visible on the screen right now
float line_len = fabsf(end.x - begin.x);
if (line_len > max_line_len) {
@@ -226,11 +225,7 @@ int main(int argc, char **argv)
}
- simple_renderer_init(&sr,
- "./shaders/simple.vert",
- "./shaders/simple_color.frag",
- "./shaders/simple_image.frag",
- "./shaders/simple_epic.frag");
+ simple_renderer_init(&sr);
free_glyph_atlas_init(&atlas, face);
bool quit = false;
diff --git a/src/simple_renderer.c b/src/simple_renderer.c
@@ -7,6 +7,16 @@
#include "./simple_renderer.h"
#include "./common.h"
+#define vert_shader_file_path "./shaders/simple.vert"
+
+static_assert(COUNT_SIMPLE_SHADERS == 4, "The amount of fragment shaders has changed");
+const char *frag_shader_file_paths[COUNT_SIMPLE_SHADERS] = {
+ [SHADER_FOR_COLOR] = "./shaders/simple_color.frag",
+ [SHADER_FOR_IMAGE] = "./shaders/simple_image.frag",
+ [SHADER_FOR_TEXT] = "./shaders/simple_text.frag",
+ [SHADER_FOR_EPICNESS] = "./shaders/simple_epic.frag",
+};
+
static const char *shader_type_as_cstr(GLuint shader)
{
switch (shader) {
@@ -118,11 +128,7 @@ static void get_uniform_location(GLuint program, GLint locations[COUNT_UNIFORM_S
}
}
-void simple_renderer_init(Simple_Renderer *sr,
- const char *vert_file_path,
- const char *color_frag_file_path,
- const char *image_frag_file_path,
- const char *epic_frag_file_path)
+void simple_renderer_init(Simple_Renderer *sr)
{
sr->camera_scale = 3.0f;
@@ -169,42 +175,17 @@ void simple_renderer_init(Simple_Renderer *sr,
// TODO: dynamic shader reloading
- if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &shaders[0])) {
+ if (!compile_shader_file(vert_shader_file_path, GL_VERTEX_SHADER, &shaders[0])) {
exit(1);
}
- // Shader for color
- {
- if (!compile_shader_file(color_frag_file_path, GL_FRAGMENT_SHADER, &shaders[1])) {
- exit(1);
- }
- sr->programs[SHADER_FOR_COLOR] = glCreateProgram();
- attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), sr->programs[SHADER_FOR_COLOR]);
- if (!link_program(sr->programs[SHADER_FOR_COLOR], __FILE__, __LINE__)) {
- exit(1);
- }
- }
-
- // Shader for image
- {
- if (!compile_shader_file(image_frag_file_path, GL_FRAGMENT_SHADER, &shaders[1])) {
- exit(1);
- }
- sr->programs[SHADER_FOR_IMAGE] = glCreateProgram();
- attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), sr->programs[SHADER_FOR_IMAGE]);
- if (!link_program(sr->programs[SHADER_FOR_IMAGE], __FILE__, __LINE__)) {
- exit(1);
- }
- }
-
- // Shader for epicness
- {
- if (!compile_shader_file(epic_frag_file_path, GL_FRAGMENT_SHADER, &shaders[1])) {
+ for (int i = 0; i < COUNT_SIMPLE_SHADERS; ++i) {
+ if (!compile_shader_file(frag_shader_file_paths[i], GL_FRAGMENT_SHADER, &shaders[1])) {
exit(1);
}
- sr->programs[SHADER_FOR_EPICNESS] = glCreateProgram();
- attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), sr->programs[SHADER_FOR_EPICNESS]);
- if (!link_program(sr->programs[SHADER_FOR_EPICNESS], __FILE__, __LINE__)) {
+ sr->programs[i] = glCreateProgram();
+ attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), sr->programs[i]);
+ if (!link_program(sr->programs[i], __FILE__, __LINE__)) {
exit(1);
}
}
@@ -244,9 +225,8 @@ void simple_renderer_quad(Simple_Renderer *sr,
simple_renderer_triangle(sr, p1, p2, p3, c1, c2, c3, uv1, uv2, uv3);
}
-void simple_renderer_image_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec2f uvp, Vec2f uvs)
+void simple_renderer_image_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec2f uvp, Vec2f uvs, Vec4f c)
{
- Vec4f c = vec4fs(0);
simple_renderer_quad(
sr,
p, vec2f_add(p, vec2f(s.x, 0)), vec2f_add(p, vec2f(0, s.y)), vec2f_add(p, s),
diff --git a/src/simple_renderer.h b/src/simple_renderer.h
@@ -34,6 +34,7 @@ typedef struct {
typedef enum {
SHADER_FOR_COLOR = 0,
SHADER_FOR_IMAGE,
+ SHADER_FOR_TEXT,
SHADER_FOR_EPICNESS, // This is the one that does that cool rainbowish animation
COUNT_SIMPLE_SHADERS,
} Simple_Shader;
@@ -57,11 +58,7 @@ typedef struct {
Vec2f camera_vel;
} Simple_Renderer;
-void simple_renderer_init(Simple_Renderer *sr,
- const char *vert_file_path,
- const char *color_frag_file_path,
- const char *image_frag_file_path,
- const char *epic_frag_file_path);
+void simple_renderer_init(Simple_Renderer *sr);
void simple_renderer_vertex(Simple_Renderer *sr,
Vec2f p, Vec4f c, Vec2f uv);
@@ -75,7 +72,7 @@ void simple_renderer_quad(Simple_Renderer *sr,
Vec4f c0, Vec4f c1, Vec4f c2, Vec4f c3,
Vec2f uv0, Vec2f uv1, Vec2f uv2, Vec2f uv3);
void simple_renderer_solid_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec4f c);
-void simple_renderer_image_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec2f uvp, Vec2f uvs);
+void simple_renderer_image_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec2f uvp, Vec2f uvs, Vec4f c);
void simple_renderer_flush(Simple_Renderer *sr);
void simple_renderer_sync(Simple_Renderer *sr);
void simple_renderer_draw(Simple_Renderer *sr);