This commit is contained in:
veclav talica 2024-10-14 11:48:46 +03:00
commit d34516c4ee
7 changed files with 54 additions and 32 deletions

View File

@ -20,9 +20,9 @@ static void title_tick(State *state) {
((float)ctx.resolution.x / 2) - ((float)320 / 2), 64, 320, 128 })); ((float)ctx.resolution.x / 2) - ((float)320 / 2), 64, 320, 128 }));
/* draw the tick count as an example of dynamic text */ /* draw the tick count as an example of dynamic text */
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->frame_number) + 1; size_t text_str_len = snprintf(NULL, 0, "%llu", state->ctx->frame_number) + 1;
char *text_str = cmalloc(text_str_len); char *text_str = cmalloc(text_str_len);
snprintf(text_str, text_str_len, "%lu", state->ctx->frame_number); snprintf(text_str, text_str_len, "%llu", state->ctx->frame_number);
const char *font = "/fonts/kenney-pixel.ttf"; const char *font = "/fonts/kenney-pixel.ttf";
int text_h = 32; int text_h = 32;
@ -39,7 +39,6 @@ static void title_tick(State *state) {
); );
draw_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font); draw_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font);
free(text_str); free(text_str);
} }

View File

@ -22,6 +22,7 @@ TWN_API void draw_sprite(char const *path,
TWN_API void draw_rectangle(Rect rect, Color color); TWN_API void draw_rectangle(Rect rect, Color color);
/* pushes a filled circle onto the circle render queue */ /* pushes a filled circle onto the circle render queue */
/* note that its edges may look jagged with a radius larger than 2048 */
TWN_API void draw_circle(Vec2 position, float radius, Color color); TWN_API void draw_circle(Vec2 position, float radius, Color color);
/* TODO: have font optional, with something minimal coming embedded */ /* TODO: have font optional, with something minimal coming embedded */

View File

@ -22,18 +22,14 @@ void draw_circle(Vec2 position, float radius, Color color) {
arrput(ctx.render_queue_2d, primitive); arrput(ctx.render_queue_2d, primitive);
} }
/* TODO: caching and reuse scheme */
/* vertices_out and indices_out MUST BE FREED */
void create_circle_geometry(Vec2 position, void create_circle_geometry(Vec2 position,
Color color, Color color,
float radius, float radius,
size_t num_vertices, size_t num_vertices,
SDL_Vertex **vertices_out, SDL_Vertex vertices[],
int **indices_out) int indices[])
{ {
SDL_Vertex *vertices = cmalloc(sizeof *vertices * (num_vertices + 1));
int *indices = cmalloc(sizeof *indices * (num_vertices * 3));
/* the angle (in radians) to rotate by on each iteration */ /* the angle (in radians) to rotate by on each iteration */
float seg_rotation_angle = (360.0f / (float)num_vertices) * ((float)M_PI / 180); float seg_rotation_angle = (360.0f / (float)num_vertices) * ((float)M_PI / 180);
@ -82,7 +78,4 @@ void create_circle_geometry(Vec2 position,
index = num_vertices; index = num_vertices;
indices[triangle_offset + 2] = (int)index; indices[triangle_offset + 2] = (int)index;
} }
*vertices_out = vertices;
*indices_out = indices;
} }

View File

