diff --git a/Makefile b/Makefile index e793022..268952a 100644 --- a/Makefile +++ b/Makefile @@ -10,3 +10,5 @@ DEPS=3rdparty/glad/include/glad/gl.h 3rdparty/glad/include/glad/glx.h 3rdparty/s $(BIN): $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) +clean: + rm $(OBJ) $(BIN) diff --git a/cudoku.c b/cudoku.c index ef7a313..62d6987 100644 --- a/cudoku.c +++ b/cudoku.c @@ -102,6 +102,9 @@ void draw_board(Cudoku *game, Size window_size) { set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); + GlyphInstanceList batch; + new_glyph_instance_list(&batch, 81); + for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (!game->board[i][j].value) { @@ -113,12 +116,14 @@ void draw_board(Cudoku *game, Size window_size) { set_y_constraint(&constraints, i * 100 + cell_size.height / 2.f - text_size.height / 2.f, UI_CONSTRAINT_FIXED); set_x_constraint(&constraints, j * 100 + cell_size.width / 2.f - text_size.width / 2.f, UI_CONSTRAINT_FIXED); if (game->board[i][j].is_locked) { - draw_text(num, 72.f, constraints, NULL, ALIGN_TOP_LEFT); + add_text_instance(&batch, num, 72.f, constraints, NULL, ALIGN_TOP_LEFT); } else { - draw_text(num, 72.f, constraints, &selection_color, ALIGN_TOP_LEFT); + add_text_instance(&batch, num, 72.f, constraints, &selection_color, ALIGN_TOP_LEFT); } } } + + draw_text_batch(&batch); } } @@ -558,13 +563,16 @@ void draw_help(Timer *timer) { set_height_constraint(&constraints, size.height, UI_CONSTRAINT_FIXED); draw_quad(constraints, &bg_color, 0.0, ALIGN_TOP_LEFT); + GlyphInstanceList batch; + new_glyph_instance_list(&batch, 100); + set_x_constraint(&constraints, text_padding, UI_CONSTRAINT_FIXED); for (int i = 0; i < HELP_TEXT_SIZE; i++) { Sizef text_size = calculate_text_size(help_texts[i], help_font_size); set_y_constraint(&constraints, total_help_texts_height, UI_CONSTRAINT_FIXED); set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); - draw_text(help_texts[i], help_font_size, constraints, &text_color, ALIGN_TOP_LEFT); + add_text_instance(&batch, help_texts[i], help_font_size, constraints, &text_color, ALIGN_TOP_LEFT); total_help_texts_height += text_size.height + text_padding; } @@ -575,8 +583,10 @@ void draw_help(Timer *timer) { Sizef closing_in_text_size = calculate_text_size(closing_in_text, closing_in_font_size); set_x_constraint(&constraints, overlay_width - closing_in_text_size.width - text_padding, UI_CONSTRAINT_FIXED); set_y_constraint(&constraints, text_padding, UI_CONSTRAINT_FIXED); - draw_text(closing_in_text, closing_in_font_size, constraints, &closing_in_text_color, ALIGN_TOP_LEFT); + add_text_instance(&batch, closing_in_text, closing_in_font_size, constraints, &closing_in_text_color, ALIGN_TOP_LEFT); } + + draw_text_batch(&batch); } void draw_timer(Timer *timer) { diff --git a/text.c b/text.c index a411197..b1fb043 100644 --- a/text.c +++ b/text.c @@ -18,21 +18,36 @@ Shader font_shader; unsigned int font_vao; unsigned int font_instance_vbo; +void extend_glyph_instance_list(GlyphInstanceList *dest, GlyphInstanceList *src) { + if (dest->size + src->size >= dest->capacity) { + dest->capacity = dest->size + src->size; + GlyphInstance* temp = realloc(dest->data, dest->capacity * sizeof(GlyphInstance)); + if (!temp) { + printf("[FATAL] Failed to reallocate memory for glyph instance list\n"); + exit(1); + } + dest->data = temp; + } + + memcpy(dest->data + dest->size, src->data, src->size * sizeof(GlyphInstance)); + dest->size += src->size; +} + void new_glyph_instance_list(GlyphInstanceList *list, uint capacity) { list->size = 0; list->capacity = capacity; - list->data = malloc(list->capacity * sizeof(TextInstance)); + list->data = malloc(list->capacity * sizeof(GlyphInstance)); } void clear_glyph_instance_list(GlyphInstanceList *list) { list->size = 0; - memset(list->data, 0, list->size * sizeof(TextInstance)); + memset(list->data, 0, list->size * sizeof(GlyphInstance)); } -void add_glyph_instance(GlyphInstanceList *list, TextInstance instance) { +void add_glyph_instance(GlyphInstanceList *list, GlyphInstance instance) { if (list->size >= list->capacity) { list->capacity *= 2; - TextInstance* temp = realloc(list->data, list->capacity * sizeof(TextInstance)); + GlyphInstance* temp = realloc(list->data, list->capacity * sizeof(GlyphInstance)); if (!temp) { printf("[FATAL] Failed to reallocate memory for glyph instance list\n"); exit(1); @@ -201,22 +216,22 @@ int init_fonts(const char *font_path) { // font instance vbo glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)0); glVertexAttribDivisor(1, 1); glEnableVertexAttribArray(2); - glVertexAttribIPointer(2, 1, GL_INT, sizeof(TextInstance), (void *)sizeof(Vec4f)); + glVertexAttribIPointer(2, 1, GL_INT, sizeof(GlyphInstance), (void *)sizeof(Vec4f)); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) + sizeof(int))); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)(sizeof(Vec4f) + sizeof(int))); glVertexAttribDivisor(3, 1); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); glEnableVertexAttribArray(7); - glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 2 + sizeof(int))); - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 3 + sizeof(int))); - glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 4 + sizeof(int))); - glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 5 + sizeof(int))); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)(sizeof(Vec4f) * 2 + sizeof(int))); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)(sizeof(Vec4f) * 3 + sizeof(int))); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)(sizeof(Vec4f) * 4 + sizeof(int))); + glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(GlyphInstance), (void *)(sizeof(Vec4f) * 5 + sizeof(int))); glVertexAttribDivisor(4, 1); glVertexAttribDivisor(5, 1); glVertexAttribDivisor(6, 1); @@ -281,7 +296,7 @@ Sizef calculate_text_size(const char *text, int font_size) { return size; } -void draw_text(const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment) { +GlyphInstanceList get_glyph_instance_list_from_text(const char *text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment) { use_shader(font_shader); Color text_color = { 0, 0, 0, 1.f }; if (color) { @@ -333,7 +348,7 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, const float xpos = (x + (ch.bearing.width - first_char_bearing_w)); float ypos = (text_size.height - ch.bearing.height - (text_size.height - max_bearing_h)); - TextInstance instance = { + GlyphInstance instance = { .position = (Vec4f){xpos, ypos, ch.size.width, ch.size.height}, .tex_coords_index = (int)text[c] - 32, .color = text_color, @@ -348,12 +363,18 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, const c++; } + return glyph_instance_list; +} + +void draw_text(const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment) { + GlyphInstanceList glyph_instance_list = get_glyph_instance_list_from_text(text, font_size, constraints, color, alignment); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, zephr_context.font.atlas_texture_id); glBindVertexArray(font_vao); glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(TextInstance) * glyph_instance_list.size, glyph_instance_list.data, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(GlyphInstance) * glyph_instance_list.size, glyph_instance_list.data, GL_DYNAMIC_DRAW); glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL, glyph_instance_list.size); @@ -362,3 +383,27 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, const free(glyph_instance_list.data); } + +void draw_text_batch(GlyphInstanceList *batch) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, zephr_context.font.atlas_texture_id); + glBindVertexArray(font_vao); + + glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(GlyphInstance) * batch->size, batch->data, GL_DYNAMIC_DRAW); + + glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL, batch->size); + + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + + free(batch->data); +} + +void add_text_instance(GlyphInstanceList *batch, const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment) { + GlyphInstanceList glyph_instance_list = get_glyph_instance_list_from_text(text, font_size, constraints, color, alignment); + + extend_glyph_instance_list(batch, &glyph_instance_list); + + free(glyph_instance_list.data); +} diff --git a/text.h b/text.h index f7b6fa5..1bc5543 100644 --- a/text.h +++ b/text.h @@ -19,14 +19,17 @@ typedef struct TextInstance { int tex_coords_index; Color color; float model[4][4]; -} TextInstance; +} GlyphInstance; typedef struct GlyphInstanceList { - TextInstance *data; + GlyphInstance *data; int size; int capacity; } GlyphInstanceList; +void new_glyph_instance_list(GlyphInstanceList *list, uint capacity); int init_fonts(const char *font_path); Sizef calculate_text_size(const char *text, int font_size); void draw_text(const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment); +void add_text_instance(GlyphInstanceList *batch, const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment); +void draw_text_batch(GlyphInstanceList *batch);