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 }));
/* 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);
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";
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);
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);
/* 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);
/* 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);
}
/* TODO: caching and reuse scheme */
/* vertices_out and indices_out MUST BE FREED */
void create_circle_geometry(Vec2 position,
Color color,
float radius,
size_t num_vertices,
SDL_Vertex **vertices_out,
int **indices_out)
SDL_Vertex vertices[],
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 */
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;
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 */
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,
Color color,
float radius,
size_t num_vertices,
SDL_Vertex **vertices_out,
int **indices_out);
SDL_Vertex vertices[],
int indices[]);
struct QuadBatch {
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;
#define CIRCLE_VERTICES_MAX 2048
void use_space_pipeline(void) {
if (pipeline_last_used == PIPELINE_SPACE)
return;
@ -166,16 +169,16 @@ void use_2d_pipeline(void) {
void render_circle(const CirclePrimitive *circle) {
SDL_Vertex *vertices = NULL;
int *indices = NULL;
int num_vertices = (int)circle->radius;
static SDL_Vertex vertices[CIRCLE_VERTICES_MAX];
static int indices[CIRCLE_VERTICES_MAX * 3];
int num_vertices = MIN((int)circle->radius, CIRCLE_VERTICES_MAX-1);
create_circle_geometry(circle->position,
circle->color,
circle->radius,
num_vertices,
&vertices,
&indices);
vertices,
indices);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,
@ -196,9 +199,6 @@ void render_circle(const CirclePrimitive *circle) {
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
SDL_free(vertices);
SDL_free(indices);
}

View File

@ -31,6 +31,19 @@ typedef struct StringArena {
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) {
arena->head = cmalloc(sizeof *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;
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));
/* 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);
stbtt_GetFontVMetrics(
&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) {
SDL_free(font_data->file_bytes);
delete_gpu_texture(font_data->texture);
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) {
/* HACK: stupid, bad, don't do this */
/* HACK: don't */
bool is_cached = false;
for (size_t i = 0; i < arrlenu(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) {
arrsetlen(cache->data, 0);
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]);
}
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);
arrfree(cache->data);
}

View File

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