summaryrefslogtreecommitdiff
path: root/gastro/src/test.c
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-08-28 20:51:55 -0400
committerLLLL Colonq <llll@colonq>2026-08-28 20:52:14 -0400
commit8567564e6df6efbcf138b390ba181b8ebb118fa1 (patch)
treee43f62ef593ef5211722335dcb3c9d72e54230b4 /gastro/src/test.c
parentfece4fc3d4decb70c94b49ab854fa9ae93b4d887 (diff)
gastro: render test scene
Diffstat (limited to 'gastro/src/test.c')
-rw-r--r--gastro/src/test.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/gastro/src/test.c b/gastro/src/test.c
new file mode 100644
index 0000000..46ce6b1
--- /dev/null
+++ b/gastro/src/test.c
@@ -0,0 +1,203 @@
+#include <lcq/gastro/test.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+static i64 off = 0;
+static gastro_program program;
+static qoi_color *texture;
+static i64 texture_width;
+static i64 texture_height;
+
+#define QUADIDX(p0, p1, p2, p3) p0, p1, p2, p2, p3, p0
+#define COLOR(r, g, b) gastro_fix_new(r), gastro_fix_new(g), gastro_fix_new(b)
+static void draw_quad(gastro_ctx *ctx, gastro_program *p) {
+ gastro_fix sz = GASTRO_FIX_HALF;
+ gastro_fix verts[] = {
+ /* front */
+ -sz, -sz, -sz, 0, 0,
+ +sz, -sz, -sz, GASTRO_FIX_ONE, 0,
+ +sz, +sz, -sz, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -sz, +sz, -sz, 0, GASTRO_FIX_ONE
+ };
+ i64 idxs[] = {
+ QUADIDX(0, 1, 2, 3), /* front */
+ };
+ gastro_render_triangles(ctx, p, verts, 5, idxs, 2);
+}
+static void draw_cube(gastro_ctx *ctx, gastro_program *p) {
+ static gastro_fix verts[] = {
+ /* front */
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ /* right */
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ /* left */
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ /* top */
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ /* bottom */
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, 0,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ /* back */
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE
+ };
+ static i64 idxs[] = {
+ QUADIDX(0, 1, 2, 3), /* front */
+ QUADIDX(4, 5, 6, 7), /* right */
+ QUADIDX(8, 9, 10, 11), /* left */
+ QUADIDX(12, 13, 14, 15), /* top */
+ QUADIDX(16, 17, 18, 19), /* bottom */
+ QUADIDX(20, 21, 22, 23) /* back */
+ };
+ gastro_render_triangles(ctx, p, verts, 5, idxs, 12);
+}
+static void draw_pyramid(gastro_ctx *ctx, gastro_program *p) {
+ static gastro_fix verts[] = {
+ /* front */
+ 0, +GASTRO_FIX_HALF, 0, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ /* right */
+ 0, +GASTRO_FIX_HALF, 0, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ /* left */
+ 0, +GASTRO_FIX_HALF, 0, 0, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ /* back */
+ 0, +GASTRO_FIX_HALF, 0, 0, 0,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ /* bottom */
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, 0, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, GASTRO_FIX_ONE, 0,
+ +GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, GASTRO_FIX_ONE, GASTRO_FIX_ONE,
+ -GASTRO_FIX_HALF, -GASTRO_FIX_HALF, +GASTRO_FIX_HALF, 0, GASTRO_FIX_ONE,
+ };
+ static i64 idxs[] = {
+ 0, 1, 2,
+ 3, 4, 5,
+ 6, 7, 8,
+ 9, 10, 11,
+ QUADIDX(12, 13, 14, 15),
+ };
+ gastro_render_triangles(ctx, p, verts, 5, idxs, 6);
+}
+
+static gastro_vec4 vertex_shader(gastro_ctx *ctx, gastro_vec3 in, gastro_fix *attrs, i64 attrs_len) {
+ gastro_fix x = gastro_fix_from_double((double) off / 1000.0);
+ gastro_vec4 v = gastro_vec4_new(in.x, in.y, in.z, GASTRO_FIX_ONE);
+ gastro_mat4x4 scale = gastro_mat4x4_new(
+ gastro_fix_from_double(1.0), 0, 0, 0,
+ 0, gastro_fix_from_double(1.0), 0, 0,
+ 0, 0, gastro_fix_from_double(1.0), 0,
+ 0, 0, 0, GASTRO_FIX_ONE
+ );
+ u8 theta = (u8) (off / 4);
+ /* u8 theta = 13; */
+ gastro_mat4x4 rot = gastro_mat4x4_new(
+ GASTRO_FIX_ONE, 0, 0, 0,
+ 0, gastro_cos(theta), -gastro_sin(theta), 0,
+ 0, gastro_sin(theta), gastro_cos(theta), 0,
+ 0, 0, 0, GASTRO_FIX_ONE
+ );
+ gastro_mat4x4 trans = gastro_mat4x4_new(
+ GASTRO_FIX_ONE, 0, 0, gastro_fix_new(0), /* x,*/
+ 0, GASTRO_FIX_ONE, 0, gastro_fix_new(1),
+ 0, 0, GASTRO_FIX_ONE, gastro_fix_new(-3),
+ 0, 0, 0, GASTRO_FIX_ONE
+ );
+ gastro_mat4x4 proj = gastro_mat4x4_new(
+ GASTRO_FIX_ONE, 0, 0, 0,
+ 0, GASTRO_FIX_ONE, 0, 0,
+ 0, 0, GASTRO_FIX_ONE, 0,
+ 0, 0, GASTRO_FIX_ONE, 0
+ );
+ v = gastro_mat4x4_mul_vec4(scale, v);
+ v = gastro_mat4x4_mul_vec4(rot, v);
+ v = gastro_mat4x4_mul_vec4(trans, v);
+ v = gastro_mat4x4_mul_vec4(proj, v);
+ return v;
+}
+
+static gastro_color fragment_shader_texture(gastro_ctx *ctx, gastro_vec3 in, gastro_fix *attrs, i64 attrs_len) {
+ gastro_fix u = attrs[0];
+ gastro_fix v = attrs[1];
+ i64 x = gastro_fix_to_i64(gastro_fix_mul(gastro_fix_new(texture_width), u));
+ i64 y = gastro_fix_to_i64(gastro_fix_mul(gastro_fix_new(texture_height), v));
+ qoi_color c = texture[y * texture_width + x];
+ return gastro_color_new(c.r, c.g, c.b, c.a);
+}
+
+static gastro_color fragment_shader_teapot(gastro_ctx *ctx, gastro_vec3 in, gastro_fix *attrs, i64 attrs_len) {
+ u8 col = (u8) gastro_fix_to_i64(
+ gastro_fix_mul(
+ gastro_fix_new(0xff),
+ gastro_fix_div(in.z, gastro_fix_new(8))
+ )
+ );
+ return gastro_color_new(0xff - col, 0xff - col, 0xff - col, 0xff);
+}
+
+static void load_image(char *path) {
+ FILE *f;
+ u8 *buf;
+ i64 len;
+ qoi_decoder q;
+ qoi_header h;
+ qoi_color *pixels;
+ if (!(f = fopen(path, "r"))) {
+ fprintf(stderr, "failed to open file: %s\n", path);
+ return;
+ }
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = calloc((size_t) len, sizeof(u8));
+ fread(buf, sizeof(u8), (size_t) len, f);
+ qoi_decoder_new(&q, buf, len);
+ if (!qoi_decode_header(&q, &h)) {
+ fprintf(stderr, "failed to decode header\n");
+ return;
+ }
+ pixels = calloc(h.width * h.height, sizeof(qoi_color));
+ qoi_decode(&q, &h, pixels);
+ texture = pixels;
+ texture_width = h.width;
+ texture_height = h.height;
+}
+
+bool gastro_test_create() {
+ program.vertex = vertex_shader;
+ program.fragment = fragment_shader_texture;
+ load_image("test.qoi");
+}
+
+void gastro_test_render(gastro_ctx *ctx) {
+ gastro_draw_clear(ctx, gastro_color_new(0, 0, 0, 0xff));
+ for (i64 i = 0; i < 1; ++i) {
+ draw_pyramid(ctx, &program);
+ }
+ /* draw_quad(&ctx, &p); */
+ /* draw_model(&ctx, &p); */
+ off += 1;
+ off %= 256 * 64;
+}