#include #include #include #include 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; }