mirror of
https://github.com/IllusionMan1212/cudoku.git
synced 2026-10-24 02:12:25 +00:00
text instancing
This commit is contained in:
@@ -29,7 +29,7 @@ static const int quad_indices[] = {
|
||||
|
||||
static const Color mistake_color = {1.f, 0.f, 0.f, 0.5f};
|
||||
|
||||
static const wide_str *win_text = U"You won!";
|
||||
static const char *win_text = "You won!";
|
||||
|
||||
static const char *help_texts[HELP_TEXT_SIZE] = {
|
||||
"F1 - Toggle help",
|
||||
@@ -58,15 +58,15 @@ void draw_win() {
|
||||
/* set_width_constraint(&constraints, window.width, UI_CONSTRAINT_FIXED); */
|
||||
/* set_height_constraint(&constraints, window.height, UI_CONSTRAINT_FIXED); */
|
||||
|
||||
Alignment align = ALIGN_CENTER;
|
||||
int font_size = 72.0f;
|
||||
Alignment align = ALIGN_TOP_LEFT;
|
||||
int font_size = 84.0f;
|
||||
|
||||
/* Sizef text_size = calculate_text_size(win_text, font_size); */
|
||||
Sizef text_size = calculate_text_size(win_text, font_size);
|
||||
|
||||
set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
|
||||
set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
|
||||
/* set_width_constraint(&constraints, text_size.width, UI_CONSTRAINT_FIXED); */
|
||||
/* set_height_constraint(&constraints, text_size.height, UI_CONSTRAINT_FIXED); */
|
||||
set_width_constraint(&constraints, text_size.width, UI_CONSTRAINT_FIXED);
|
||||
set_height_constraint(&constraints, text_size.height, UI_CONSTRAINT_FIXED);
|
||||
/* set_rotation_constraint(&constraints, 0); */
|
||||
|
||||
/* UIConstraints circle_const; */
|
||||
@@ -76,7 +76,7 @@ void draw_win() {
|
||||
/* set_height_constraint(&circle_const, 90, UI_CONSTRAINT_FIXED); */
|
||||
|
||||
/* draw_circle(circle_const, NULL, ALIGN_LEFT_CENTER); */
|
||||
/* draw_quad(constraints, &bg_color, 0.0, align); */
|
||||
draw_quad(constraints, &bg_color, 0.0, align);
|
||||
/* set_x_constraint(&constraints, -50, UI_CONSTRAINT_FIXED); */
|
||||
/* draw_quad(constraints, &bg_color, 25.0, ALIGN_TOP_RIGHT); */
|
||||
/* set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); */
|
||||
@@ -87,7 +87,17 @@ void draw_win() {
|
||||
|
||||
set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED);
|
||||
set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED);
|
||||
/* set_rotation_constraint(&constraints, 0); */
|
||||
draw_text(win_text, font_size, constraints, &text_color, align);
|
||||
|
||||
/* for (int i = 0; i < 100; i++) { */
|
||||
/* int x = rand() % window.width; */
|
||||
/* int y = rand() % window.height; */
|
||||
/* set_x_constraint(&constraints, x, UI_CONSTRAINT_FIXED); */
|
||||
/* set_y_constraint(&constraints, y, UI_CONSTRAINT_FIXED); */
|
||||
|
||||
/* draw_text(win_text, font_size, constraints, &text_color, align); */
|
||||
/* } */
|
||||
}
|
||||
|
||||
void set_scale_factor(int width, int height, float *x, float *y) {
|
||||
|
||||
@@ -70,14 +70,6 @@ Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, floa
|
||||
return result;
|
||||
}
|
||||
|
||||
uint wide_str_len(const wide_str *text) {
|
||||
uint len = 0;
|
||||
for (uint i = 0; text[i] != '\0'; i++) {
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int max(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,12 @@
|
||||
|
||||
#include "z_math.h"
|
||||
|
||||
typedef unsigned int wide_str;
|
||||
|
||||
Matrix4x4 identity();
|
||||
void mult_4x4(Matrix4x4 *multiplicant, Matrix4x4 *multiplier);
|
||||
void apply_scale(Matrix4x4 *matrix, Sizef scale);
|
||||
void apply_rotation(Matrix4x4 *model, float angle);
|
||||
void apply_translation(Matrix4x4 *matrix, Vec2f pos);
|
||||
Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, float top);
|
||||
uint wide_str_len(const wide_str *text);
|
||||
int max(int a, int b);
|
||||
float maxf(float a, float b);
|
||||
float clampf(float value, float min, float max);
|
||||
|
||||
@@ -87,6 +87,11 @@ void set_float(Shader shader, const char *name, float val) {
|
||||
glUniform1f(loc, val);
|
||||
}
|
||||
|
||||
void set_vec2f(Shader shader, const char *name, float val1, float val2) {
|
||||
int loc = glGetUniformLocation(shader.program, name);
|
||||
glUniform2f(loc, val1, val2);
|
||||
}
|
||||
|
||||
void set_vec3f(Shader shader, const char *name, float val1, float val2, float val3) {
|
||||
int loc = glGetUniformLocation(shader.program, name);
|
||||
glUniform3f(loc, val1, val2, val3);
|
||||
|
||||
@@ -9,5 +9,6 @@ Shader create_shader(const char *vertex_path, const char *fragment_path);
|
||||
void use_shader(Shader shader);
|
||||
void set_mat4f(Shader shader, const char *name, float *mat);
|
||||
void set_float(Shader shader, const char *name, float val);
|
||||
void set_vec2f(Shader shader, const char *name, float val1, float val2);
|
||||
void set_vec3f(Shader shader, const char *name, float val1, float val2, float val3);
|
||||
void set_vec4f(Shader shader, const char *name, float val1, float val2, float val3, float val4);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 vertex;
|
||||
|
||||
// per instance
|
||||
layout (location = 1) in vec4 offset;
|
||||
layout (location = 2) in int tex_index;
|
||||
|
||||
out vec2 v_TexCoords;
|
||||
uniform mat4 projection;
|
||||
uniform mat4 model;
|
||||
// buffer for all the 96 ascii characters' texcoords
|
||||
uniform vec2 texcoords[96 * 4];
|
||||
|
||||
void main() {
|
||||
vec2 pos = vec2((vertex.x) * offset.z, (vertex.y) * offset.w);
|
||||
gl_Position = projection * model * vec4(pos + offset.xy, 0.0, 1.0);
|
||||
v_TexCoords = texcoords[tex_index * 4 + gl_VertexID];
|
||||
}
|
||||
@@ -4,8 +4,12 @@
|
||||
and replace them with the screen's currently active resolution
|
||||
|
||||
text rendering improvements
|
||||
- [x] unicode support (allows for non-ascii characters)
|
||||
- [ ] unicode support (allows for non-ascii characters)
|
||||
- unicode support removed for the foreseeable future
|
||||
- [x] atlas texture for text glyphs (this means we only load in one texture for all text)
|
||||
- [x] better estimation of atlas width and height (currently the generated atlas texture
|
||||
has a lot of empty space (over 50% of the texture's height))
|
||||
- ended up just looping over the ascii glyphs and finding the max width and height
|
||||
|
||||
- SDF generation allowing for better text scaling (slower but visually better)
|
||||
- SDF is too slow if we want to support unicode. it's acceptably fast for ascii only though.
|
||||
@@ -17,4 +21,24 @@ text rendering improvements
|
||||
|
||||
Will probably end up using MSDF (if I can get it to work with C lol)
|
||||
|
||||
- instanced rendering for text (this means we only have to do one draw call for all text)
|
||||
- [x] instanced rendering for text (this means we only have to do one draw call for all text)
|
||||
running into problems. we got the positions to instance correctly but the texture coordinates
|
||||
are more difficult to work with because we can't just send a texcoord per vertex per instance
|
||||
- Ended up passing hardcoded texcoords of all glyphs to the shader using a uniform array which allows us to render infinite
|
||||
instances of text in one draw call without exceeding any buffer limits. Of course this does mean that if we were to support
|
||||
unicode we'd have to make the uniform array bigger and its size dynamic. So unicode is dropped for now
|
||||
|
||||
|
||||
text tests / iGPU / Non-instaned rendering
|
||||
- 10 texts / 72 font size
|
||||
0.8-0.9ms per frame (1200-1300fps)
|
||||
|
||||
- 100 texts / 48 font size
|
||||
1.2-1.3ms per frame (770-830fps)
|
||||
|
||||
- 1000 texts / 28 font size
|
||||
9-9.5ms per frame (105-110fps)
|
||||
|
||||
- 10000 texts / 9 font size
|
||||
80-85ms per frame (12-13fps)
|
||||
|
||||
|
||||
@@ -19,15 +19,20 @@
|
||||
Display *display;
|
||||
Window window;
|
||||
|
||||
typedef struct InstanceData {
|
||||
Vec4f position;
|
||||
int tex_coords_index;
|
||||
} InstanceData;
|
||||
|
||||
Context zephr_context;
|
||||
Shader font_shader;
|
||||
Shader ui_shader;
|
||||
unsigned int font_vao;
|
||||
unsigned int ui_vao;
|
||||
unsigned int font_vbo;
|
||||
unsigned int font_instance_vbo;
|
||||
unsigned int ui_vbo;
|
||||
|
||||
// TODO: instanced rendering of ui elements and text??
|
||||
// TODO: instanced rendering of ui elements
|
||||
|
||||
int init_fonts(const char *font_path) {
|
||||
FT_Library ft;
|
||||
@@ -55,22 +60,38 @@ int init_fonts(const char *font_path) {
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
uint max_dim = (1 + (face->size->metrics.height >> 6)) * ceilf(sqrtf(face->num_glyphs));
|
||||
uint tex_width = 1;
|
||||
while (tex_width < max_dim) {
|
||||
tex_width <<= 1;
|
||||
}
|
||||
uint tex_height = tex_width;
|
||||
/* uint max_dim = (1 + (face->size->metrics.height >> 6)) * ceilf(sqrtf(face->num_glyphs)); */
|
||||
/* uint tex_width = 1; */
|
||||
/* while (tex_width < max_dim) { */
|
||||
/* tex_width <<= 1; */
|
||||
/* } */
|
||||
/* uint tex_height = tex_width; */
|
||||
|
||||
char *pixels = (char *)calloc(tex_width * tex_height, 1);
|
||||
int pen_x = 0, pen_y = 0;
|
||||
|
||||
FT_UInt glyph_idx;
|
||||
FT_ULong c = FT_Get_First_Char(face, &glyph_idx);
|
||||
|
||||
while (glyph_idx) {
|
||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
||||
printf("[ERROR]: failed to load glyph for char '0x%lx'\n", c);
|
||||
uint tex_width = 0, tex_height = 0;
|
||||
for (uint i = 32; i < 128; i++) {
|
||||
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
|
||||
printf("[ERROR]: failed to load glyph for char '0x%x'\n", i);
|
||||
}
|
||||
|
||||
/* FT_Render_Glyph(face->glyph, FT_RENDER_MODE_SDF); */
|
||||
|
||||
tex_width += face->glyph->bitmap.width + 1;
|
||||
tex_height = max(tex_height, face->glyph->bitmap.rows);
|
||||
}
|
||||
|
||||
printf("[INFO] Texture size: %d,%d\n", tex_width, tex_height);
|
||||
|
||||
char *pixels = (char *)calloc(tex_width * tex_height, 1);
|
||||
|
||||
for (uint i = 32; i < 128; i++) {
|
||||
/* while (glyph_idx) { */
|
||||
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
|
||||
printf("[ERROR]: failed to load glyph for char '0x%x'\n", i);
|
||||
}
|
||||
|
||||
/* FT_Render_Glyph(face->glyph, FT_RENDER_MODE_SDF); */
|
||||
@@ -110,11 +131,11 @@ int init_fonts(const char *font_path) {
|
||||
character.size = (Size){ .width = face->glyph->bitmap.width, .height = face->glyph->bitmap.rows };
|
||||
character.bearing = (Size){ .width = face->glyph->bitmap_left, .height = face->glyph->bitmap_top };
|
||||
|
||||
hmput(zephr_context.font.characters, c, character);
|
||||
zephr_context.font.characters[i] = character;
|
||||
|
||||
pen_x += bmp->width + 1;
|
||||
|
||||
c = FT_Get_Next_Char(face, c, &glyph_idx);
|
||||
/* c = FT_Get_Next_Char(face, c, &glyph_idx); */
|
||||
}
|
||||
|
||||
unsigned int texture;
|
||||
@@ -140,6 +161,9 @@ int init_fonts(const char *font_path) {
|
||||
}
|
||||
|
||||
int init_ui(const char* font_path, Size window_size) {
|
||||
uint font_vbo;
|
||||
uint font_ebo;
|
||||
|
||||
zephr_context.window_size = window_size;
|
||||
zephr_context.projection = orthographic_projection_2d(0.f, window_size.width, window_size.height, 0.f);
|
||||
|
||||
@@ -152,19 +176,58 @@ int init_ui(const char* font_path, Size window_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
font_shader = create_shader("shaders/ui.vert", "shaders/font.frag");
|
||||
font_shader = create_shader("shaders/font.vert", "shaders/font.frag");
|
||||
ui_shader = create_shader("shaders/ui.vert", "shaders/ui.frag");
|
||||
|
||||
glGenVertexArrays(1, &font_vao);
|
||||
glGenVertexArrays(1, &ui_vao);
|
||||
glGenBuffers(1, &font_vbo);
|
||||
glGenBuffers(1, &font_instance_vbo);
|
||||
glGenBuffers(1, &font_ebo);
|
||||
glGenBuffers(1, &ui_vbo);
|
||||
|
||||
float quad_vertices[4][2] = {
|
||||
{0.0, 1.0}, // top left
|
||||
{1.0, 1.0}, // top right
|
||||
{1.0, 0.0}, // bottom right
|
||||
{0.0, 0.0}, // bottom left
|
||||
};
|
||||
|
||||
int quad_indices[6] = {
|
||||
0, 1, 2,
|
||||
2, 3, 0
|
||||
};
|
||||
|
||||
glBindVertexArray(font_vao);
|
||||
|
||||
// font quad vbo
|
||||
glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 2, quad_vertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
|
||||
|
||||
// font instance vbo
|
||||
glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void *)0);
|
||||
glVertexAttribDivisor(1, 1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribIPointer(2, 1, GL_INT, sizeof(InstanceData), (void *)sizeof(Vec4f));
|
||||
glVertexAttribDivisor(2, 1);
|
||||
|
||||
// font ebo
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad_indices), quad_indices, GL_STATIC_DRAW);
|
||||
|
||||
use_shader(font_shader);
|
||||
|
||||
for (int i = 32; i < 128; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
char text[32];
|
||||
snprintf(text, 32, "texcoords[%d]", (i - 32) * 4 + j);
|
||||
set_vec2f(font_shader, text, zephr_context.font.characters[i].tex_coords[j].x, zephr_context.font.characters[i].tex_coords[j].y);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(ui_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ui_vbo);
|
||||
@@ -256,9 +319,16 @@ bool zephr_should_quit() {
|
||||
/* update_ui(); */
|
||||
audio_update();
|
||||
|
||||
|
||||
return zephr_context.should_quit;
|
||||
}
|
||||
|
||||
// example of how to batch all text drawing in one drawcall
|
||||
// this should be called at the end of the frame
|
||||
/* void batch_text_draw(&zephr_context.texts) {
|
||||
* do something with zephr_context.texts
|
||||
}*/
|
||||
|
||||
void zephr_swap_buffers() {
|
||||
glXSwapBuffers(display, window);
|
||||
}
|
||||
@@ -267,7 +337,7 @@ Size zephr_get_window_size() {
|
||||
return zephr_context.window_size;
|
||||
}
|
||||
|
||||
Sizef calculate_text_size(const wide_str *text, int font_size) {
|
||||
Sizef calculate_text_size(const char *text, int font_size) {
|
||||
float scale = (float)font_size / FONT_PIXEL_SIZE;
|
||||
Sizef size = { .width = 0, .height = 0 };
|
||||
int w = 0;
|
||||
@@ -275,29 +345,27 @@ Sizef calculate_text_size(const wide_str *text, int font_size) {
|
||||
int max_bearing_h = 0;
|
||||
|
||||
// NOTE: I don't like looping through the characters twice, but it's fine for now
|
||||
for (uint i = 0; (i < text[i]) != '\0'; i++) {
|
||||
Character ch = hmget(zephr_context.font.characters, (uint)text[i]);
|
||||
/* Character ch = characters[(uint)text[i]]; */
|
||||
for (int i = 0; text[i] != '\0'; i++) {
|
||||
Character ch = zephr_context.font.characters[(uint)text[i]];
|
||||
max_bearing_h = max(max_bearing_h, ch.bearing.height);
|
||||
}
|
||||
|
||||
for (uint i = 0; (i < text[i]) != '\0'; i++) {
|
||||
Character ch = hmget(zephr_context.font.characters, (uint)text[i]);
|
||||
/* Character ch = characters[(uint)text[i]]; */
|
||||
for (int i = 0; text[i] != '\0'; i++) {
|
||||
Character ch = zephr_context.font.characters[(uint)text[i]];
|
||||
w += ch.advance / 64;
|
||||
|
||||
// remove bearing of first character
|
||||
if (i == 0 && wide_str_len(text) > 1) {
|
||||
if (i == 0 && strlen(text) > 1) {
|
||||
w -= ch.bearing.width;
|
||||
}
|
||||
|
||||
// remove the trailing width of the last character
|
||||
if (i == wide_str_len(text) - 1) {
|
||||
if (i == strlen(text) - 1) {
|
||||
w -= ((ch.advance / 64) - (ch.bearing.width + ch.size.width));
|
||||
}
|
||||
|
||||
// if we only have one character in the text, then remove the bearing width
|
||||
if (wide_str_len(text) == 1) {
|
||||
if (strlen(text) == 1) {
|
||||
w -= (ch.bearing.width);
|
||||
}
|
||||
|
||||
@@ -525,7 +593,7 @@ void draw_triangle(UIConstraints constraints, Color *color, Alignment align) {
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void draw_text(const wide_str* text, int font_size, UIConstraints constraints, Color *color, Alignment alignment) {
|
||||
void draw_text(const char* text, int font_size, UIConstraints constraints, Color *color, Alignment alignment) {
|
||||
use_shader(font_shader);
|
||||
if (color) {
|
||||
set_vec4f(font_shader, "textColor", color->r / 255.f, color->g / 255.f, color->b / 255.f, color->a / 255.f);
|
||||
@@ -556,52 +624,54 @@ void draw_text(const wide_str* text, int font_size, UIConstraints constraints, C
|
||||
set_mat4f(font_shader, "model", (float *)model.m);
|
||||
|
||||
int max_bearing_h = 0;
|
||||
for (uint i = 0; (i < text[i]) != '\0'; i++) {
|
||||
Character ch = hmget(zephr_context.font.characters, text[i]);
|
||||
/* Character ch = characters[(int)text[i]]; */
|
||||
for (int i = 0; (i < text[i]) != '\0'; i++) {
|
||||
Character ch = zephr_context.font.characters[(int)text[i]];
|
||||
max_bearing_h = max(max_bearing_h, ch.bearing.height);
|
||||
}
|
||||
|
||||
float first_char_bearing_w = hmget(zephr_context.font.characters, (int)text[0]).bearing.width;
|
||||
float first_char_bearing_w = zephr_context.font.characters[(int)text[0]].bearing.width;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, zephr_context.font.atlas_texture_id);
|
||||
glBindVertexArray(font_vao);
|
||||
|
||||
InstanceData* instance_data = malloc(sizeof(InstanceData) * strlen(text));
|
||||
|
||||
// we use the original text and character sizes in the loop and then we just
|
||||
// scale up or down the model matrix to get the desired font size.
|
||||
// this way everything works out fine and we get to transform the text using the
|
||||
// model matrix
|
||||
int c = 0;
|
||||
int x = 0;
|
||||
/* int line = 0; */
|
||||
while (text[c] != '\0') {
|
||||
Character ch = hmget(zephr_context.font.characters, text[c]);
|
||||
/* Character ch = characters[(int)text[c]]; */
|
||||
Character ch = zephr_context.font.characters[(int)text[c]];
|
||||
// subtract the bearing width of the first character to remove the extra space
|
||||
// at the start of the text and move every char to the left by that width
|
||||
float xpos = (x + (ch.bearing.width - first_char_bearing_w));
|
||||
float ypos = (text_size.height - ch.bearing.height - (text_size.height - max_bearing_h));
|
||||
float ypos = /*(line * text_size.height) + */(text_size.height - ch.bearing.height - (text_size.height - max_bearing_h));
|
||||
|
||||
float vertices[6][4] = {
|
||||
{xpos, ypos + ch.size.height, ch.tex_coords[0].x, ch.tex_coords[0].y},
|
||||
{xpos, ypos, ch.tex_coords[3].x, ch.tex_coords[3].y},
|
||||
{xpos + ch.size.width, ypos, ch.tex_coords[2].x, ch.tex_coords[2].y},
|
||||
/* if (text[c] == '\n') { */
|
||||
/* line++; */
|
||||
/* x = 0; */
|
||||
/* c++; */
|
||||
/* continue; */
|
||||
/* } */
|
||||
|
||||
{xpos, ypos + ch.size.height, ch.tex_coords[0].x, ch.tex_coords[0].y},
|
||||
{xpos + ch.size.width, ypos, ch.tex_coords[2].x, ch.tex_coords[2].y},
|
||||
{xpos + ch.size.width, ypos + ch.size.height, ch.tex_coords[1].x, ch.tex_coords[1].y},
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
instance_data[c].position = (Vec4f){xpos, ypos, ch.size.width, ch.size.height};
|
||||
instance_data[c].tex_coords_index = (int)text[c] - 32;
|
||||
|
||||
x += (ch.advance >> 6);
|
||||
c++;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(InstanceData) * strlen(text), instance_data, GL_DYNAMIC_DRAW);
|
||||
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL, strlen(text));
|
||||
|
||||
free(instance_data);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
@@ -12,13 +12,8 @@ typedef struct Character {
|
||||
Vec2f tex_coords[4]; // the 4 corners of the character quad
|
||||
} Character;
|
||||
|
||||
typedef struct Characters {
|
||||
uint key;
|
||||
Character value;
|
||||
} Characters;
|
||||
|
||||
typedef struct ZephFont {
|
||||
Characters *characters;
|
||||
Character characters[128];
|
||||
unsigned int atlas_texture_id;
|
||||
} ZephFont;
|
||||
|
||||
@@ -71,5 +66,5 @@ void set_rotation_constraint(UIConstraints *constraints, float angle_d);
|
||||
void draw_quad(UIConstraints constraints, Color *color, float border_radius, Alignment align);
|
||||
void draw_circle(UIConstraints constraints, Color *color, Alignment align);
|
||||
void draw_triangle(UIConstraints constraints, Color *color, Alignment align);
|
||||
void draw_text(const uint* text, int font_size, UIConstraints constraints, Color *color, Alignment align);
|
||||
Sizef calculate_text_size(const uint *text, int font_size);
|
||||
void draw_text(const char* text, int font_size, UIConstraints constraints, Color *color, Alignment align);
|
||||
Sizef calculate_text_size(const char *text, int font_size);
|
||||
|
||||
Reference in New Issue
Block a user