refactor: grid and timer using zephr

This commit is contained in:
2023-11-26 05:34:42 +02:00
parent d3eb097f1e
commit 63759ffa1b
7 changed files with 141 additions and 209 deletions
+109 -73
View File
@@ -74,15 +74,37 @@ void draw_win(Cudoku *game) {
draw_text(time_text, 48.f, constraints, &text_color, ALIGN_CENTER);
}
void set_scale_factor(int width, int height, float *x, float *y) {
if (width > height) {
float ratio = (float)height / (float)width;
*x = ratio;
*y = 1.f;
} else {
float ratio = (float)width / (float)height;
*x = 1.f;
*y = ratio;
void draw_grid(Size window_size) {
Color bg_color = {240.0f, 235.0f, 227.0f, 255.f};
Color color = {0.0f, 0.0f, 0.0f, 255.f};
UIConstraints constraints = {0};
set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
set_width_constraint(&constraints, window_size.width, UI_CONSTRAINT_FIXED);
set_height_constraint(&constraints, window_size.height, UI_CONSTRAINT_FIXED);
draw_quad(constraints, &bg_color, 0.0, ALIGN_TOP_LEFT);
for (int i = 1; i < 10; i++) {
set_x_constraint(&constraints, i * 100, UI_CONSTRAINT_FIXED);
set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
if (i % 3 == 0) {
set_width_constraint(&constraints, 4, UI_CONSTRAINT_FIXED);
} else {
set_width_constraint(&constraints, 2, UI_CONSTRAINT_FIXED);
}
set_height_constraint(&constraints, window_size.height, UI_CONSTRAINT_FIXED);
draw_quad(constraints, &color, 0.0, ALIGN_TOP_LEFT);
set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&constraints, i * 100, UI_CONSTRAINT_FIXED);
set_width_constraint(&constraints, window_size.width, UI_CONSTRAINT_FIXED);
if (i % 3 == 0) {
set_height_constraint(&constraints, 4, UI_CONSTRAINT_FIXED);
} else {
set_height_constraint(&constraints, 2, UI_CONSTRAINT_FIXED);
}
draw_quad(constraints, &color, 0.0, ALIGN_TOP_LEFT);
}
}
@@ -617,82 +639,96 @@ void draw_ui_element_at(Shader shader, unsigned int vao, unsigned int vbo, Matri
glBindVertexArray(0);
}
void draw_help_overlay(Shader overlay_shader, Shader font_shader, unsigned int overlay_vao, unsigned int overlay_vbo, unsigned int font_vao, unsigned int font_vbo, Matrix4x4 *projection, int window_height, Timer *timer) {
int total_help_texts_height = 20;
/* void draw_help_overlay(Timer *timer) { */
/* int total_help_texts_height = 20; */
int const text_padding = 10;
float const text_scale = 0.3f;
int overlay_height = 0;
int overlay_width = 0;
/* int const text_padding = 10; */
/* float const text_scale = 0.3f; */
/* int overlay_height = 0; */
/* int overlay_width = 0; */
for (int i = 0; i < HELP_TEXT_SIZE; i++) {
/* Size text_size = calculate_text_size(help_texts[i], text_scale); */
/* overlay_height += text_size.height + text_padding; */
/* overlay_width = max(overlay_width, text_size.width + text_padding * 2); */
}
Size size = {.width = overlay_width, .height = overlay_height + text_padding * 2};
Vec2 pos = {
.x = 0,
.y = window_height - size.height
};
Color color = {
.r = 0.1f,
.g = 0.1f,
.b = 0.1f,
.a = 0.95f
};
draw_ui_element_at(overlay_shader, overlay_vao, overlay_vbo, projection, pos, size, color);
/* for (int i = 0; i < HELP_TEXT_SIZE; i++) { */
/* /1* Size text_size = calculate_text_size(help_texts[i], text_scale); *1/ */
/* /1* overlay_height += text_size.height + text_padding; *1/ */
/* /1* overlay_width = max(overlay_width, text_size.width + text_padding * 2); *1/ */
/* } */
/* Size size = {.width = overlay_width, .height = overlay_height + text_padding * 2}; */
/* /1* Vec2 pos = { *1/ */
/* /1* .x = 0, *1/ */
/* /1* .y = window_height - size.height *1/ */
/* /1* }; *1/ */
/* Color color = { */
/* .r = 0.1f, */
/* .g = 0.1f, */
/* .b = 0.1f, */
/* .a = 0.95f */
/* }; */
/* /1* draw_ui_element_at(overlay_shader, overlay_vao, overlay_vbo, projection, pos, size, color); *1/ */
for (int i = 0; i < HELP_TEXT_SIZE; i++) {
/* Size text_size = calculate_text_size(help_texts[i], text_scale); */
/* Vec2 text_pos = { */
/* .x = text_padding, */
/* .y = window_height - total_help_texts_height - (text_padding * 2) */
/* }; */
/* total_help_texts_height += text_size.height + text_padding; */
/* draw_text_at(font_shader, help_texts[i], text_pos, text_scale, font_vao, font_vbo, (float *)projection->m, NULL); */
}
/* for (int i = 0; i < HELP_TEXT_SIZE; i++) { */
/* /1* Size text_size = calculate_text_size(help_texts[i], text_scale); *1/ */
/* /1* Vec2 text_pos = { *1/ */
/* /1* .x = text_padding, *1/ */
/* /1* .y = window_height - total_help_texts_height - (text_padding * 2) *1/ */
/* /1* }; *1/ */
/* /1* total_help_texts_height += text_size.height + text_padding; *1/ */
/* /1* draw_text_at(font_shader, help_texts[i], text_pos, text_scale, font_vao, font_vbo, (float *)projection->m, NULL); *1/ */
/* } */
if (timer->is_running) {
char closing_in_text[128];
/* snprintf(closing_in_text, sizeof(closing_in_text), "Hiding in %ds", (int)timer_remaining(timer) + 1); */
/* Size closing_in_text_size = calculate_text_size(closing_in_text, text_scale / 2.0); */
/* Vec2 closing_in_text_pos = { */
/* .x = overlay_width - closing_in_text_size.width, */
/* .y = window_height - closing_in_text_size.height - text_padding, */
/* }; */
/* Color closing_in_text_color = { */
/* .r = 255.0f, */
/* .g = 150.0f, */
/* .b = 0.0f, */
/* .a = 1.0f, */
/* }; */
/* draw_text_at(font_shader, closing_in_text, closing_in_text_pos, text_scale / 2.0, font_vao, font_vbo, (float *)projection->m, &closing_in_text_color); */
}
}
/* if (timer->is_running) { */
/* char closing_in_text[128]; */
/* /1* snprintf(closing_in_text, sizeof(closing_in_text), "Hiding in %ds", (int)timer_remaining(timer) + 1); *1/ */
/* /1* Size closing_in_text_size = calculate_text_size(closing_in_text, text_scale / 2.0); *1/ */
/* /1* Vec2 closing_in_text_pos = { *1/ */
/* /1* .x = overlay_width - closing_in_text_size.width, *1/ */
/* /1* .y = window_height - closing_in_text_size.height - text_padding, *1/ */
/* /1* }; *1/ */
/* /1* Color closing_in_text_color = { *1/ */
/* /1* .r = 255.0f, *1/ */
/* /1* .g = 150.0f, *1/ */
/* /1* .b = 0.0f, *1/ */
/* /1* .a = 1.0f, *1/ */
/* /1* }; *1/ */
/* /1* draw_text_at(font_shader, closing_in_text, closing_in_text_pos, text_scale / 2.0, font_vao, font_vbo, (float *)projection->m, &closing_in_text_color); *1/ */
/* } */
/* } */
void draw_timer(Shader shader, unsigned int vao, unsigned int vbo, float *projection, Timer *timer, int win_width) {
void draw_timer(Timer *timer) {
if (!timer->is_running) return;
char timer_text[64];
Color text_color = {
.r = 66.0f,
.g = 92.0f,
.b = 124.0f,
.a = 255.0f,
};
Color bg_color = {
.r = 0.0f,
.g = 0.0f,
.b = 0.0f,
.a = 25.0f,
};
float font_size = 32.f;
Alignment alignment = ALIGN_BOTTOM_RIGHT;
float elapsed = timer_elapsed(timer);
int minutes = elapsed / 60;
int seconds = (int)elapsed % 60;
/* snprintf(timer_text, sizeof(timer_text), "Time: %02d:%02d", minutes, seconds); */
/* float text_scale = 0.35f; */
/* Size text_size = calculate_text_size(timer_text, text_scale); */
/* Vec2 text_pos = { */
/* .x = win_width - text_size.width - 10, */
/* .y = 10, */
/* }; */
/* Color text_color = { */
/* .r = 66.0f, */
/* .g = 92.0f, */
/* .b = 124.0f, */
/* .a = 1.0f, */
/* }; */
snprintf(timer_text, sizeof(timer_text), "Time: %02d:%02d", minutes, seconds);
/* draw_text_at(shader, timer_text, text_pos, text_scale, vao, vbo, projection, &text_color); */
Sizef text_size = calculate_text_size(timer_text, font_size);
UIConstraints constraints = {0};
set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED);
set_width_constraint(&constraints, text_size.width + 4, UI_CONSTRAINT_FIXED);
set_height_constraint(&constraints, text_size.height + 4, UI_CONSTRAINT_FIXED);
draw_quad(constraints, &bg_color, 0.0, alignment);
set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED);
set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED);
draw_text(timer_text, font_size, constraints, &text_color, alignment);
}
+2 -1
View File
@@ -53,5 +53,6 @@ void draw_help_overlay(
int window_height,
Timer *timer
);
void draw_timer(Shader shader, unsigned int vao, unsigned int vbo, float *projection, Timer *timer, int win_width);
void draw_timer(Timer *timer);
void draw_win(Cudoku *game);
void draw_grid(Size window_size);
+12 -73
View File
@@ -88,10 +88,6 @@ void handle_keypress(XEvent xev, Cudoku *game) {
int main(int argc, char *argv[]) {
bool use_texture = false;
// scale factors for the entire board to nicely fit as a square inside
// the window
float x_scale = 1.f, y_scale = 1.f;
if (argc > 1) {
char *flag = argv[1];
if (strcmp(flag, "-h") == 0 || strcmp(flag, "--help") == 0) {
@@ -121,8 +117,9 @@ int main(int argc, char *argv[]) {
}
}
Color clear_color = {0.2f, 0.15f, 0.5f, 1.f};
int res = init_zephr(font_path, title, (Size){900, 900}, &clear_color);
Color clear_color = {0.0f, 0.0f, 0.0f, 1.f};
Size window_size = {900, 900};
int res = init_zephr(font_path, title, window_size, &clear_color);
if (res != 0) {
printf("[ERROR]: could not initialize zephr\n");
return 1;
@@ -136,21 +133,14 @@ int main(int argc, char *argv[]) {
generate_random_board(&game);
Shader grid_shader;
unsigned int grid_texture;
if (!use_texture)
grid_shader = create_shader("shaders/board_v.vert", "shaders/grid_f.frag");
else
if (use_texture)
grid_shader = create_shader("shaders/board_v.vert", "shaders/board_f.frag");
int board_vao = prepare_bg(use_texture, &grid_texture);
Shader selection_shader = create_shader("shaders/board_v.vert", "shaders/quad.frag");
/* Shader selection_shader = create_shader("shaders/board_v.vert", "shaders/quad.frag"); */
unsigned int selection_vao, selection_vbo;
Color selection_color = {0.4f, 0.4f, 1.0f, 0.5f};
prepare_selection_box(&selection_vao, &selection_vbo);
Shader win_shader = create_shader("shaders/board_v.vert", "shaders/quad.frag");
float delta_t, last_t = 0.0;
timer_start(&game.help_timer, 5.0f);
timer_start(&game.timer, 0.0f);
@@ -160,49 +150,15 @@ int main(int argc, char *argv[]) {
delta_t = now - last_t;
last_t = now;
Size window_size = zephr_get_window_size();
/* int width = 15.f; */
/* int height = 35.f; */
/* int padding = 10.f; */
float ratio_w = (float)window_size.width / 1920.f;
float ratio_h = (float)window_size.height / 1080.f;
int width = window_size.height;
int height = window_size.width;
if (window_size.height > window_size.width) {
width = window_size.width;
height = window_size.width;
} else {
width = window_size.height;
height = window_size.height;
if (!use_texture) {
draw_grid(window_size);
}
draw_win(&game);
/* draw_quad( */
/* (Vec2){0.0, 0.0}, */
/* (Size){width, height}, */
/* &(Color){240.f, 235.f, 227.f, 255.f}, */
/* ALIGN_CENTER); */
/* UIConstraints constraints = {0}; */
/* set_x_constraint(&constraints, 0.0, UI_CONSTRAINT_FIXED); */
/* set_y_constraint(&constraints, 0.0, UI_CONSTRAINT_FIXED); */
/* set_width_constraint(&constraints, 50, UI_CONSTRAINT_FIXED); */
/* set_height_constraint(&constraints, 50, UI_CONSTRAINT_FIXED); */
/* draw_quad( */
/* constraints, */
/* &(Color){240.f, 235.f, 227.f, 255.f}, */
/* ALIGN_TOP_LEFT */
/* ); */
/* Size size = calculate_text_size("Bruh", 1.0f); */
/* float x = clampf(500.0f * timer_elapsed(&my_time), 0.0, window_size.width - size.width); */
/* draw_text("Bruh", 1.0f, (Vec2){0.0, size.height}, &(Color){255.f, 0.f, 0.f, 255.f}); */
draw_timer(&game.timer);
if (game.has_won) {
draw_win(&game);
}
zephr_batch_text_draw();
zephr_swap_buffers();
@@ -240,18 +196,7 @@ int main(int argc, char *argv[]) {
/* /1* } *1/ */
/* /1* } *1/ */
/* float transform[4][4] = { */
/* {x_scale, 0, 0, 0}, */
/* {0, y_scale, 0, 0}, */
/* {0, 0, 1, 0}, */
/* {0, 0, 0, 1}, */
/* }; */
/* /1* Matrix4x4 projection = orthographic_projection_2d(0.0f, width, 0.0f, height); *1/ */
/* /1* if (!use_texture) *1/ */
/* /1* draw_bg_grid_shader(grid_shader, board_vao, (float *)transform, width < height ? width : height); *1/ */
/* /1* else *1/ */
/* /1* if (use_texture) *1/ */
/* /1* draw_bg_grid_texture(grid_shader, board_vao, grid_texture, (float *)transform); *1/ */
/* if (game.should_draw_selection) */
@@ -277,8 +222,6 @@ int main(int argc, char *argv[]) {
/* /1* draw_text_at(font_shader, text, text_pos, text_scale, font_vao, font_vbo, (float *)projection.m, &text_color); *1/ */
/* /1* } *1/ */
/* /1* draw_timer(font_shader, font_vao, font_vbo, (float *)projection.m, &game.timer, width); *1/ */
/* if (timer_ended(&game.help_timer)) { */
/* timer_stop(&game.help_timer); */
/* game.should_draw_help = false; */
@@ -287,10 +230,6 @@ int main(int argc, char *argv[]) {
/* /1* if (game.should_draw_help) *1/ */
/* /1* draw_help_overlay(selection_shader, font_shader, selection_vao, selection_vbo, font_vao, font_vbo, &projection, height, &game.help_timer); *1/ */
/* /1* if (game.has_won) { *1/ */
/* /1* draw_win_overlay(win_shader, font_shader, win_vao, font_vao, font_vbo, (float *)transform, &game); *1/ */
/* /1* } *1/ */
/* /1* glXSwapBuffers(display, window); *1/ */
/* } */
-51
View File
@@ -1,51 +0,0 @@
#version 330 core
out vec4 FragColor;
uniform mat4 transform;
uniform float resolution;
void main()
{
// Define the size of the grid
int gridSize = 9;
// Calculate the step size for the grid lines
float stepSize = 2.0 / float(gridSize);
// Calculate the UV coordinates of the current fragment
vec2 uv = (gl_FragCoord * transform).xy / vec2(resolution, resolution); // Adjust the resolution as needed
float scale_x = transform[0][0];
float scale_y = transform[1][1];
// Calculate the coordinates of the current fragment in the [-1, 1] range
float fragCoordX = (uv.x - 0.5) * (2.0 / scale_x) - 1.0;
float fragCoordY = (uv.y - 0.5) * (2.0 / scale_y) - 1.0;
// Colors for grid lines
vec3 gridColor = vec3(0.4, 0.4, 0.4);
vec3 gridColorThick = vec3(0.2, 0.2, 0.2);
bool isInsideGridHorizontally = (fragCoordX >= -2.0 && fragCoordX <= 0.0);
bool isInsideGridVertically = (fragCoordY >= -2.0 && fragCoordY <= 0.0);
bool isInsideGrid = isInsideGridHorizontally && isInsideGridVertically;
// Determine if the current fragment is on a thicker grid line
bool isThickLineX = isInsideGrid && mod(fragCoordX, (stepSize + 0.0007) * 3) <= 0.01;
bool isThickLineY = isInsideGrid && mod(fragCoordY, (stepSize + 0.0007) * 3) <= 0.01;
// Check if the current fragment is on a grid line
// 0.0007 to shift the grid lines a bit to the left
bool isGridX = isInsideGrid && mod(fragCoordX, stepSize + 0.0007) <= 0.005;
bool isGridY = isInsideGrid && mod(fragCoordY, stepSize + 0.0007) <= 0.005;
// Set the fragment color based on whether it's a grid line or a thicker grid line
if ((isThickLineX) || (isThickLineY)) {
FragColor = vec4(gridColorThick, 1.0);
} else if (isGridX || isGridY) {
FragColor = vec4(gridColor, 1.0);
} else {
FragColor = vec4(240.f/255.f, 235.f/255.f, 227.f/255.f, 1.0);
}
}
-8
View File
@@ -1,8 +0,0 @@
#version 330 core
out vec4 FragColor;
uniform vec4 aColor;
void main() {
FragColor = vec4(aColor);
}
+15
View File
@@ -1,5 +1,20 @@
- "premade" (but also customizable) ui elements (buttons, text boxes, etc) with instanced rendering
- border decorations for shapes (maybe. or maybe only for ui elements)
- some kind of ui layout/hierarchy system (for later, when we actually need it)
- grid texture (draw_image? or draw_texture? func)
- sooo a bit of a problem... since we render all our text in one draw call
at the end of the frame. this means that we can't have text that's rendered
in behind anything else. This needs to be fixed because drawing any overlay
will result in all the text being drawn OVER everything else, which might not be
the desired behavior at times (e.g. help/win overlay where the board numbers need to be
rendered under the overlay(s))
- possible solutions :Clueless:
- z-index based on the order of creation (e.g. the first drawable created has the lowest z-index)
I _think_ this works because we can just chuck a global z-index whenever we call
draw_text or draw_quad/etc.. and the shader _should_ take care of everything
- every draw_text call actually makes a single draw call (compromises on performance but way easier to use)
text rendering improvements
- [ ] unicode support (allows for non-ascii characters)
+3 -3
View File
@@ -320,7 +320,6 @@ bool zephr_should_quit() {
zephr_context.window_size = (Size){ .width = xce.width, .height = xce.height };
zephr_context.projection = orthographic_projection_2d(0.f, xce.width, xce.height, 0.f);
resize_x11_window(display, window);
/* set_scale_factor(xce.width, xce.height, &x_scale, &y_scale); */
}
} else if (xev.type == KeyPress) {
@@ -354,8 +353,8 @@ bool zephr_should_quit() {
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
/* This MUST be called at the end of the frame
if you wish to draw text */
void zephr_batch_text_draw() {
glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(TextInstance) * zephr_context.texts.size, zephr_context.texts.data, GL_DYNAMIC_DRAW);
@@ -368,6 +367,7 @@ void zephr_batch_text_draw() {
clear_text_instance_list(&zephr_context.texts);
}
// This MUST be called at the end of the frame
void zephr_swap_buffers() {
glXSwapBuffers(display, window);
}