diff options
| author | iamcheeseman <[email protected]> | 2026-05-08 19:30:44 -0400 |
|---|---|---|
| committer | iamcheeseman <[email protected]> | 2026-05-08 19:30:44 -0400 |
| commit | 5625a8626fe303748b205c80f87035593cf2f561 (patch) | |
| tree | 5e5a5adb6f1265358ae21ec47cd384362345df5a /teensy/renderer.c | |
Initial commit
Diffstat (limited to 'teensy/renderer.c')
| -rw-r--r-- | teensy/renderer.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/teensy/renderer.c b/teensy/renderer.c new file mode 100644 index 0000000..9e5f824 --- /dev/null +++ b/teensy/renderer.c @@ -0,0 +1,227 @@ +#include "renderer.h" + +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "context.h" +#include "dyn_arr.h" + +struct ty_renderer r; + +static +void renderer_init_check() +{ +#ifdef TEENSY_DEBUG + if ( + r.screen.data == NULL || + r.screen.width * r.screen.height == 0 + ) { + ty_log_fatal( + TY_ERR_RENDERER_NOT_INIT, + "renderer is not yet intialized" + ); + } +#endif +} + +static +void image_bounds_check(struct ty_image img, struct ty_vec2i pos) +{ +#ifdef TEENSY_DEBUG + if ( + pos.x < 0 || + pos.x >= img.width || + pos.y < 0 || + pos.y >= img.height + ) { + ty_log_fatal( + TY_ERR_RENDER_OOB, + "rendered at (%d, %d), when bounds are " + "(0, 0) to (%d, %d)", + pos.x, pos.y, + img.width, img.height + ); + } +#endif +} + +void ty_init_renderer(void) +{ + r.screen = ty_create_image( + ctx.creation_hints.win_width, + ctx.creation_hints.win_height, + NULL + ); +} + +void ty_deinit_renderer(void) +{ + renderer_init_check(); + + ty_free_image(r.screen); +} + +struct ty_image ty_create_image(int w, int h, const struct ty_color* data) +{ + struct ty_image img; + + img.width = w; + img.height = h; + + size_t size = sizeof(struct ty_color) * w * h; + img.data = ty_alloc(size); + if (data) + memcpy(img.data, data, size); + else + memset(img.data, 0, size); + + return img; +} + +void ty_free_image(struct ty_image img) +{ + ty_free(img.data); +} + +struct ty_color ty_img_get_pixel(struct ty_image img, struct ty_vec2i pos) +{ + image_bounds_check(img, pos); + return img.data[pos.y * img.width + pos.x]; +} + +void ty_img_set_pixel( + struct ty_image img, + struct ty_vec2i pos, + struct ty_color color +) { + image_bounds_check(img, pos); + img.data[pos.y * img.width + pos.x] = color; +} + +void ty_draw_clear(struct ty_color col) +{ + renderer_init_check(); + for (int i = 0; i < r.screen.width * r.screen.height; i++) { + r.screen.data[i] = col; + } +} + +void ty_draw_image(struct ty_image img, struct ty_vec2i pos) +{ + int x1 = fmin(fmax(floor(pos.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(pos.y), 0), r.screen.height); + + int x2 = fmin(fmax(floor(pos.x + img.width), 0), r.screen.width); + int y2 = fmin(fmax(floor(pos.y + img.height), 0), r.screen.height); + + for (int dx = x1; dx < x2; dx++) { + for (int dy = y1; dy < y2; dy++) { + struct ty_vec2i tex_coord = ty_vec2i(dx - x1, dy - y1); + ty_img_set_pixel( + r.screen, + (struct ty_vec2i){dx, dy}, + ty_img_get_pixel(img, tex_coord) + ); + } + } +} + +void ty_draw_image_ex( + struct ty_image img, + struct ty_recti src, + struct ty_recti dst +) { + int x1 = fmin(fmax(floor(dst.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(dst.y), 0), r.screen.height); + int x2 = fmin(fmax(floor(dst.x + dst.w), 0), r.screen.width); + int y2 = fmin(fmax(floor(dst.y + dst.h), 0), r.screen.height); + + for (int dx = x1; dx < x2; dx++) { + for (int dy = y1; dy < y2; dy++) { + int tex_x = (dx - x1) / (dst.w / src.w) + src.x; + int tex_y = (dy - y1) / (dst.h / src.h) + src.y; + + ty_img_set_pixel( + r.screen, + (struct ty_vec2i){dx, dy}, + ty_img_get_pixel(img, ty_vec2i(tex_x, tex_y)) + ); + } + } +} + +void ty_draw_rect(struct ty_recti rect, struct ty_color color) +{ + int x1 = fmin(fmax(floor(rect.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(rect.y), 0), r.screen.height); + + int x2 = fmin(fmax(floor(rect.x + rect.w), 0), r.screen.width); + int y2 = fmin(fmax(floor(rect.y + rect.h), 0), r.screen.height); + + for (int dx = x1; dx < x2; dx++) { + for (int dy = y1; dy < y2; dy++) { + ty_img_set_pixel( + r.screen, + (struct ty_vec2i){dx, dy}, + color + ); + } + } +} + +void ty_draw_line( + struct ty_vec2i start, + struct ty_vec2i end, + struct ty_color color +) { + int dx = end.x - start.x; + int dy = end.y - start.y; + + if (abs(dx) > abs(dy)) { + if (start.x > end.x) { + int tmp = start.x; + start.x = end.x; + end.x = tmp; + + tmp = start.y; + start.y = end.y; + end.y = tmp; + } + + for (int x = start.x; x < end.x; x++) { + int y = start.y + dy * (x - start.x) / dx; + + ty_img_set_pixel( + r.screen, + (struct ty_vec2i){x, y}, + color + ); + } + } else { + if (start.y > end.y) { + int tmp = start.x; + start.x = end.x; + end.x = tmp; + + tmp = start.y; + start.y = end.y; + end.y = tmp; + } + + for (int y = start.y; y < end.y; y++) { + int x = start.x + dx * (y - start.y) / dy; + + ty_img_set_pixel( + r.screen, + ty_vec2i(x, y), + color + ); + } + } +} + +void ty_draw_end(void) +{ + renderer_init_check(); +} |
