From 7b29269ac55b3c6d9422cfc44e889358f919edc8 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Fri, 12 Sep 2025 17:43:46 +0300 Subject: [PATCH] Saving uncomplete changes. Have to generate png methods for all the png types --- src/l1/anne/codegen.c | 7 +- .../{vulkan_utils.h => margaret_misc.h} | 5 +- src/l1/anne/margaret/png_pixel_masses.h | 74 +++ src/l1/anne/pixel_masses.h | 16 +- src/l1/anne/some_tests.h | 3 + src/l1/anne/util_temp_very_base.h | 4 + src/l1/codegen/util_template_inst.h | 94 ++++ src/l1/marie/geom_alg_utils.h | 15 + src/l1_5/core/stringop.h | 1 + src/l2/margaret/png_pixel_masses.h | 12 +- src/l2/marie/rasterization.h | 30 +- src/l2/marie/texture_processing.h | 41 ++ src/l2/tests/r0/r0.c | 458 ++++++++++-------- src/l2/tests/r0/r0_assets.h | 131 ++++- src/l2/tests/r0/r0_scene.h | 3 + src/l2/tests/r0/r0_tex_init_prep.c | 41 +- src/l2/tests/tv0/tv0.c | 0 17 files changed, 641 insertions(+), 294 deletions(-) rename src/l1/anne/margaret/{vulkan_utils.h => margaret_misc.h} (91%) create mode 100644 src/l1/anne/margaret/png_pixel_masses.h create mode 100644 src/l2/tests/tv0/tv0.c diff --git a/src/l1/anne/codegen.c b/src/l1/anne/codegen.c index 11b77de..88e241c 100644 --- a/src/l1/anne/codegen.c +++ b/src/l1/anne/codegen.c @@ -7,10 +7,11 @@ #include "some_tests.h" #include "util_temp_vulkan.h" -#include "margaret/vulkan_utils.h" +#include "margaret/margaret_misc.h" #include "marie/graphics_geom.h" #include "liza.h" #include "codegen_from_l1_5.h" +#include "margaret/png_pixel_masses.h" int main() { mkdir_nofail("l1"); @@ -21,10 +22,12 @@ int main() { generate_pixel_masses_header(); generate_headers_for_r0_r1_r2_r3(); generate_util_templ_inst_for_vulkan_headers(); - generate_margaret_eve_for_vulkan_utils(); generate_marie_headers_for_graphics_geom(); generate_liza_l1_headers(); generate_l1_headers_for_l1_5(); + mkdir_nofail("l1/margaret"); + generate_margaret_eve_for_vulkan_utils(); + generate_margaret_png_pixel_masses_header(); finish_layer(cstr("l1")); return 0; } diff --git a/src/l1/anne/margaret/vulkan_utils.h b/src/l1/anne/margaret/margaret_misc.h similarity index 91% rename from src/l1/anne/margaret/vulkan_utils.h rename to src/l1/anne/margaret/margaret_misc.h index 393523f..7c8d7c1 100644 --- a/src/l1/anne/margaret/vulkan_utils.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -1,5 +1,5 @@ -#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_VULKAN_H -#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_VULKAN_H +#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H +#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H #include "../../codegen/util_template_inst.h" @@ -21,4 +21,5 @@ void generate_margaret_eve_for_vulkan_utils() { .collab_vec_span = true}); } + #endif \ No newline at end of file diff --git a/src/l1/anne/margaret/png_pixel_masses.h b/src/l1/anne/margaret/png_pixel_masses.h new file mode 100644 index 0000000..ea00bed --- /dev/null +++ b/src/l1/anne/margaret/png_pixel_masses.h @@ -0,0 +1,74 @@ +#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H +#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H + +#include "../../codegen/util_template_inst.h" + +typedef struct { + int channel_count; + SpanU8 name; +} color_type_name_in_png; + +color_type_name_in_png color_types_names_in_png[3] = { + {1, cstr("PNG_COLOR_TYPE_GRAY")}, + {3, cstr("PNG_COLOR_TYPE_RGB")}, + {4, cstr("PNG_COLOR_TYPE_RGBA")}, +}; + +NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signature, int depth, int channel_count) { + if (depth != 8) + abortf("Please no"); + for (size_t i = 0; i < ARRAY_SIZE(color_types_names_in_png); i++) { + if (channel_count == color_types_names_in_png[i].channel_count) { + SpanU8 color_type = color_types_names_in_png[i].name; + VecU8 res = VecU8_new(); + + VecU8 g_promise = VecU8_fmt("MargaretPromisedPng%s", format_signature); + SpanU8 promise = VecU8_to_span(&g_promise); + VecU8 g_tex = VecU8_fmt("TextureData%s", format_signature); + SpanU8 tex = VecU8_to_span(&g_tex); + + /* Non clonable structure */ + VecU8_append_vec(&res, VecU8_fmt( + "typedef struct {\n" + SPACE4 "FILE* fp;\n" + SPACE4 "png_structp pngshka;\n" + SPACE4 "png_infop info;\n" + SPACE4 "png_infop end_info;\n" + "} %s;\n\n" + "void %s_drop(%s self) {\n" + SPACE4 "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n" + SPACE4 "fclose(self.fp);\n" + "}\n\n", promise, promise, promise)); + + VecU8_append_vec(&res, generate_result_template_inst(promise, cstr("VecU8"), false, false)); + + VecU8_drop(g_promise); + VecU8_drop(g_tex); + return res; + } + } + abortf("Please don't"); +} + +void generate_margaret_png_pixel_masses_header() { + GeneratedHeader header = begin_header(cstr("l1/margaret/png_pixel_masses.h")); + + VecU8_append_span(&header.result, cstr( + "#include \"../pixel_masses.h\"" + "#include \"../ResultVoidOrVecU8\"" + "#include \n\n")); + + VecU8_append_span(&header.result, cstr( + "void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) {\n" + "printf(\"[!] %s\\n\", err);\n" + "}\n\n" + "void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) {\n" + "printf(\"[.] %s\\n\", warning);\n" + "}")); + + VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("TextureDataR8G8B8A8"), 8, 4)); + + finish_header(header); +} + +#endif \ No newline at end of file diff --git a/src/l1/anne/pixel_masses.h b/src/l1/anne/pixel_masses.h index 8a7868d..8e14f6d 100644 --- a/src/l1/anne/pixel_masses.h +++ b/src/l1/anne/pixel_masses.h @@ -2,6 +2,7 @@ #define PROTOTYPE_SRC_L1_CODEGEN_PIXEL_MASSES_H #include "../codegen/codegen.h" +#include "../codegen/util_template_inst.h" /* Used to generate both _at() and _cat() methods */ NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU8 memb, bool const_access) { @@ -76,17 +77,12 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 SPACE4 "write_whole_file_or_abort(path, VecU8_to_span(&data));\n" SPACE4 "VecU8_drop(data);\n" "}\n\n", tex, tex, tex)); - /* Result structure */ - VecU8 g_resoftex = VecU8_fmt("Result%sOrSpanU8", tex); + /* Result structure */ + VecU8 g_resoftex = get_ResultType_inst_name(tex, cstr("SpanU8")); SpanU8 resoftex = VecU8_to_span(&g_resoftex); - VecU8_append_vec(&res, VecU8_fmt( - "typedef struct {\n" - SPACE4 "Result_variant variant;\n" - SPACE4 "union {\n" - SPACE4 SPACE4 "%s ok;\n" - SPACE4 SPACE4 "SpanU8 err;\n" - SPACE4 "};\n" - "} %s;\n\n", tex, resoftex)); + VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("SpanU8"), false, true)); + /* I also add this, because why not?? Maye I will use it in the future... */ + VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("VecU8"), false, false)); /* Method _from_bitmap_text() * We assume that bytes are tightly packed in member type */ VecU8_append_vec(&res, VecU8_fmt( diff --git a/src/l1/anne/some_tests.h b/src/l1/anne/some_tests.h index ca058c4..1182fbe 100644 --- a/src/l1/anne/some_tests.h +++ b/src/l1/anne/some_tests.h @@ -21,6 +21,9 @@ void generate_headers_for_r0_r1_r2_r3() { /* r0_scene.h */ generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("UsedGenericModelOnScene"), true, false); generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("UsedShinyModelOnScene"), true, false); + /* r0 */ + generate_eve_span_company_for_primitive(l, ns, cstr("GenericModelTopAndTexInMemoryInfo"), true, false); + generate_eve_span_company_for_primitive(l, ns, cstr("ShinyModelTopInMemoryInfo"), true, false); } mkdir_nofail("l1/eve/r2"); { /* r2 */ diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index c4ea880..34de7ba 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -55,6 +55,10 @@ void generate_util_temp_very_base_headers() { } generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("CSTR"), cstr(""), true, false); + generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), + cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_int_primitives.h\""), true, false); + generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), + cstr(""), cstr("SpanU8"), cstr("#include \"VecAndSpan_int_primitives.h\""), true, true); } #endif \ No newline at end of file diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 99c08fb..4398c8b 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -3,6 +3,7 @@ #include "codegen.h" + // todo: add macro that iterates over vector /* if !primitive, requires methods T_drop, and, if also clonable, requires method T_clone */ @@ -614,4 +615,97 @@ void generate_guarded_span_company_for_non_primitive_non_clonable( }); } +NODISCARD VecU8 get_ResultType_inst_name(SpanU8 OkT, SpanU8 ErrT){ + bool ok_t_void = OkT.len == 0; + bool err_t_void = ErrT.len == 0; + assert(!ok_t_void || !err_t_void); + return VecU8_fmt("Result%s%s%s", !ok_t_void ? OkT : cstr("Void"), + !err_t_void ? cstr("Or") : cstr(""), !err_t_void ? ErrT : cstr("")); +} + +/* We are talking about Result template instantiation */ +NODISCARD VecU8 generate_result_template_inst(SpanU8 OkT, SpanU8 ErrT, bool ok_t_primitive, bool err_t_primitive) { + bool ok_t_void = OkT.len == 0; + bool err_t_void = ErrT.len == 0; + assert(!ok_t_void || !err_t_void); + assert(!ok_t_void || ok_t_primitive); + assert(!err_t_void || err_t_primitive); + + VecU8 g_ResultT = get_ResultType_inst_name(OkT, ErrT); + SpanU8 ResultT = VecU8_to_span(&g_ResultT); + + VecU8 res = VecU8_new(); + + VecU8_append_span(&res, cstr( + "typedef struct {\n" + SPACE4 "Result_variant variant;\n")); + if (ok_t_void && !err_t_void) { + VecU8_append_vec(&res, VecU8_fmt(SPACE4 "%s err;\n", ErrT)); + } else if (!ok_t_void && err_t_void) { + VecU8_append_vec(&res, VecU8_fmt(SPACE4 "%s ok;\n", OkT)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + SPACE4 "union {\n" + SPACE4 SPACE4 "%s ok;\n" + SPACE4 SPACE4 "%s err;\n" + SPACE4 "};\n", OkT, ErrT)); + } + VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", ResultT)); + + if (!ok_t_primitive || !err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + "void %s_drop(%s self) {\n", ResultT, ResultT)); + if (ok_t_primitive && !err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + SPACE4 "if (self.variant == Result_Err)\n" + SPACE4 SPACE4 "%s_drop(self.err);\n", ErrT)); + } else if (!ok_t_primitive && err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + SPACE4 "if (self.variant == Result_Ok)\n" + SPACE4 SPACE4 "%s_drop(self.ok);\n", OkT)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + SPACE4 "if (self.variant == Result_Ok)\n" + SPACE4 SPACE4 "%s_drop(self.ok);\n" + SPACE4 "else\n" + SPACE4 SPACE4 "%s_drop(self.err);\n", OkT, ErrT)); + } + VecU8_append_span(&res, cstr("}\n\n")); + } + VecU8_drop(g_ResultT); /* ResultT variable invalidated */ + return res; +} + +void generate_eve_header_of_result_type_instantiation( + SpanU8 l, SpanU8 ns, SpanU8 OkT, SpanU8 ErrT, bool ok_t_primitive, bool err_t_primitive + ) { + VecU8 ResultT = get_ResultType_inst_name(OkT, ErrT); + VecU8 nt_filepath = VecU8_fmt("%s/eve/%s/%s.h%c", l, ns, VecU8_to_span(&ResultT), 0); + VecU8 text = generate_result_template_inst(OkT, ErrT, ok_t_primitive, err_t_primitive); + write_whole_file_or_abort((CSTR)text.buf, VecU8_to_span(&text)); + VecU8_drop(text); + VecU8_drop(nt_filepath); + VecU8_drop(ResultT); +} + +void generate_guarded_header_of_result_type_instantiation( + SpanU8 layer, SpanU8 bonus_ns, SpanU8 OkT, SpanU8 ErrT, SpanU8 dependencies, bool ok_t_primitive, bool err_t_primitive + ) { + assert(layer.len > 1); + VecU8 filename = get_ResultType_inst_name(OkT, ErrT); + VecU8 path = VecU8_fmt("%s/%s%s%s", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), VecU8_to_span(&filename)); + GeneratedHeader head = begin_header(VecU8_to_span(&path)); + VecU8_drop(path); + VecU8_drop(filename); + VecU8_append_span(&head.result, cstr("#include \"../../")); + int to_my_layer = get_number_of_parts_in_header_namespace(bonus_ns); + for (int i = 0; i < to_my_layer; i++) + VecU8_append_span(&head.result, cstr("../")); + VecU8_append_span(&head.result, cstr("src/l1/core/util.h\"\n")); + VecU8_append_span(&head.result, dependencies); + VecU8_append_span(&head.result, cstr("\n\n")); + VecU8_append_vec(&head.result, generate_result_template_inst(OkT, ErrT, ok_t_primitive, err_t_primitive)); + finish_header(head); +} + #endif diff --git a/src/l1/marie/geom_alg_utils.h b/src/l1/marie/geom_alg_utils.h index 2cb162b..dd26bd2 100644 --- a/src/l1/marie/geom_alg_utils.h +++ b/src/l1/marie/geom_alg_utils.h @@ -54,6 +54,13 @@ typedef struct { vec2 v2; } MarieTriangle; +MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) { + return (MarieTriangle){ + .v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), + .v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), + .v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))}; +} + #include "../../../gen/l1/eve/marie/VecMarieTriangle.h" typedef struct { @@ -62,6 +69,14 @@ typedef struct { MariePlaneVertAttr v2; } MarieTriangleAttr; +MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) { + return (MarieTriangleAttr){ + {mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}}, + {mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}}, + {mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}}, + }; +} + #include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h" vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) { diff --git a/src/l1_5/core/stringop.h b/src/l1_5/core/stringop.h index e59cd43..ef85baf 100644 --- a/src/l1_5/core/stringop.h +++ b/src/l1_5/core/stringop.h @@ -27,6 +27,7 @@ bool string_contains_string_ignorecase(SpanU8 str1, SpanU8 str2) { return false; } +// todo: create a method "span_contents_equal" in span template bool strings_in_spans_equal(SpanU8 a, SpanU8 b) { if (a.len != b.len) return false; diff --git a/src/l2/margaret/png_pixel_masses.h b/src/l2/margaret/png_pixel_masses.h index 9fbc9c2..e3f1819 100644 --- a/src/l2/margaret/png_pixel_masses.h +++ b/src/l2/margaret/png_pixel_masses.h @@ -4,6 +4,7 @@ #include "../../../gen/l1/pixel_masses.h" #include "../../l1/core/util.h" #include "../../l1/core/VecU8_as_str.h" +#include "../../../gen/l1/ResultVoidOrVecU8" #include // todo: generate all of this automaticcally @@ -16,16 +17,6 @@ void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) printf("[.] %s\n", warning); } -typedef struct { - Result_variant variant; - VecU8 err; -} ResultVoidOrVecU8; - -void ResultVoidOrVecU8_drop(ResultVoidOrVecU8 self) { - if (self.variant == Result_Err) - VecU8_drop(self.err); -} - ResultVoidOrVecU8 TextureDataR8G8B8A8_write_to_png(const TextureDataR8G8B8A8* self, SpanU8 filename) { VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0); FILE *fp = fopen((CSTR)nt_filename.buf, "wb"); @@ -79,7 +70,6 @@ void TextureDataR8G8B8A8_write_to_png_nofail(const TextureDataR8G8B8A8* self, Sp } } -/* This structure will be pinned */ typedef struct { FILE* fp; png_structp pngshka; diff --git a/src/l2/marie/rasterization.h b/src/l2/marie/rasterization.h index ca433c6..78bb141 100644 --- a/src/l2/marie/rasterization.h +++ b/src/l2/marie/rasterization.h @@ -24,7 +24,7 @@ MarieLinearFun marie_gen_scanline_borderline(vec2 a, vec2 b) { /* Utility function, that is used by rasterization function. * Don't use in your code*/ -void marie_rasterize_line_in_triangle_with_attr_sorted( +void marie_h_rasterize_only_one_line_of_triangle( vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 L, S32 R, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, float S, S32 my, FnMarieRasterizerCallback cb ) { @@ -44,7 +44,7 @@ void marie_rasterize_line_in_triangle_with_attr_sorted( /* Utility function, that is used by rasterization function. * Don't use in your code*/ -void marie_scan_rast_line_in_triangle_with_attr_sorted( +void marie_h_rasterize_half_of_triangle( vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 below, S32 above, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, MarieLinearFun left_border, MarieLinearFun right_border, FnMarieRasterizerCallback cb ) { @@ -66,7 +66,9 @@ void marie_scan_rast_line_in_triangle_with_attr_sorted( } } -void marie_rasterize_triangle_with_attr_sorted( +/* Utility function, that is used by rasterization function. + * Don't use in your code*/ +void marie_h_rasterize_triangle_with_attr_sorted( MariePlaneVertAttr v0, MariePlaneVertAttr v1, MariePlaneVertAttr v2, FnMarieRasterizerCallback cb ) { float S = marie_surface(v0.pos, v1.pos, v2.pos); @@ -89,22 +91,22 @@ void marie_rasterize_triangle_with_attr_sorted( MarieLinearFun line_12 = marie_gen_scanline_borderline(v1.pos, v2.pos); MarieLinearFun line_20 = marie_gen_scanline_borderline(v2.pos, v0.pos); - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy0, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy0, cb); if (sy0 + 1 < sy1) { MarieLinearFun left_border = S > 0 ? line_20 : line_01; MarieLinearFun right_border = S > 0 ? line_01 : line_20; - marie_scan_rast_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, sy0, sy1, P0, P1, P2, left_border, right_border, cb); + marie_h_rasterize_half_of_triangle(v0.pos, v1.pos, v2.pos, sy0, sy1, P0, P1, P2, left_border, right_border, cb); } if (sy1 > sy0) { - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy1, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy1, cb); } if (sy1 + 1 < sy2) { MarieLinearFun left_border = S > 0 ? line_20 : line_12; MarieLinearFun right_border = S > 0 ? line_12 : line_20; - marie_scan_rast_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, sy1, sy2, P0, P1, P2, left_border, right_border, cb); + marie_h_rasterize_half_of_triangle(v0.pos, v1.pos, v2.pos, sy1, sy2, P0, P1, P2, left_border, right_border, cb); } if (sy2 > sy1) { - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy2, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy2, cb); } } void marie_rasterize_triangle_with_attr( @@ -112,22 +114,22 @@ void marie_rasterize_triangle_with_attr( ) { if (a.pos.y < b.pos.y) { if (b.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(a, b, c, cb); + marie_h_rasterize_triangle_with_attr_sorted(a, b, c, cb); } else { if (a.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(a, c, b, cb); + marie_h_rasterize_triangle_with_attr_sorted(a, c, b, cb); } else { - marie_rasterize_triangle_with_attr_sorted(c, a, b, cb); + marie_h_rasterize_triangle_with_attr_sorted(c, a, b, cb); } } } else { if (a.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(b, a, c, cb); + marie_h_rasterize_triangle_with_attr_sorted(b, a, c, cb); } else { if (b.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(b, c, a, cb); + marie_h_rasterize_triangle_with_attr_sorted(b, c, a, cb); } else { - marie_rasterize_triangle_with_attr_sorted(c, b, a, cb); + marie_h_rasterize_triangle_with_attr_sorted(c, b, a, cb); } } } diff --git a/src/l2/marie/texture_processing.h b/src/l2/marie/texture_processing.h index 26b177d..7406564 100644 --- a/src/l2/marie/texture_processing.h +++ b/src/l2/marie/texture_processing.h @@ -2,6 +2,7 @@ #define PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H #include "../../../gen/l1/pixel_masses.h" +#include "rasterization.h" void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) { U64 width = self->width; @@ -62,4 +63,44 @@ NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(cons return res; } +vec4 marie_color_cvec4_to_vec4(cvec4 clr) { + return (vec4){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255, (float)clr.w / 255}; +} + +cvec4 marie_color_vec4_to_cvec4(vec4 clr) { + return (cvec4){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255), (U8)roundf(clr.w * 255)}; +} + +vec3 marie_color_cvec3_to_vec3(cvec3 clr) { + return (vec3){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255}; +} + +cvec3 marie_color_vec3_to_cvec3(vec3 clr) { + return (cvec3){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255)}; +} + +typedef struct { + TextureDataR8G8B8A8* self; + cvec4 pixel; +} TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest; + +void TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest(void* ug, S32 x, S32 y, vec4 attr) { + TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest *g = ug; + if (TextureDataR8G8B8A8_is_inside(g->self, x, y)) + *TextureDataR8G8B8A8_mat(g->self, x, y) = g->pixel; +} + +/* Given triangle is not natural : it is from parameter space */ +void TextureDataR8G8B8A8_draw_triangle_of_one_color( + TextureDataR8G8B8A8* self, vec3 color, MarieTriangle param_triang, mat3x2 trop + ) { + TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba = + { self, marie_color_vec4_to_cvec4(vec3_and_one(color)) }; + MarieTriangle natural = MarieTriangle_mat3x2_mul_pos(param_triang, trop); + marie_rasterize_triangle_with_attr( + (MariePlaneVertAttr){natural.v0, {}}, (MariePlaneVertAttr){natural.v1, {}}, (MariePlaneVertAttr){natural.v2, {}}, + (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest, + .guest = &aboba}); +} + #endif \ No newline at end of file diff --git a/src/l2/tests/r0/r0.c b/src/l2/tests/r0/r0.c index e47d1cc..671d82b 100644 --- a/src/l2/tests/r0/r0.c +++ b/src/l2/tests/r0/r0.c @@ -1019,6 +1019,32 @@ typedef struct { VkQueue presentation_queue; } UsedVulkanQueues; +typedef struct { + MargaretBufferInMemoryInfo vbo; + MargaretBufferInMemoryInfo ebo; + /* We store image in yet another meaningless buffer (will change it later) */ + TextureDataR8G8B8A8 reading_diffuse; + TextureDataR8G8B8A8 reading_normal; + TextureDataR8 reading_specular; + /* Filled during first (and the only) memory init */ + MargaretImageInMemoryInfo diffuse; + MargaretImageInMemoryInfo normal; + MargaretImageInMemoryInfo specular; + /* will be filled in later */ + VkImageView diffuse_view; + VkImageView normal_view; + VkImageView specular_view; +} GenericModelTopAndTexInMemoryInfo; + +#include "../../../../gen/l1/eve/r0/VecGenericModelTopAndTexInMemoryInfo.h" + +typedef struct { + MargaretBufferInMemoryInfo vbo; + MargaretBufferInMemoryInfo ebo; +} ShinyModelTopInMemoryInfo; + +#include "../../../../gen/l1/eve/r0/VecShinyModelTopInMemoryInfo.h" + typedef struct { MargaretInstanceAndItsDebug instance_and_debug; VkSurfaceKHR surface; @@ -1037,20 +1063,15 @@ typedef struct { MargaretSwapchainBundle swfb; SceneTemplate scene_template; - TextureDataR8G8B8A8 cyl_1_diffuse_tex; - TextureDataR8G8B8A8 cyl_1_normal_tex; + + VecGenericModelTopAndTexInMemoryInfo device_generic_models_top_and_tex; + VecShinyModelTopInMemoryInfo device_shiny_models_top; MargaretBufferInMemoryInfo host_mem_buffer; VkDeviceMemory host_mem; - VecMargaretBufferInMemoryInfo device_ebo_buffers_for_generic_meshes; - VecMargaretBufferInMemoryInfo device_vbo_buffers_for_generic_meshes; - VecMargaretBufferInMemoryInfo device_ebo_buffers_for_shiny_meshes; - VecMargaretBufferInMemoryInfo device_vbo_buffers_for_shiny_meshes; MargaretBufferInMemoryInfo device_lighting_ubo; MargaretBufferInMemoryInfo device_instance_attrs_for_models; MargaretImageInMemoryInfo device_IT1_image; MargaretImageInMemoryInfo device_zbuffer_image; - MargaretImageInMemoryInfo device_cyl_1_diffuse_texture; - MargaretImageInMemoryInfo device_cyl_1_normal_texture; VkDeviceMemory device_mem; VkCommandPool command_pool; @@ -1664,6 +1685,7 @@ int main() { state_r0 state = {0}; state.sane_image_extent_limit = (VkExtent2D){1000, 700}; + vulkan_ctx_r0 *vk_ctx = &state.vk_ctx; state.wl_display = wl_display_connect(NULL); if (!state.wl_display) @@ -1701,181 +1723,192 @@ int main() { abortf("wl_surface_frame\n"); wl_callback_add_listener(state.wl_callback, &main_h_wl_surface_frame_listener, &state); - state.vk_ctx.instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); - VkInstance instance = state.vk_ctx.instance_and_debug.instance; + vk_ctx->instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); + VkInstance instance = vk_ctx->instance_and_debug.instance; // print_instance_available_extensions(instance); // print_instance_available_layers(instance); - state.vk_ctx.surface = margaret_create_surface(instance, state.wl_display, state.wl_surface); + vk_ctx->surface = margaret_create_surface(instance, state.wl_display, state.wl_surface); - state.vk_ctx.physical_device = margaret_select_one_physical_device( - instance, state.vk_ctx.surface, GPU, bugged_GPU, sane_image_extent_limit); + vk_ctx->physical_device = margaret_select_one_physical_device( + instance, vk_ctx->surface, GPU, bugged_GPU, sane_image_extent_limit); // print_physical_device_available_extensions(physical_device); ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families( - state.vk_ctx.physical_device, state.vk_ctx.surface); + vk_ctx->physical_device, vk_ctx->surface); if (queue_fam_res.variant != Result_Ok) abortf("queue_fam_res.variant != Result_Ok"); - state.vk_ctx.queue_fam = queue_fam_res.ok; + vk_ctx->queue_fam = queue_fam_res.ok; - state.vk_ctx.device = margaret_create_logical_device(state.vk_ctx.physical_device, state.vk_ctx.queue_fam); + vk_ctx->device = margaret_create_logical_device(vk_ctx->physical_device, vk_ctx->queue_fam); - vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics, 0, &state.vk_ctx.queues.graphics_queue); - vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_presentation, 0, &state.vk_ctx.queues.presentation_queue); + vkGetDeviceQueue(vk_ctx->device, vk_ctx->queue_fam.for_graphics, 0, &vk_ctx->queues.graphics_queue); + vkGetDeviceQueue(vk_ctx->device, vk_ctx->queue_fam.for_presentation, 0, &vk_ctx->queues.presentation_queue); ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - state.vk_ctx.physical_device, state.vk_ctx.surface, sane_image_extent_limit); + vk_ctx->physical_device, vk_ctx->surface, sane_image_extent_limit); if (swapchain_details_res.variant != Result_Ok) abortf("swapchain_details_res.variant != Result_Ok"); - OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(state.vk_ctx.physical_device); + OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(vk_ctx->physical_device); if (zbuffer_format.variant != Option_Some) abortf("Could not find supported zbuffer format\n"); - state.vk_ctx.zbuffer_format = zbuffer_format.some; - OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(state.vk_ctx.physical_device); + vk_ctx->zbuffer_format = zbuffer_format.some; + OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(vk_ctx->physical_device); if (IT1_format.variant != Option_Some) abortf("Could not find supported hdr buffer format\n"); - state.vk_ctx.IT1_format = IT1_format.some; + vk_ctx->IT1_format = IT1_format.some; - state.vk_ctx.render_pass_0 = create_render_pass_0(state.vk_ctx.device, IT1_format.some, zbuffer_format.some); - state.vk_ctx.pipeline_hands_0a = create_graphics_pipeline_0(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0); - state.vk_ctx.pipeline_hands_0b = create_graphics_pipeline_0_b(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0); + vk_ctx->render_pass_0 = create_render_pass_0(vk_ctx->device, IT1_format.some, zbuffer_format.some); + vk_ctx->pipeline_hands_0a = create_graphics_pipeline_0(vk_ctx->device, vk_ctx->render_pass_0, 0); + vk_ctx->pipeline_hands_0b = create_graphics_pipeline_0_b(vk_ctx->device, vk_ctx->render_pass_0, 0); - state.vk_ctx.render_pass_1 = create_render_pass_1(state.vk_ctx.device, swapchain_details_res.ok.surface_format.format); - state.vk_ctx.pipeline_hands_1 = create_graphics_pipeline_1(state.vk_ctx.device, state.vk_ctx.render_pass_1, 0); + vk_ctx->render_pass_1 = create_render_pass_1(vk_ctx->device, swapchain_details_res.ok.surface_format.format); + vk_ctx->pipeline_hands_1 = create_graphics_pipeline_1(vk_ctx->device, vk_ctx->render_pass_1, 0); - state.vk_ctx.swfb = MargaretSwapchainBundle_new( - state.vk_ctx.device, state.vk_ctx.queue_fam, swapchain_details_res.ok, - state.vk_ctx.surface, state.vk_ctx.render_pass_1, NULL); + vk_ctx->swfb = MargaretSwapchainBundle_new( + vk_ctx->device, vk_ctx->queue_fam, swapchain_details_res.ok, + vk_ctx->surface, vk_ctx->render_pass_1, NULL); - state.vk_ctx.scene_template = (SceneTemplate){ + vk_ctx->scene_template = (SceneTemplate){ .generic_models = VecGenericMeshInSceneTemplate_new(), .shiny_models = VecShinyMeshInSceneTemplate_new(), .point_lights_max_count = pipeline_0_ubo_point_light_max_count, .spotlights_max_count = pipeline_0_ubo_spotlight_max_count}; - VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models, - (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100}); - VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models, - (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1}); - VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){ + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(10, 2, 6, 100)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(5, 5, 10, 1)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(1, 10, 4, 2)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(2, 1, 6, 2)); + VecShinyMeshInSceneTemplate_append(&vk_ctx->scene_template.shiny_models, (ShinyMeshInSceneTemplate){ .topology = generate_shiny_rhombicuboctahedron(0.5f), .max_instance_count = 5 }); - VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){ + VecShinyMeshInSceneTemplate_append(&vk_ctx->scene_template.shiny_models, (ShinyMeshInSceneTemplate){ .topology = generate_shiny_cube(0.5f), .max_instance_count = 5 }); - // todo: generate more cool shiny models - // todo: learn how to use libpng - state.vk_ctx.cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("textures/log_10_2_6.png")); - // todo: learn how to write texture immediately from file to mapped host memory buffer - // todo: and at the same time I need to add methods to convert between these formats - state.vk_ctx.cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("textures/log_10_2_6_NORMAL.png")); + vk_ctx->device_generic_models_top_and_tex = VecGenericModelTopAndTexInMemoryInfo_new_reserved(vk_ctx->scene_template.generic_models.len); + for (size_t i = 0; i < vk_ctx->scene_template.generic_models.len; i++) { + const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&vk_ctx->scene_template.generic_models, i); + VecGenericModelTopAndTexInMemoryInfo_append(&vk_ctx->device_generic_models_top_and_tex, + (GenericModelTopAndTexInMemoryInfo){ + .vbo = GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len), + .ebo = margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len), + .reading_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&M->diffuse_texture_path)), + .reading_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&M->diffuse_texture_path)), + // todo: continue from here. But first - create TextureDataR8 reading function + .reading_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&M->diffuse_texture_path)), + }); + } + // todo: kill myself (update: still WiP (update: it's became growing technical debt point now) - // todo: kill myself (update: still WiP) // We have only one staging buffer in host memory (because we don't really need more) - state.vk_ctx.host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = - MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&state.vk_ctx.scene_template), - MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&state.vk_ctx.scene_template), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex), 0)))) + vk_ctx->host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = + MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&vk_ctx->scene_template), + MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&vk_ctx->scene_template), + MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->cyl_1_diffuse_tex), + MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->cyl_1_normal_tex), 0)))) , .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; - PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&state.vk_ctx.host_mem_buffer}; - state.vk_ctx.host_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, + PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&vk_ctx->host_mem_buffer}; + vk_ctx->host_mem = margaret_initialize_buffers_and_images(vk_ctx->physical_device, vk_ctx->device, (MutSpanPtrMargaretBufferInMemoryInfo){.data = host_mem_buffer_SPAN, .len = 1}, (MutSpanPtrMargaretImageInMemoryInfo){ 0 }, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); // todo: split this in two (or maybe even better: merge it all into one/two buffer and use offsets - state.vk_ctx.device_ebo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); - state.vk_ctx.device_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); - for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) { - const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, + vk_ctx->device_ebo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); + vk_ctx->device_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); + for (size_t mi = 0; mi < vk_ctx->scene_template.generic_models.len; mi++) { + const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&vk_ctx->scene_template.generic_models, mi); + VecMargaretBufferInMemoryInfo_append(&vk_ctx->device_vbo_buffers_for_generic_meshes, GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len)); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, + VecMargaretBufferInMemoryInfo_append(&vk_ctx->device_ebo_buffers_for_generic_meshes, margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len)); } - state.vk_ctx.device_ebo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); - state.vk_ctx.device_vbo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); - for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) { - const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, + vk_ctx->device_ebo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); + vk_ctx->device_vbo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); + for (size_t mi = 0; mi < vk_ctx->scene_template.shiny_models.len; mi++) { + const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&vk_ctx->scene_template.shiny_models, mi); + VecMargaretBufferInMemoryInfo_append(&vk_ctx->device_vbo_buffers_for_shiny_meshes, ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len)); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, + VecMargaretBufferInMemoryInfo_append(&vk_ctx->device_ebo_buffers_for_shiny_meshes, margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len)); } - state.vk_ctx.device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); - state.vk_ctx.device_instance_attrs_for_models = (MargaretBufferInMemoryInfo){ - .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&state.vk_ctx.scene_template), + vk_ctx->device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); + vk_ctx->device_instance_attrs_for_models = (MargaretBufferInMemoryInfo){ + .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&vk_ctx->scene_template), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT }; VecPtrMargaretBufferInMemoryInfo device_mem_buffers_SPAN = VecPtrMargaretBufferInMemoryInfo_new(); // todo: add iteration macro generation - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++) { + for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_generic_meshes.len; i++) { VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i)); + VecMargaretBufferInMemoryInfo_mat(&vk_ctx->device_ebo_buffers_for_generic_meshes, i)); } - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++) { + for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_generic_meshes.len; i++) { VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i)); + VecMargaretBufferInMemoryInfo_mat(&vk_ctx->device_vbo_buffers_for_generic_meshes, i)); } - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++) { + for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_shiny_meshes.len; i++) { VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i)); + VecMargaretBufferInMemoryInfo_mat(&vk_ctx->device_ebo_buffers_for_shiny_meshes, i)); } - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++) { + for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_shiny_meshes.len; i++) { VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i)); + VecMargaretBufferInMemoryInfo_mat(&vk_ctx->device_vbo_buffers_for_shiny_meshes, i)); } - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_lighting_ubo); - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_instance_attrs_for_models); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &vk_ctx->device_lighting_ubo); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &vk_ctx->device_instance_attrs_for_models); - state.vk_ctx.device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer( + vk_ctx->device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer( MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some); - state.vk_ctx.device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer( + vk_ctx->device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer( MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some); - state.vk_ctx.device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba( - state.vk_ctx.cyl_1_diffuse_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_diffuse_tex)); - state.vk_ctx.device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_unorm_32( - state.vk_ctx.cyl_1_normal_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_normal_tex)); + vk_ctx->device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba( + vk_ctx->cyl_1_diffuse_tex.width, TextureDataR8G8B8A8_get_height(&vk_ctx->cyl_1_diffuse_tex)); + vk_ctx->device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_unorm_32( + vk_ctx->cyl_1_normal_tex.width, TextureDataR8G8B8A8_get_height(&vk_ctx->cyl_1_normal_tex)); PtrMargaretImageInMemoryInfo device_mem_images_SPAN[] = { - &state.vk_ctx.device_IT1_image, &state.vk_ctx.device_zbuffer_image, &state.vk_ctx.device_cyl_1_diffuse_texture, - &state.vk_ctx.device_cyl_1_normal_texture + &vk_ctx->device_IT1_image, &vk_ctx->device_zbuffer_image, &vk_ctx->device_cyl_1_diffuse_texture, + &vk_ctx->device_cyl_1_normal_texture }; - state.vk_ctx.device_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, + vk_ctx->device_mem = margaret_initialize_buffers_and_images(vk_ctx->physical_device, vk_ctx->device, VecPtrMargaretBufferInMemoryInfo_to_mspan(&device_mem_buffers_SPAN), (MutSpanPtrMargaretImageInMemoryInfo){ .data = device_mem_images_SPAN, .len = ARRAY_SIZE(device_mem_images_SPAN) }, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); /* device_mem_buffers_SPAN invalidated */ VecPtrMargaretBufferInMemoryInfo_drop(device_mem_buffers_SPAN); - state.vk_ctx.command_pool = margaret_create_resettable_command_pool(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics); - state.vk_ctx.rendering_command_buffer_0 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); - state.vk_ctx.rendering_command_buffer_1 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); - state.vk_ctx.transfer_command_buffer = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); + vk_ctx->command_pool = margaret_create_resettable_command_pool(vk_ctx->device, vk_ctx->queue_fam.for_graphics); + vk_ctx->rendering_command_buffer_0 = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); + vk_ctx->rendering_command_buffer_1 = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); + vk_ctx->transfer_command_buffer = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); - state.vk_ctx.my_cam_control_info = CamControlInfo_new(); - state.vk_ctx.Buba_control_info = (vec3){0}; + vk_ctx->my_cam_control_info = CamControlInfo_new(); + vk_ctx->Buba_control_info = (vec3){0}; - state.vk_ctx.scene = Scene_new(); + vk_ctx->scene = Scene_new(); { size_t offset_in_attr_buffer = 0; - for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) { - const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi); - VecUsedGenericModelOnScene_append(&state.vk_ctx.scene.generic_models, (UsedGenericModelOnScene){ + for (size_t mi = 0; mi < vk_ctx->scene_template.generic_models.len; mi++) { + const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&vk_ctx->scene_template.generic_models, mi); + VecUsedGenericModelOnScene_append(&vk_ctx->scene.generic_models, (UsedGenericModelOnScene){ .model = (ModelOnSceneMem){ .vbo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_vbo_buffers_for_generic_meshes, mi)->buffer, + &vk_ctx->device_vbo_buffers_for_generic_meshes, mi)->buffer, .ebo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_ebo_buffers_for_generic_meshes, mi)->buffer, + &vk_ctx->device_ebo_buffers_for_generic_meshes, mi)->buffer, .indexes = M->topology.indexes.len, - .instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer, + .instance_attr_buf = vk_ctx->device_instance_attrs_for_models.buffer, .instance_attr_buf_offset = offset_in_attr_buffer, .limit_max_instance_count = M->max_instance_count }, @@ -1883,16 +1916,16 @@ int main() { }); offset_in_attr_buffer += M->max_instance_count * sizeof(GenericMeshInstance); } - for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) { - const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi); - VecUsedShinyModelOnScene_append(&state.vk_ctx.scene.shiny_models, (UsedShinyModelOnScene){ + for (size_t mi = 0; mi < vk_ctx->scene_template.shiny_models.len; mi++) { + const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&vk_ctx->scene_template.shiny_models, mi); + VecUsedShinyModelOnScene_append(&vk_ctx->scene.shiny_models, (UsedShinyModelOnScene){ .model = (ModelOnSceneMem){ .vbo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_vbo_buffers_for_shiny_meshes, mi)->buffer, + &vk_ctx->device_vbo_buffers_for_shiny_meshes, mi)->buffer, .ebo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_ebo_buffers_for_shiny_meshes, mi)->buffer, + &vk_ctx->device_ebo_buffers_for_shiny_meshes, mi)->buffer, .indexes = M->topology.indexes.len, - .instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer, + .instance_attr_buf = vk_ctx->device_instance_attrs_for_models.buffer, .instance_attr_buf_offset = offset_in_attr_buffer, .limit_max_instance_count = M->max_instance_count }, @@ -1904,121 +1937,121 @@ int main() { for (int X = 0; X < 10; X++) { for (int Z = 0; Z < 10; Z++) { - VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 0)->instances, + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 0)->instances, (GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}) }); } } - VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 1)->instances, - (GenericMeshInstance){ .model_t = marie_translation_mat4(state.vk_ctx.Buba_control_info) + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 1)->instances, + (GenericMeshInstance){ .model_t = marie_translation_mat4(vk_ctx->Buba_control_info) }); for (U64 i = 0; i < 5; i++) { - VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 0)->instances, + VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&vk_ctx->scene.shiny_models, 0)->instances, (ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){ (float)((i * i * 10 + i * 4 + 1) % 13) + 2, (float)((i * i * 11 + i * 2 + 2) % 13), (float)((i * i * 9 + i * 1 + 4) % 13) + 3}), .color_off = (vec3){0.6f, 0.2f, 0.2f}}); } - VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 1)->instances, + VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&vk_ctx->scene.shiny_models, 1)->instances, (ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){-5, 0, 3}), .color_off = (vec3){0.3f, 0.5f, 0.5f}}); // todo: synchronize them with my cool light sources) - if (vkMapMemory(state.vk_ctx.device, state.vk_ctx.host_mem, 0, VK_WHOLE_SIZE, 0, &state.vk_ctx.host_mem_buffer_mem) != VK_SUCCESS) + if (vkMapMemory(vk_ctx->device, vk_ctx->host_mem, 0, VK_WHOLE_SIZE, 0, &vk_ctx->host_mem_buffer_mem) != VK_SUCCESS) abortf("vkMapMemory"); SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( - &state.vk_ctx.scene_template, &state.vk_ctx.scene, state.vk_ctx.host_mem_buffer_mem, - state.vk_ctx.transfer_command_buffer, state.vk_ctx.host_mem_buffer.buffer); + &vk_ctx->scene_template, &vk_ctx->scene, vk_ctx->host_mem_buffer_mem, + vk_ctx->transfer_command_buffer, vk_ctx->host_mem_buffer.buffer); { - VkCommandBuffer command_buffers[1] = { state.vk_ctx.transfer_command_buffer }; + VkCommandBuffer command_buffers[1] = { vk_ctx->transfer_command_buffer }; VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = ARRAY_SIZE(command_buffers), .pCommandBuffers = command_buffers, }; - if (vkQueueSubmit(state.vk_ctx.queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + if (vkQueueSubmit(vk_ctx->queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) abortf("vkQueueSubmit\n"); } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); { - memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_diffuse_tex.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex)); + memcpy(vk_ctx->host_mem_buffer_mem, vk_ctx->cyl_1_diffuse_tex.pixels.buf, + TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->cyl_1_diffuse_tex)); margaret_copy_buffer_to_texture_for_frag_shader_imm( - state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, - &state.vk_ctx.device_cyl_1_diffuse_texture, state.vk_ctx.host_mem_buffer.buffer); + vk_ctx->device, vk_ctx->command_pool, vk_ctx->queues.graphics_queue, + &vk_ctx->device_cyl_1_diffuse_texture, vk_ctx->host_mem_buffer.buffer); } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); { - memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_normal_tex.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex)); + memcpy(vk_ctx->host_mem_buffer_mem, vk_ctx->cyl_1_normal_tex.pixels.buf, + TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->cyl_1_normal_tex)); margaret_copy_buffer_to_texture_for_frag_shader_imm( - state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, - &state.vk_ctx.device_cyl_1_normal_texture, state.vk_ctx.host_mem_buffer.buffer); + vk_ctx->device, vk_ctx->command_pool, vk_ctx->queues.graphics_queue, + &vk_ctx->device_cyl_1_normal_texture, vk_ctx->host_mem_buffer.buffer); } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); // We sent everything we needed. but host_mem_buffer_mem may be used later // My zbuffer also needs a view - state.vk_ctx.zbuffer_view = margaret_create_view_for_image(state.vk_ctx.device, - &state.vk_ctx.device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); + vk_ctx->zbuffer_view = margaret_create_view_for_image(vk_ctx->device, + &vk_ctx->device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); /* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */ - state.vk_ctx.IT1_view = margaret_create_view_for_image(state.vk_ctx.device, - &state.vk_ctx.device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); - state.vk_ctx.IT1_framebuffer = create_IT1_framebuffer(state.vk_ctx.device, - state.vk_ctx.IT1_view, state.vk_ctx.zbuffer_view, state.vk_ctx.render_pass_0, MAX_WIN_WIDTH, MAX_WIN_HEIGHT); + vk_ctx->IT1_view = margaret_create_view_for_image(vk_ctx->device, + &vk_ctx->device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); + vk_ctx->IT1_framebuffer = create_IT1_framebuffer(vk_ctx->device, + vk_ctx->IT1_view, vk_ctx->zbuffer_view, vk_ctx->render_pass_0, MAX_WIN_WIDTH, MAX_WIN_HEIGHT); // My cylinder 1 texture needs VkImageView - state.vk_ctx.cyl_1_diffuse_texture_view = margaret_create_view_for_image( - state.vk_ctx.device, &state.vk_ctx.device_cyl_1_diffuse_texture, VK_IMAGE_ASPECT_COLOR_BIT); + vk_ctx->cyl_1_diffuse_texture_view = margaret_create_view_for_image( + vk_ctx->device, &vk_ctx->device_cyl_1_diffuse_texture, VK_IMAGE_ASPECT_COLOR_BIT); // My cylinder 1 normal texture also needs NkImageView - state.vk_ctx.cyl_1_normal_texture_view = margaret_create_view_for_image( - state.vk_ctx.device, &state.vk_ctx.device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT); + vk_ctx->cyl_1_normal_texture_view = margaret_create_view_for_image( + vk_ctx->device, &vk_ctx->device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT); // Right now I only have one light source - VecPipeline0PointLight_append(&state.vk_ctx.scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); + VecPipeline0PointLight_append(&vk_ctx->scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); // These samplers are global for a lot of my future textures - state.vk_ctx.linear_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, true); - state.vk_ctx.nearest_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, false); + vk_ctx->linear_sampler = margaret_create_sampler(vk_ctx->physical_device, vk_ctx->device, true); + vk_ctx->nearest_sampler = margaret_create_sampler(vk_ctx->physical_device, vk_ctx->device, false); - state.vk_ctx.descriptor_pool = margaret_create_descriptor_set_pool(state.vk_ctx.device, 2, 3, 3); - state.vk_ctx.descriptor_set_for_pipeline_0a = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0a.descriptor_set_layout); - state.vk_ctx.descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0b.descriptor_set_layout); - state.vk_ctx.descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_1.descriptor_set_layout); + vk_ctx->descriptor_pool = margaret_create_descriptor_set_pool(vk_ctx->device, 2, 3, 3); + vk_ctx->descriptor_set_for_pipeline_0a = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_0a.descriptor_set_layout); + vk_ctx->descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_0b.descriptor_set_layout); + vk_ctx->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_1.descriptor_set_layout); // Configuring my descriptor sets, that I just allocated VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0a = { - .buffer = state.vk_ctx.device_lighting_ubo.buffer, + .buffer = vk_ctx->device_lighting_ubo.buffer, .offset = 0, .range = sizeof(Pipeline0UBO), }; VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0a = { - .sampler = state.vk_ctx.linear_sampler, - .imageView = state.vk_ctx.cyl_1_diffuse_texture_view, + .sampler = vk_ctx->linear_sampler, + .imageView = vk_ctx->cyl_1_diffuse_texture_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = { - .sampler = state.vk_ctx.nearest_sampler, - .imageView = state.vk_ctx.cyl_1_normal_texture_view, + .sampler = vk_ctx->nearest_sampler, + .imageView = vk_ctx->cyl_1_normal_texture_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0b = { - .buffer = state.vk_ctx.device_lighting_ubo.buffer, + .buffer = vk_ctx->device_lighting_ubo.buffer, .offset = 0, .range = sizeof(Pipeline0UBO), }; VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { - .sampler = state.vk_ctx.nearest_sampler, - .imageView = state.vk_ctx.IT1_view, + .sampler = vk_ctx->nearest_sampler, + .imageView = vk_ctx->IT1_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkWriteDescriptorSet writes_in_descriptor_sets[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, + .dstSet = vk_ctx->descriptor_set_for_pipeline_0a, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -2027,7 +2060,7 @@ int main() { }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, + .dstSet = vk_ctx->descriptor_set_for_pipeline_0a, .dstBinding = 1, .dstArrayElement = 0, .descriptorCount = 1, @@ -2036,7 +2069,7 @@ int main() { }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, + .dstSet = vk_ctx->descriptor_set_for_pipeline_0a, .dstBinding = 2, .dstArrayElement = 0, .descriptorCount = 1, @@ -2046,7 +2079,7 @@ int main() { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0b, + .dstSet = vk_ctx->descriptor_set_for_pipeline_0b, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -2056,7 +2089,7 @@ int main() { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_1, + .dstSet = vk_ctx->descriptor_set_for_pipeline_1, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -2064,90 +2097,91 @@ int main() { .pImageInfo = &image_info_for_descriptor_0_in_set_1, }, }; - vkUpdateDescriptorSets(state.vk_ctx.device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); + vkUpdateDescriptorSets(vk_ctx->device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); - state.vk_ctx.jane = Jane_r0_create(state.vk_ctx.device); + vk_ctx->jane = Jane_r0_create(vk_ctx->device); state.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); state.frame_count_since_key = 0; /* Will happen mid-frame */ - state.vk_ctx.dt_transfer_required = true; + vk_ctx->dt_transfer_required = true; while (wl_display_dispatch(state.wl_display) >= 0) { if (state.closed) break; } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); // The End - vkDestroyDescriptorPool(state.vk_ctx.device, state.vk_ctx.descriptor_pool, NULL); - vkDestroySampler(state.vk_ctx.device, state.vk_ctx.linear_sampler, NULL); - vkDestroySampler(state.vk_ctx.device, state.vk_ctx.nearest_sampler, NULL); + vkDestroyDescriptorPool(vk_ctx->device, vk_ctx->descriptor_pool, NULL); + vkDestroySampler(vk_ctx->device, vk_ctx->linear_sampler, NULL); + vkDestroySampler(vk_ctx->device, vk_ctx->nearest_sampler, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_normal_texture_view, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_diffuse_texture_view, NULL); - vkDestroyFramebuffer(state.vk_ctx.device, state.vk_ctx.IT1_framebuffer, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.IT1_view, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.zbuffer_view, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->cyl_1_normal_texture_view, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->cyl_1_diffuse_texture_view, NULL); + vkDestroyFramebuffer(vk_ctx->device, vk_ctx->IT1_framebuffer, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->IT1_view, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->zbuffer_view, NULL); - Scene_drop(state.vk_ctx.scene); + Scene_drop(vk_ctx->scene); - vkDestroyCommandPool(state.vk_ctx.device, state.vk_ctx.command_pool, NULL); + vkDestroyCommandPool(vk_ctx->device, vk_ctx->command_pool, NULL); - vkUnmapMemory(state.vk_ctx.device, state.vk_ctx.host_mem); - vkFreeMemory(state.vk_ctx.device, state.vk_ctx.host_mem, NULL); - vkFreeMemory(state.vk_ctx.device, state.vk_ctx.device_mem, NULL); + vkUnmapMemory(vk_ctx->device, vk_ctx->host_mem); + vkFreeMemory(vk_ctx->device, vk_ctx->host_mem, NULL); + vkFreeMemory(vk_ctx->device, vk_ctx->device_mem, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_diffuse_texture.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_normal_texture.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_IT1_image.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_zbuffer_image.image, NULL); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_lighting_ubo.buffer, NULL); + // todo: delete all the crap + vkDestroyImage(vk_ctx->device, vk_ctx->device_cyl_1_diffuse_texture.image, NULL); + vkDestroyImage(vk_ctx->device, vk_ctx->device_cyl_1_normal_texture.image, NULL); + vkDestroyImage(vk_ctx->device, vk_ctx->device_IT1_image.image, NULL); + vkDestroyImage(vk_ctx->device, vk_ctx->device_zbuffer_image.image, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->device_lighting_ubo.buffer, NULL); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_instance_attrs_for_models.buffer, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->device_instance_attrs_for_models.buffer, NULL); - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i)->buffer, + for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_generic_meshes.len; i++) + vkDestroyBuffer(vk_ctx->device, + VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_ebo_buffers_for_generic_meshes, i)->buffer, NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_generic_meshes); + VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_ebo_buffers_for_generic_meshes); - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i)->buffer, + for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_generic_meshes.len; i++) + vkDestroyBuffer(vk_ctx->device, + VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_vbo_buffers_for_generic_meshes, i)->buffer, NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_generic_meshes); + VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_vbo_buffers_for_generic_meshes); - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i)->buffer, + for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_shiny_meshes.len; i++) + vkDestroyBuffer(vk_ctx->device, + VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_ebo_buffers_for_shiny_meshes, i)->buffer, NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_shiny_meshes); + VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_ebo_buffers_for_shiny_meshes); - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i)->buffer, + for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_shiny_meshes.len; i++) + vkDestroyBuffer(vk_ctx->device, + VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_vbo_buffers_for_shiny_meshes, i)->buffer, NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_shiny_meshes); + VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_vbo_buffers_for_shiny_meshes); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.host_mem_buffer.buffer, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->host_mem_buffer.buffer, NULL); - TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_normal_tex); - TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_diffuse_tex); - SceneTemplate_drop(state.vk_ctx.scene_template); + TextureDataR8G8B8A8_drop(vk_ctx->cyl_1_normal_tex); + TextureDataR8G8B8A8_drop(vk_ctx->cyl_1_diffuse_tex); + SceneTemplate_drop(vk_ctx->scene_template); - MargaretSwapchainBundle_drop_with_device(state.vk_ctx.device, state.vk_ctx.swfb); - Jane_r0_destroy(state.vk_ctx.device, state.vk_ctx.jane); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_1); - vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_1, NULL); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0b); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0a); - vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_0, NULL); - vkDestroyDevice(state.vk_ctx.device, NULL); - vkDestroySurfaceKHR(instance, state.vk_ctx.surface, NULL); - MargaretInstanceAndItsDebug_drop(state.vk_ctx.instance_and_debug); + MargaretSwapchainBundle_drop_with_device(vk_ctx->device, vk_ctx->swfb); + Jane_r0_destroy(vk_ctx->device, vk_ctx->jane); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_1); + vkDestroyRenderPass(vk_ctx->device, vk_ctx->render_pass_1, NULL); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_0b); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_0a); + vkDestroyRenderPass(vk_ctx->device, vk_ctx->render_pass_0, NULL); + vkDestroyDevice(vk_ctx->device, NULL); + vkDestroySurfaceKHR(instance, vk_ctx->surface, NULL); + MargaretInstanceAndItsDebug_drop(vk_ctx->instance_and_debug); if (state.wl_callback) wl_callback_destroy(state.wl_callback); diff --git a/src/l2/tests/r0/r0_assets.h b/src/l2/tests/r0/r0_assets.h index 1460d7a..2e177ef 100644 --- a/src/l2/tests/r0/r0_assets.h +++ b/src/l2/tests/r0/r0_assets.h @@ -8,6 +8,7 @@ #include "../../../../gen/l1/VecAndSpan_vec.h" #include "../../../../gen/l1/pixel_masses.h" #include "../../marie/rasterization.h" +#include "../../marie/texture_processing.h" typedef struct { vec3 pos; @@ -32,10 +33,16 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) { typedef struct { GenericMeshTopology topology; U32 max_instance_count; + VecU8 diffuse_texture_path; + VecU8 normal_texture_path; + VecU8 specular_texture_path; } GenericMeshInSceneTemplate; void GenericMeshInSceneTemplate_drop(GenericMeshInSceneTemplate self) { GenericMeshTopology_drop(self.topology); + VecU8_drop(self.diffuse_texture_path); + VecU8_drop(self.normal_texture_path); + VecU8_drop(self.specular_texture_path); } GenericMeshInSceneTemplate GenericMeshInSceneTemplate_clone(const GenericMeshInSceneTemplate* self) { @@ -454,6 +461,41 @@ vec2 Bublazhuzhka_get_derivative(const Bublazhuzhka* self, vec2 v) { return sum; } +cvec3 Bublazhuzhka_get_color(const Bublazhuzhka* self, vec2 v) { + float flats = 0; + for (size_t i = 0; i < self->wimbzles.len; i++) { + Wimbzle rect = *VecWimbzle_at(&self->wimbzles, i); + vec2 B = {rect.tr.x + rect.brd, rect.tr.y + rect.brd}; + vec2 C = {rect.bl.x - rect.brd, rect.bl.y - rect.brd}; + vec2 A = {C.x, B.y}; + vec2 D = {B.x, C.y}; + vec2 F = rect.tr; + vec2 G = rect.bl; + vec2 E = {G.x, F.y}; + vec2 H = {F.x, G.y}; + float slp = rect.height / rect.brd; + if (A.x < v.x && v.x < E.x && marie_surface(E, A, v) > 0 && marie_surface(C, G, v) > 0) { + return (cvec3){100, 30, 40}; + } else if (F.x < v.x && v.x < B.x && marie_surface(B, F, v) > 0 && marie_surface(H, D, v) > 0) { + return (cvec3){70, 60, 45}; + } else if (C.y < v.y && v.y < G.y && marie_surface(G, C, v) > 0 && marie_surface(D, H, v) > 0) { + return (cvec3){10, 100, 70}; + } else if (F.y < v.y && v.y < B.y && marie_surface(A, E, v) > 0 && marie_surface(F, B, v) > 0) { + return (cvec3){25, 50, 110}; + } else if (E.x <= v.x && v.x <= F.x && G.y <= v.y && v.y <= F.y) { + flats += rect.height; + } + } + for (size_t i = 0; i < self->nibzles.len; i++) { + Nibzle sphere = *VecNibzle_at(&self->nibzles, i); + float sq_h = pow2f(sphere.rad) - pow2f(v.x - sphere.center.x) - pow2f(v.y - sphere.center.y); + if (sq_h >= 0) + return (cvec3){120, 120, 120}; + } + U8 p = (U8)roundf((1.f - expf(flats)) * 60); + return (cvec3){121 - p * 2, 30 + p, 65 - p}; +} + cvec3 compress_normal_vec_into_norm_texel(vec3 n) { return (cvec3){(U32)roundf(255 * (n.x + 1) / 2), (U32)roundf(255 * (n.y + 1) / 2), (U32)roundf(255 * (n.z + 1) / 2)}; } @@ -575,10 +617,36 @@ void draw_polygon_on_normal_texture_flat_param_surf(TextureDataR8G8B8A8* tex, ve } +typedef struct { + TextureDataR8G8B8A8* self; + const Bublazhuzhka* bublazhuzhka; +} TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest; + +void TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_h_draw_guest(void* ug, S32 x, S32 y, vec4 attr) { + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest *g = ug; + cvec3 clr = Bublazhuzhka_get_color(g->bublazhuzhka, (vec2){attr.x, attr.y}); + if (TextureDataR8G8B8A8_is_inside(g->self, x, y)) + *TextureDataR8G8B8A8_mat(g->self, x, y) = (cvec4){clr.x, clr.y, clr.z, 255}; +} + +/* Not natural coordinates. Needs translation operator to convert + * from parameter space*/ +void TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka( + TextureDataR8G8B8A8* self, const Bublazhuzhka* bublazhuzhka, MarieTriangle param_triangle, mat3x2 trop + ) { + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest aboba = + {self, bublazhuzhka}; + MarieTriangleAttr natural = MarieTriangle_goto_nat_cords_pres_par(param_triangle, trop); + // todo: continue from here + marie_rasterize_triangle_with_attr( + natural.v0, natural.v1, natural.v2, + (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_h_draw_guest, .guest = &aboba}); +} -TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { + +TextureDataR8G8B8A8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { assert(k >= 1); const float a = M_PI_2f / (float)k; const float l = 2 * r * sinf(M_PI_4f / (float)k); @@ -589,36 +657,42 @@ TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, const vec2 v1tex = {r + w, r}; const vec2 v2tex = {r, 2 * r}; const vec2 v3tex = {r + w, 2 * r}; - TextureDataR8 res = TextureDataR8_new(width_pix, height_pix); - Vecvec2 P = Vecvec2_new_reserved(6 + k * 4); - Vecvec2_append(&P, v0tex); - Vecvec2_append(&P, (vec2){r, 0}); // 4 - Vecvec2_append(&P, (vec2){r + w, 0}); // 5 - Vecvec2_append(&P, v1tex); - for (size_t i = k; i > 0; i--) { - Vecvec2_append(&P, (vec2){r + w + r * sinf(a * (float)i), r + r * cosf(a * (float)i)}); - } - Vecvec2_append(&P, v3tex); + const vec2 v4tex = {r, 0}; + const vec2 v5tex = {r + w, 0}; + TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width_pix, height_pix); + mat3x2 cord_resol_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y}; + + vec3 color_1 = (vec3){0.3f, 0.5f, 0.1f}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v4tex, v5tex}, cord_resol_trop); + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v5tex, v1tex}, cord_resol_trop); + vec3 color_2 = (vec3){0.1f, 0.2f, 0.8f}; + vec3 color_3 = (vec3){0.2f, 0.3f, 0.9f}; + vec3 color_4 = (vec3){0.1f, 0.5f, 0.7f}; + vec3 color_5 = (vec3){0.7f, 0.05f, 0.2f}; for (size_t i = 1; i <= k; i++) { - Vecvec2_append(&P, (vec2){r + w, 2 * r + (float)i * l}); + vec2 A = (vec2){r - r * sinf(a * (float)i), r + r * cosf(a * (float)i)}; + vec2 B = (vec2){r - r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_2, (MarieTriangle){v0tex, B, A}, cord_resol_trop); } - for (size_t i = k; i > 0; i--) { - Vecvec2_append(&P, (vec2){r, 2 * r + (float)i * l}); - } - Vecvec2_append(&P, v2tex); for (size_t i = 1; i <= k; i++) { - Vecvec2_append(&P, (vec2){r - r * sinf(a * (float)i), r + r * cosf(a * (float)i)}); + vec2 A = (vec2){r + w + r * sinf(a * (float)i), r + r * cosf(a * (float)i)}; + vec2 B = (vec2){r + w + r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_3, (MarieTriangle){v1tex, A, B}, cord_resol_trop); } - for (size_t i = 0; i < P.len; i++) { - *Vecvec2_mat(&P, i) = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); + for (size_t i = 1; i <= k; i++) { + vec2 A = (vec2){r, 2 * r + (float)(i) * l}; + vec2 B = (vec2){r, 2 * r + (float)(i-1) * l}; + vec2 C = (vec2){r + w, 2 * r + (float)(i-1) * l}; + vec2 D = (vec2){r + w, 2 * r + (float)(i) * l}; + vec3 c = i % 2 ? color_4 : color_5; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, c, (MarieTriangle){A, B, C}, cord_resol_trop); + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, c, (MarieTriangle){A, C, D}, cord_resol_trop); } - TextureDataR8_draw_perimeter_maxing(&res, Vecvec2_to_span(&P)); - Vecvec2_drop(P); Bublazhuzhka crap_on_back_side = fill_rectangle_with_crap(w, r); - // todo: draw bublazhuzhka pixel-by-pixel myself - Bublazhuzhka_TextureDataR8_draw_maxing(&crap_on_back_side, &res, - (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)}); + mat3x2 back_side_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)}; + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {0, 0}, {w, 0}}, back_side_trop); + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {w, 0}, {w, r}}, back_side_trop); Bublazhuzhka_drop(crap_on_back_side); return res; } @@ -792,4 +866,13 @@ ShinyMeshTopology generate_shiny_rhombicuboctahedron(float r) { return res; } +GenericMeshInSceneTemplate GenericMeshInSceneTemplate_for_log(U32 w, U32 r, U32 k, U32 max_instance_count) { + return (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder((float)w, (float)r, k), + .max_instance_count = max_instance_count, + .diffuse_texture_path = VecU8_format("log_%u_%u_%u_diffuse.png", w, r, k), + .normal_texture_path = VecU8_format("log_%u_%u_%u_NORMAL.png", w, r, k), + .specular_texture_path = VecU8_format("log_%u_%u_%u_specular.png", w, r, k), + }; +} + #endif diff --git a/src/l2/tests/r0/r0_scene.h b/src/l2/tests/r0/r0_scene.h index 4eca086..455dead 100644 --- a/src/l2/tests/r0/r0_scene.h +++ b/src/l2/tests/r0/r0_scene.h @@ -12,6 +12,9 @@ typedef struct { VkBuffer instance_attr_buf; VkDeviceSize instance_attr_buf_offset; U32 limit_max_instance_count; + VkImage diffuse_texture; + VkImage normal_texture; + VkImage specular_texture; } ModelOnSceneMem; /* Contains both data for model instances attributes and buffer (+offset) where it is stored */ diff --git a/src/l2/tests/r0/r0_tex_init_prep.c b/src/l2/tests/r0/r0_tex_init_prep.c index d96de16..0e1137d 100644 --- a/src/l2/tests/r0/r0_tex_init_prep.c +++ b/src/l2/tests/r0/r0_tex_init_prep.c @@ -3,28 +3,31 @@ #include "../../margaret/png_pixel_masses.h" #include "../../marie/texture_processing.h" -void model_1_template() { - TextureDataR8 tex = generate_tex_template_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 tex_1_big = TextureDataR8G8B8A8_new(tex.width, TextureDataR8_get_height(&tex)); - for (size_t i = 0; i < tex.pixels.len; i++) { - U8 g = *VecU8_at(&tex.pixels, i); - *Veccvec4_mat(&tex_1_big.pixels, i) = (cvec4){g, g, g, 255}; +void for_log(U32 w, U32 r, U32 k) { + { + TextureDataR8G8B8A8 tex = generate_tex_template_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k); + TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); + VecU8 name = VecU8_format("textures/log_%u_%u_%u_TEMPLATE.png", w, r, k); + TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name)); + VecU8_drop(name); + TextureDataR8G8B8A8_drop(fixed_tex); + TextureDataR8G8B8A8_drop(tex); + } + { + TextureDataR8G8B8A8 tex = generate_normal_tex_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k); + TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); + VecU8 name = VecU8_format("textures/log_%u_%u_%u_NORMAL.png", w, r, k); + TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name)); + VecU8_drop(name); + TextureDataR8G8B8A8_drop(fixed_tex); + TextureDataR8G8B8A8_drop(tex); } - TextureDataR8G8B8A8_write_to_png_nofail(&tex_1_big, cstr("textures/log_10_2_6_TEMPLATE.png")); - TextureDataR8G8B8A8_drop(tex_1_big); - TextureDataR8_drop(tex); -} - -void model_1_normal() { - TextureDataR8G8B8A8 tex = generate_normal_tex_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); - TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, cstr("textures/log_10_2_6_NORMAL.png")); - TextureDataR8G8B8A8_drop(fixed_tex); - TextureDataR8G8B8A8_drop(tex); } int main() { - model_1_template(); - model_1_normal(); + for_log(10, 2, 6); + for_log(5, 5, 10); + for_log(1, 10, 4); + for_log(2, 1, 6); return 0; } diff --git a/src/l2/tests/tv0/tv0.c b/src/l2/tests/tv0/tv0.c new file mode 100644 index 0000000..e69de29