@ -126,12 +126,14 @@ void render(void);
/* clears all render queues */ /* clears all render queues */
void render_queue_clear(void); void render_queue_clear(void);
/* fills two existing arrays with the geometry data of a circle */
/* the size of indices must be at least 3 times the number of vertices */
void create_circle_geometry(Vec2 position, void create_circle_geometry(Vec2 position,
Color color, Color color,
float radius, float radius,
size_t num_vertices, size_t num_vertices,
SDL_Vertex **vertices_out, SDL_Vertex vertices[],
int **indices_out); int indices[]);
struct QuadBatch { struct QuadBatch {
size_t size; /* how many primitives are in current batch */ size_t size; /* how many primitives are in current batch */

View File

@ -87,6 +87,9 @@ typedef enum {
static Pipeline pipeline_last_used = PIPELINE_NO; static Pipeline pipeline_last_used = PIPELINE_NO;
#define CIRCLE_VERTICES_MAX 2048
void use_space_pipeline(void) { void use_space_pipeline(void) {
if (pipeline_last_used == PIPELINE_SPACE) if (pipeline_last_used == PIPELINE_SPACE)
return; return;
@ -166,16 +169,16 @@ void use_2d_pipeline(void) {
void render_circle(const CirclePrimitive *circle) { void render_circle(const CirclePrimitive *circle) {
SDL_Vertex *vertices = NULL; static SDL_Vertex vertices[CIRCLE_VERTICES_MAX];
int *indices = NULL; static int indices[CIRCLE_VERTICES_MAX * 3];
int num_vertices = (int)circle->radius; int num_vertices = MIN((int)circle->radius, CIRCLE_VERTICES_MAX-1);
create_circle_geometry(circle->position, create_circle_geometry(circle->position,
circle->color, circle->color,
circle->radius, circle->radius,
num_vertices, num_vertices,
&vertices, vertices,
&indices); indices);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, glVertexPointer(2,
@ -196,9 +199,6 @@ void render_circle(const CirclePrimitive *circle) {
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
SDL_free(vertices);
SDL_free(indices);
} }

View File

@ -31,6 +31,19 @@ typedef struct StringArena {
static StringArena string_arena; static StringArena string_arena;
typedef struct FontFileBuffer {
size_t len;
unsigned char *buffer;
} FontFileBuffer;
typedef struct FontFileCacheItem {
char *key;
FontFileBuffer value;
} FontFileCacheItem;
static FontFileCacheItem *font_file_cache_hash;
static void string_arena_init(StringArena *arena) { static void string_arena_init(StringArena *arena) {
arena->head = cmalloc(sizeof *arena->head); arena->head = cmalloc(sizeof *arena->head);
arena->current_block = arena->head; arena->current_block = arena->head;
@ -103,12 +116,22 @@ static FontData *text_load_font_data(const char *path, int height_px) {
{ {
unsigned char *buf = NULL; unsigned char *buf = NULL;
int64_t buf_len = file_to_bytes(path, &buf); int64_t buf_len = 0;
/* if the file was already loaded just get it */
FontFileCacheItem *font_file_ptr = shgetp_null(font_file_cache_hash, path);
if (font_file_ptr != NULL) {
buf = font_file_ptr->value.buffer;
buf_len = font_file_ptr->value.len;
} else {
buf_len = file_to_bytes(path, &buf);
FontFileBuffer buffer = { buf_len, buf };
shput(font_file_cache_hash, path, buffer);
}
stbtt_InitFont(&font_data->info, buf, stbtt_GetFontOffsetForIndex(buf, 0)); stbtt_InitFont(&font_data->info, buf, stbtt_GetFontOffsetForIndex(buf, 0));
/* might as well get these now, for later */ /* might as well get these now, for later */
font_data->file_bytes = buf;
font_data->file_bytes_len = buf_len;
font_data->scale_factor = stbtt_ScaleForPixelHeight(&font_data->info, (float)height_px); font_data->scale_factor = stbtt_ScaleForPixelHeight(&font_data->info, (float)height_px);
stbtt_GetFontVMetrics( stbtt_GetFontVMetrics(
&font_data->info, &font_data->info,
@ -142,7 +165,6 @@ static FontData *text_load_font_data(const char *path, int height_px) {
static void text_destroy_font_data(FontData *font_data) { static void text_destroy_font_data(FontData *font_data) {
SDL_free(font_data->file_bytes);
delete_gpu_texture(font_data->texture); delete_gpu_texture(font_data->texture);
SDL_free(font_data); SDL_free(font_data);
} }
@ -192,7 +214,7 @@ static void text_draw_with(FontData* font_data, char* text, Vec2 position, Color
static void ensure_font_cache(const char *font_path, int height_px) { static void ensure_font_cache(const char *font_path, int height_px) {
/* HACK: stupid, bad, don't do this */ /* HACK: don't */
bool is_cached = false; bool is_cached = false;
for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) { for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) {
FontData *font_data = ctx.text_cache.data[i]; FontData *font_data = ctx.text_cache.data[i];
@ -229,6 +251,8 @@ void render_text(const TextPrimitive *text) {
void text_cache_init(TextCache *cache) { void text_cache_init(TextCache *cache) {
arrsetlen(cache->data, 0); arrsetlen(cache->data, 0);
string_arena_init(&string_arena); string_arena_init(&string_arena);
sh_new_arena(font_file_cache_hash);
} }
@ -237,8 +261,13 @@ void text_cache_deinit(TextCache *cache) {
text_destroy_font_data(ctx.text_cache.data[i]); text_destroy_font_data(ctx.text_cache.data[i]);
} }
arrfree(cache->data); for (size_t i = 0; i < shlenu(font_file_cache_hash); ++i) {
SDL_free(font_file_cache_hash[i].value.buffer);
}
shfree(font_file_cache_hash);
string_arena_deinit(&string_arena); string_arena_deinit(&string_arena);
arrfree(cache->data);
} }

View File

@ -22,8 +22,6 @@ typedef struct FontData {
stbtt_fontinfo info; stbtt_fontinfo info;
const char *file_path; const char *file_path;
unsigned char *file_bytes;
size_t file_bytes_len;
GPUTexture texture; GPUTexture texture;