diff --git a/CMakeLists.txt b/CMakeLists.txt index fb83dc4..667a9fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set(CMAKE_C_FLAGS "-Wall -Wextra -Werror=implicit-function-declaration -Werror=r add_compile_definitions(_POSIX_C_SOURCE=200112L) add_compile_definitions(_GNU_SOURCE) +add_compile_options(-fno-trapping-math) add_executable(main src/l1/main.c) diff --git a/src/l1/core/int_primitives.h b/src/l1/core/int_primitives.h index c0cb9bd..6d72836 100644 --- a/src/l1/core/int_primitives.h +++ b/src/l1/core/int_primitives.h @@ -56,6 +56,7 @@ T MAX_##T (T a, T b){ return a < b ? b : a; } int_minmax_function_Definition(U8) int_minmax_function_Definition(U32) +int_minmax_function_Definition(S32) int_minmax_function_Definition(U64) int_minmax_function_Definition(float) int_minmax_function_Definition(double) diff --git a/src/l1/gen/geom_and_textures.h b/src/l1/gen/geom_and_textures.h index 5666c6f..18a7082 100644 --- a/src/l1/gen/geom_and_textures.h +++ b/src/l1/gen/geom_and_textures.h @@ -168,6 +168,52 @@ NODISCARD VecU8 generate_xvecy_method_div_by_scal(ConstSpanU8 xvec, ConstSpanU8 return res; } +NODISCARD VecU8 generate_xvecy_method_mul_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int n) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("_mul_")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("(")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("){ ")); + for (int i = 0; i < n; i++) { + if (i) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, i); + VecU8_append_span(&res, cstr(" * B.")); + string_append_vec_field_name(&res, i); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvecy_method_and_one(ConstSpanU8 xvec, int n) { + assert(2 <= n && n < 4); + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, n + 1); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("_and_one(")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, n + 1); + VecU8_append_span(&res, cstr("){ ")); + for (int i = 0; i < n; i++) { + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, i); + VecU8_append_span(&res, cstr(", ")); + } + VecU8_append_span(&res, cstr("1 };\n}\n\n")); + return res; +} + void string_append_xmatnm(VecU8* str, ConstSpanU8 xmat, int cols, int rows) { VecU8_append_span(str, xmat); VecU8_append(str, '0' + cols); @@ -512,16 +558,26 @@ VecU8 generate_xmatnm_method_transpose(ConstSpanU8 xmat, ConstSpanU8 xvec, Const return res; } -NODISCARD VecU8 generate_xvec234_structs_and_methods(ConstSpanU8 xvec, ConstSpanU8 member) { +NODISCARD VecU8 generate_xvec234_structs_and_important_methods(ConstSpanU8 xvec, ConstSpanU8 member) { VecU8 res = VecU8_new(); for (int cc = 2; cc <= 4; cc++) { VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, cc)); VecU8_append_vec(&res, generate_xvecy_method_add_xvecy(xvec, member, cc)); VecU8_append_vec(&res, generate_xvecy_method_minus_xvecy(xvec, member, cc)); VecU8_append_vec(&res, generate_xvecy_method_minus(xvec, member, cc)); + } + return res; +} + +NODISCARD VecU8 generate_xvec234_structs_and_methods(ConstSpanU8 xvec, ConstSpanU8 member) { + VecU8 res = generate_xvec234_structs_and_important_methods(xvec, member); + for (int cc = 2; cc <= 4; cc++) { VecU8_append_vec(&res, generate_xvecy_method_mul_scal(xvec, member, cc)); VecU8_append_vec(&res, generate_xvecy_method_div_by_scal(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_mul_xvecy(xvec, member, cc)); } + for (int n = 2; n <= 3; n++) + VecU8_append_vec(&res, generate_xvecy_method_and_one(xvec, n)); return res; } @@ -564,8 +620,8 @@ NODISCARD VecU8 generate_xmat234x234_structs_and_methods(ConstSpanU8 xmat, Const void generate_geom_header() { VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_GEOM")); VecU8_append_span(&res, cstr("#include \"../src/l1/core/int_primitives.h\"\n\n")); - VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("cvec"), cstr("U8"))); - VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("ivec"), cstr("S32"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_important_methods(cstr("cvec"), cstr("U8"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_important_methods(cstr("ivec"), cstr("S32"))); VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("vec"), cstr("float"))); VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("dvec"), cstr("double"))); @@ -753,6 +809,14 @@ VecU8 generate_texture_data_struct_and_necc_methods(ConstSpanU8 texdatat, ConstS SPACE8 "fprintf(stderr, \"Tried loading bitmap texture from file, but encountered decoding error: \");\n" SPACE8 "ConstSpanU8_fprint(res.err, stderr);\n" SPACE8 "abortf(\"\\n\");\n" SPACE4 "}\n" SPACE4 "VecU8_drop(data);\n" SPACE4 "return res.ok;\n}\n\n")); + /* Method _is_inside() */ + VecU8_append_span(&res, cstr("bool ")); + VecU8_append_span(&res, texdatat); + VecU8_append_span(&res, cstr("_is_inside(const ")); + VecU8_append_span(&res, texdatat); + VecU8_append_span(&res, cstr("* self, S32 x, S32 y) {\n" + SPACE4 "return x >= 0 && y >= 0 && x < self->width && self->width * y + x < self->pixels.len;\n" + "}\n\n")); return res; } diff --git a/src/l2/core/stringop.h b/src/l2/core/stringop.h index 6f42ca9..b7045dc 100644 --- a/src/l2/core/stringop.h +++ b/src/l2/core/stringop.h @@ -1,5 +1,5 @@ -#ifndef PROTOTYPE1_SRC_L2_MARGARET_STRINGOP_H -#define PROTOTYPE1_SRC_L2_MARGARET_STRINGOP_H +#ifndef PROTOTYPE1_SRC_L2_CORE_STRINGOP_H +#define PROTOTYPE1_SRC_L2_CORE_STRINGOP_H #include "../../l1/core/VecSpan_int_primitives.h" diff --git a/src/l2/margaret/graphics_geom.h b/src/l2/marie/graphics_geom.h similarity index 72% rename from src/l2/margaret/graphics_geom.h rename to src/l2/marie/graphics_geom.h index d4481c9..36fcd00 100644 --- a/src/l2/margaret/graphics_geom.h +++ b/src/l2/marie/graphics_geom.h @@ -1,10 +1,10 @@ -#ifndef PROTOTYPE1_SRC_L2_MARGARET_GRAPHICS_GEOM_H -#define PROTOTYPE1_SRC_L2_MARGARET_GRAPHICS_GEOM_H +#ifndef PROTOTYPE1_SRC_L2_MARIE_GRAPHICS_GEOM_H +#define PROTOTYPE1_SRC_L2_MARIE_GRAPHICS_GEOM_H #include "../../../gen/geom.h" #include "math.h" -mat4 margaret_translation_mat4(vec3 vec) { +mat4 marie_translation_mat4(vec3 vec) { return mat4_new( 1, 0, 0, vec.x, 0, 1, 0, vec.y, @@ -13,7 +13,7 @@ mat4 margaret_translation_mat4(vec3 vec) { ); } -mat3 margaret_3d_rot_mat3(vec3 r, float a) { +mat3 marie_3d_rot_mat3(vec3 r, float a) { float cosa = cosf(a); float sina = sinf(a); return mat3_new( @@ -23,7 +23,7 @@ mat3 margaret_3d_rot_mat3(vec3 r, float a) { ); } -mat4 margaret_mat3_to_mat4(mat3 A) { +mat4 marie_mat3_to_mat4(mat3 A) { return mat4_new( A.x.x, A.y.x, A.z.x, 0, A.x.y, A.y.y, A.z.y, 0, @@ -31,7 +31,7 @@ mat4 margaret_mat3_to_mat4(mat3 A) { 0, 0, 0, 1); } -mat4 margaret_mat3_to_mat4_transposed(mat3 A) { +mat4 marie_mat3_to_mat4_transposed(mat3 A) { return mat4_new( A.x.x, A.x.y, A.x.z, 0, A.y.x, A.y.y, A.y.z, 0, @@ -39,12 +39,12 @@ mat4 margaret_mat3_to_mat4_transposed(mat3 A) { 0, 0, 0, 1); } -mat4 margaret_3d_rot_mat4(vec3 r, double a) { - return margaret_mat3_to_mat4(margaret_3d_rot_mat3(r, a)); +mat4 marie_3d_rot_mat4(vec3 r, double a) { + return marie_mat3_to_mat4(marie_3d_rot_mat3(r, a)); } -mat4 margaret_perspective_projection_mat4(float right, float top, float near, float far) { +mat4 marie_perspective_projection_mat4(float right, float top, float near, float far) { return mat4_new( near/right, 0, 0, 0, 0, -near/top, 0, 0, @@ -52,15 +52,15 @@ mat4 margaret_perspective_projection_mat4(float right, float top, float near, fl 0, 0, -1, 0 ); } -mat4 margaret_perspective_projection_fov_mat4(float win_width, float win_height, float fov, +mat4 marie_perspective_projection_fov_mat4(float win_width, float win_height, float fov, float spat_frustum_near, float spat_frustum_far) { float right = tanf(fov / 2) * spat_frustum_near; float top = win_height * right / win_width; - return margaret_perspective_projection_mat4(right, top, spat_frustum_near, spat_frustum_far); + return marie_perspective_projection_mat4(right, top, spat_frustum_near, spat_frustum_far); } -mat3 margaret_simple_camera_rot_m_basis_in_cols(float yaw, float pitch, float roll) { +mat3 marie_simple_camera_rot_m_basis_in_cols(float yaw, float pitch, float roll) { float cos_ya = cosf(yaw); float sin_ya = sinf(yaw); float cos_pi = cosf(pitch); diff --git a/src/l2/marie/rasterization.h b/src/l2/marie/rasterization.h new file mode 100644 index 0000000..28cb054 --- /dev/null +++ b/src/l2/marie/rasterization.h @@ -0,0 +1,181 @@ +#ifndef SPLITTER_DRAFT_SRC_L2_MARIE_RASTERIZATION_H +#define SPLITTER_DRAFT_SRC_L2_MARIE_RASTERIZATION_H + +#include "../../../gen/geom.h" +#include "../../../gen/pixel_masses.h" +#include "math.h" + +#include +#include + +/* float size check and IEEE‑754 binary32 characteristic checks */ +_Static_assert(sizeof(float) == 4, + "This code assumes 32‑bit floats"); +#if defined(__STDC_IEC_559__) /* implementation claims IEC 60559 */ +_Static_assert(__STDC_IEC_559__, "Implementation is not IEC 60559"); +#else +/* Fall back to value‑based checks: radix 2, 24‑bit mantissa, exponent ranges. + These values are unique to binary32 among the formats in actual use. */ +_Static_assert(FLT_RADIX == 2, "Non‑binary radix"); +_Static_assert(FLT_MANT_DIG == 24, "Float is not binary32"); +_Static_assert(FLT_MAX_EXP == 128, "Float is not binary32"); +_Static_assert(FLT_MIN_EXP == -125, "Float is not binary32"); +#endif + +// todo: move line rasterization here (from r0 test) + +uint32_t marie_pun_float2u32(float f) { + uint32_t u; + memcpy(&u, &f, sizeof u); + return u; +} + +bool marie_same_dir3(float A0, float A1, float A2, float B) { + uint32_t bb = marie_pun_float2u32(B); + uint32_t diff = (marie_pun_float2u32(A0) ^ bb) | + (marie_pun_float2u32(A1) ^ bb) | + (marie_pun_float2u32(A2) ^ bb); + return A0 == 0 || A1 == 0 || A2 == 0 || (diff & 0x80000000u) == 0; +} + +typedef vec4 MarieVertAttr; + +typedef struct { + /* guest, x, y, attribute (custom) */ + void (*fn)(void*, S32, S32, MarieVertAttr); + void* guest; +} FnMarieRasterizerCallback; + +typedef struct { + vec2 pos; + MarieVertAttr attr; +} MariePlaneVertAttr; + +float marie_surface(vec2 vi, vec2 vj, vec2 u) { + return u.x * (vi.y - vj.y) + u.y * (vj.x - vi.x) + (vi.x * vj.y - vj.x * vi.y); +} + +typedef struct { + float c1; + float c0; +} MarieLinearFun; + + +/* f(y) = (y + 0.5 - a.y) / (b.y - a.y) * (b.x - a.x) + a.x - 0.5 */ +MarieLinearFun marie_gen_scanline_borderline(vec2 a, vec2 b) { + return (MarieLinearFun){.c1 = (b.x - a.x) / (b.y - a.y), + .c0 = (0.5 - a.y) * (b.x - a.x) / (b.y - a.y) + a.x - 0.5 }; +} + +/* Utility function, that is used by rasterization function. + * Don't use in your code*/ +void marie_rasterize_line_in_triangle_with_attr_sorted( + vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 L, S32 R, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, + float S, S32 my, FnMarieRasterizerCallback cb + ) { + float E01 = marie_surface(v0pos, v1pos, (vec2){L + 0.5, my + 0.5}); + float E12 = marie_surface(v1pos, v2pos, (vec2){L + 0.5, my + 0.5}); + float E20 = marie_surface(v2pos, v0pos, (vec2){L + 0.5, my + 0.5}); + for (S32 x = L; x <= R; x++) { + if (marie_same_dir3(E01, E12, E20, S)) { + cb.fn(cb.guest, x, my, vec4_add_vec4(vec4_mul_scal(P0, E12), + vec4_add_vec4(vec4_mul_scal(P1, E20), vec4_mul_scal(P2, E01)))); + } + E01 += (v0pos.y - v1pos.y); + E12 += (v1pos.y - v2pos.y); + E20 += (v2pos.y - v0pos.y); + } +} + +/* Utility function, that is used by rasterization function. + * Don't use in your code*/ +void marie_scan_rast_line_in_triangle_with_attr_sorted( + vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 below, S32 above, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, + MarieLinearFun left_border, MarieLinearFun right_border, FnMarieRasterizerCallback cb + ) { + for (S32 my = below + 1; my < above; my++) { + S32 left = (S32)ceilf(left_border.c1 * (float)my + left_border.c0); + S32 right = (S32)floorf(right_border.c1 * (float)my + right_border.c0); + MarieVertAttr Q0 = vec4_mul_scal(P0, marie_surface(v1pos, v2pos, (vec2){left + 0.5, (float)my + 0.5})); + MarieVertAttr Q1 = vec4_mul_scal(P1, marie_surface(v2pos, v0pos, (vec2){left + 0.5, (float)my + 0.5})); + MarieVertAttr Q2 = vec4_mul_scal(P2, marie_surface(v0pos, v1pos, (vec2){left + 0.5, (float)my + 0.5})); + MarieVertAttr dq0 = vec4_mul_scal(P0, v1pos.y - v2pos.y); + MarieVertAttr dq1 = vec4_mul_scal(P1, v2pos.y - v0pos.y); + MarieVertAttr dq2 = vec4_mul_scal(P2, v0pos.y - v1pos.y); + for (S32 x = left; x <= right; x++) { + cb.fn(cb.guest, x, my, vec4_add_vec4(Q0, vec4_add_vec4(Q1, Q2))); + Q0 = vec4_add_vec4(Q0, dq0); + Q1 = vec4_add_vec4(Q1, dq1); + Q2 = vec4_add_vec4(Q2, dq2); + } + } +} + +void marie_rasterize_triangle_with_attr_sorted( + MariePlaneVertAttr v0, MariePlaneVertAttr v1, MariePlaneVertAttr v2, FnMarieRasterizerCallback cb + ) { + float S = marie_surface(v0.pos, v1.pos, v2.pos); + S32 sx0 = (S32)roundf(v0.pos.x - 0.5); + S32 sy0 = (S32)roundf(v0.pos.y - 0.5); + S32 sx1 = (S32)roundf(v1.pos.x - 0.5); + S32 sy1 = (S32)roundf(v1.pos.y - 0.5); + S32 sx2 = (S32)roundf(v2.pos.x - 0.5); + S32 sy2 = (S32)roundf(v2.pos.y - 0.5); + + S32 L = MIN_S32(sx0, MIN_S32(sx1, sx2)); + S32 R = MAX_S32(sx0, MAX_S32(sx1, sx2)); + + MarieVertAttr P0 = vec4_div_by_scal(v0.attr, S); + MarieVertAttr P1 = vec4_div_by_scal(v1.attr, S); + MarieVertAttr P2 = vec4_div_by_scal(v2.attr, S); + + /* I compile with -fno-trapping-math, so I hope nothing bad would happen */ + MarieLinearFun line_01 = marie_gen_scanline_borderline(v0.pos, v1.pos); + 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); + 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); + } + 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); + } + 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); + } + 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); + } +} +void marie_rasterize_triangle_with_attr( + MariePlaneVertAttr a, MariePlaneVertAttr b, MariePlaneVertAttr c, FnMarieRasterizerCallback cb + ) { + if (a.pos.y < b.pos.y) { + if (b.pos.y < c.pos.y) { + marie_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); + } else { + marie_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); + } else { + if (b.pos.y < c.pos.y) { + marie_rasterize_triangle_with_attr_sorted(b, c, a, cb); + } else { + marie_rasterize_triangle_with_attr_sorted(c, b, a, cb); + } + } + } +} + +#endif diff --git a/src/l2/tests/r0.c b/src/l2/tests/r0.c index dca27fc..87c052e 100644 --- a/src/l2/tests/r0.c +++ b/src/l2/tests/r0.c @@ -808,10 +808,10 @@ int main() { Scene scene = Scene_new(); VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = { .vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len - }, .model_t = margaret_translation_mat4((vec3){1, -1, 5}) }); + }, .model_t = marie_translation_mat4((vec3){1, -1, 5}) }); VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = { .vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len - }, .model_t = margaret_translation_mat4((vec3){6, -3, 7}) }); + }, .model_t = marie_translation_mat4((vec3){6, -3, 7}) }); // Sampler is global for a lot of my future textures VkSampler my_texture_sampler = margaret_create_sampler(physical_device, device); @@ -942,10 +942,10 @@ int main() { float ae = margaret_ns_time_sec_diff(start, frame_A0); scene.anim_time = ae; scene.color = (VkClearColorValue){{0.5f, fabsf(sinf(ae)), .3f, 1.0f}}; - mat4 projection_matrix = margaret_perspective_projection_fov_mat4((float)wep.width, (float)wep.height, + mat4 projection_matrix = marie_perspective_projection_fov_mat4((float)wep.width, (float)wep.height, my_cam_control_info.fov, 0.01f, 1000); - mat4 camera_rotation_matrix = margaret_mat3_to_mat4_transposed(my_cam_control_info.cam_basis); - mat4 camera_translation_matrix = margaret_translation_mat4(vec3_minus(my_cam_control_info.pos)); + mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(my_cam_control_info.cam_basis); + mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(my_cam_control_info.pos)); mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); { diff --git a/src/l2/tests/r0_assets.h b/src/l2/tests/r0_assets.h index 59524f2..6487494 100644 --- a/src/l2/tests/r0_assets.h +++ b/src/l2/tests/r0_assets.h @@ -1,7 +1,7 @@ #ifndef SPLITTER_DRAFT_SRC_L2_TESTS_R0_ASSETS_H #define SPLITTER_DRAFT_SRC_L2_TESTS_R0_ASSETS_H -#include "../margaret/graphics_geom.h" +#include "../marie/graphics_geom.h" #include "../../l1/core/util.h" #include "../../l1/core/VecSpan_int_primitives.h" #include "../../l1/system/fileio.h" @@ -77,14 +77,14 @@ VecT_trivmove_method_Definition(Pipeline0PointLight) VecT_primitive_zeroinit_method_Definition(Pipeline0PointLight) const size_t pipeline_0_ubo_point_light_max_count = 20; -const size_t pipeline_0_ubo_spotlight_max_count = 20; +const size_t pipeline_0_ubo_spotlight_max_count = 120; typedef struct { int spotlight_count; int point_light_count; char _padding_1[8]; - Pipeline0PointLight point_light_arr[20]; - Pipeline0Spotlight spotlight_arr[120]; + Pipeline0PointLight point_light_arr[pipeline_0_ubo_point_light_max_count]; + Pipeline0Spotlight spotlight_arr[pipeline_0_ubo_spotlight_max_count]; } Pipeline0UBO; size_t ModelTopology_get_space_needed_for_staging_buffer(const ModelTopology* self) { @@ -183,25 +183,25 @@ void TextureDataR8_draw_inner_line_maxing(TextureDataR8* self, } } -void TextureDataR8_draw_spot_maxing(TextureDataR8* self, float x, float y, float r_cut, float r_decay) { - S32 sx = (S32)roundf(x - .5f); - S32 sy = (S32)roundf(y - .5f); +void TextureDataR8_draw_spot_maxing(TextureDataR8* self, vec2 v, float r_cut, float r_decay) { + S32 sx = (S32)roundf(v.x - .5f); + S32 sy = (S32)roundf(v.y - .5f); S32 k = (S32)ceilf(r_cut); for (S32 i = sx-k; i <= sx+k; i++) { for (S32 j = sy-k; j <= sy+k; j++) { - float dx = 0.5f + (float)i - x; - float dy = 0.5f + (float)j - y; + float dx = 0.5f + (float)i - v.x; + float dy = 0.5f + (float)j - v.y; float dist = sqrtf(dx*dx + dy*dy); TextureDataR8_pixel_maxing(self, i, j, a_small_cute_gradient(r_cut, r_decay, dist)); } } } -void TextureDataR8G8B8A8_draw_one_segment_maxing_alpha(TextureDataR8* self, - float x1, float y1, float x2, float y2, float r_cut, float r_decay) { - TextureDataR8_draw_spot_maxing(self, x1, y1, r_cut, r_decay); - TextureDataR8_draw_spot_maxing(self, x2, y2, r_cut, r_decay); - TextureDataR8_draw_inner_line_maxing(self, x1, y1, x2, y2, r_cut, r_decay); +void TextureDataR8_draw_one_segment_maxing(TextureDataR8* self, + vec2 v1, vec2 v2, float r_cut, float r_decay) { + TextureDataR8_draw_spot_maxing(self, v1, r_cut, r_decay); + TextureDataR8_draw_spot_maxing(self, v2, r_cut, r_decay); + TextureDataR8_draw_inner_line_maxing(self, v1.x, v1.y, v2.x, v2.y, r_cut, r_decay); } TextureDataR8G8B8A8 generate_wood_texture() { @@ -287,6 +287,63 @@ ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) { return (ModelTopology){.vertices = vertices, .indexes = indexes}; } +typedef struct { + vec2 bl; + vec2 tr; + float height; + float brd; +} Wimbzle; + +#define Wimbzle_drop(x) {} +#define Wimbzle_clone(xp) (*(xp)) + +VecT_trivmove_struct_Definition(Wimbzle) +VecT_trivmove_method_Definition(Wimbzle) +VecT_primitive_zeroinit_method_Definition(Wimbzle) + +typedef struct { + vec2 center; + vec2 rad; + float hc; +} Nibzle; + +#define Nibzle_drop(x) {} +#define Nibzle_clone(xp) (*(xp)) + +VecT_trivmove_struct_Definition(Nibzle) +VecT_trivmove_method_Definition(Nibzle) +VecT_primitive_zeroinit_method_Definition(Nibzle) + +typedef struct { + VecWimbzle wibmzles; + VecNibzle nibzles; +} Bublazhuzhka; + +Bublazhuzhka Bublazhuzhka_new() { + return (Bublazhuzhka){.wibmzles = VecWimbzle_new(), .nibzles = VecNibzle_new()}; +} + +void Bublazhuzhka_drop(Bublazhuzhka self) { + VecWimbzle_drop(self.wibmzles); + VecNibzle_drop(self.nibzles); +} + +void Bublazhuzhka_TextureDataR8_draw_maxing(const Bublazhuzhka* self, TextureDataR8* canvas, vec2) { + for (size_t i = 0; i < self->wibmzles.len; i++) { + Wimbzle rect = *VecWimbzle_cat(&self->wibmzles, 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}; + + TextureDataR8_draw_one_segment_maxing(canvas, A, B, 1.5, 1); + } +} + #define vec2_drop(x) {} #define vec2_clone(x) (*(x)) @@ -295,17 +352,17 @@ VecT_trivmove_method_Definition(vec2) VecT_primitive_zeroinit_method_Definition(vec2) TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { - assert(k >= 1); assert(k >= 1); const float a = M_PI_2f / (float)k; const float l = 2 * r * sin(M_PI_4f / (float)k); - // We will multiply everything by s_resol at the end + size_t width_pix = (size_t)ceilf(s_resol * (2 * r + w)); + size_t height_pix = (size_t)ceilf(s_resol * (2 * r + k * l)); + vec2 cord_resol = {(float)width_pix / (2 * r + w), (float)height_pix / (2 * r + k * l)}; const vec2 v0tex = {r, r}; const vec2 v1tex = {r + w, r}; const vec2 v2tex = {r, 2 * r}; const vec2 v3tex = {r + w, 2 * r}; - TextureDataR8 res = TextureDataR8_new((size_t)ceilf((float)s_resol * (2 * r + w)), - (size_t)ceilf((float)s_resol * (2 * r + k * l))); + TextureDataR8 res = TextureDataR8_new(width_pix, height_pix); Vecvec2 P = Vecvec2_new(); // todo: reserve 6 + k * 4 Vecvec2_append(&P, v0tex); Vecvec2_append(&P, (vec2){r, 0}); // 4 @@ -330,15 +387,59 @@ TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float r_cut = 2; float r_decay = 1; for (size_t i = 0; i < S; i++) { - vec2 p = vec2_mul_scal(*Vecvec2_at(&P, i), s_resol); - TextureDataR8_draw_spot_maxing(&res, p.x, p.y, r_cut, r_decay); + vec2 p = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); + TextureDataR8_draw_spot_maxing(&res, p, r_cut, r_decay); } for (size_t i = 0; i < S; i++) { - vec2 pp = vec2_mul_scal(*Vecvec2_at(&P, i ? i - 1 : S - 1), s_resol); - vec2 p = vec2_mul_scal(*Vecvec2_at(&P, i), s_resol); + vec2 pp = vec2_mul_vec2(*Vecvec2_at(&P, i ? i - 1 : S - 1), cord_resol); + vec2 p = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); TextureDataR8_draw_inner_line_maxing(&res, pp.x, pp.y, p.x, p.y, r_cut, r_decay); } return res; } +TextureDataR8G8B8 generate_normal_tex_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 * sin(M_PI_4f / (float)k); + size_t width_pix = (size_t)ceilf(s_resol * (2 * r + w)); + size_t height_pix = (size_t)ceilf(s_resol * (2 * r + k * l)); + vec2 cord_resol = {(float)width_pix / (2 * r + w), (float)height_pix / (2 * r + k * l)}; + const vec2 v0tex = {r, r}; + const vec2 v1tex = {r + w, r}; + const vec2 v2tex = {r, 2 * r}; + const vec2 v3tex = {r + w, 2 * r}; + TextureDataR8G8B8 res = TextureDataR8G8B8_new(width_pix, height_pix); + // Vecvec2 P = Vecvec2_new(); // todo: reserve 6 + k * 4 + // for (size_t i = k; i > 0; i--) { + // Vecvec2_append(&P, (vec2){r + w + r * sinf(a * i), r + r * cos(a * i)}); + // } + // Vecvec2_append(&P, v3tex); + // for (size_t i = 1; i <= k; i++) { + // Vecvec2_append(&P, (vec2){r + w, 2 * r + i * l}); + // } + // for (size_t i = k; i > 0; i--) { + // Vecvec2_append(&P, (vec2){r, 2 * r + i * l}); + // } + // Vecvec2_append(&P, v2tex); + // for (size_t i = 1; i <= k; i++) { + // Vecvec2_append(&P, (vec2){r - r * sinf(a * i), r + r * cos(a * i)}); + // } + // size_t S = 6 + 4 * k; + // assert(P.len == S); + // float r_cut = 2; + // float r_decay = 1; + // for (size_t i = 0; i < S; i++) { + // vec2 p = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); + // TextureDataR8_draw_spot_maxing(&res, p.x, p.y, r_cut, r_decay); + // } + // for (size_t i = 0; i < S; i++) { + // vec2 pp = vec2_mul_vec2(*Vecvec2_at(&P, i ? i - 1 : S - 1), cord_resol); + // vec2 p = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); + // TextureDataR8_draw_inner_line_maxing(&res, pp.x, pp.y, p.x, p.y, r_cut, r_decay); + // } + return res; +} + + #endif diff --git a/src/l2/tests/r0_scene.h b/src/l2/tests/r0_scene.h index 511fc94..5a0651b 100644 --- a/src/l2/tests/r0_scene.h +++ b/src/l2/tests/r0_scene.h @@ -66,7 +66,7 @@ void CamControlInfo_up(CamControlInfo* self, float fl) { CamControlInfo CamControlInfo_new() { return (CamControlInfo){ - .fov = 1.5, .cam_basis = margaret_simple_camera_rot_m_basis_in_cols(0, 0, 0), .pos = {0, 0, 0}, + .fov = 1.5, .cam_basis = marie_simple_camera_rot_m_basis_in_cols(0, 0, 0), .pos = {0, 0, 0}, .speed = 2.7, .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PI * 0.49 }; } @@ -81,7 +81,7 @@ void CamControlInfo_update_direction(CamControlInfo* self, int win_width, int wi (float)(win_height / 2 - pointer_y) * self->sensitivity, -self->pitch_cap, self->pitch_cap ); - self->cam_basis = margaret_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0); + self->cam_basis = marie_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0); } typedef struct { diff --git a/src/l2/tests/r0_tex_init_prep.c b/src/l2/tests/r0_tex_init_prep.c index 0189340..5edfbf4 100644 --- a/src/l2/tests/r0_tex_init_prep.c +++ b/src/l2/tests/r0_tex_init_prep.c @@ -1,9 +1,34 @@ #include "r0_assets.h" -#include "../../l1/system/fileio.h" +#include "../marie/rasterization.h" + +void draw_cool_triangle_h_frag(void* ug, S32 x, S32 y, MarieVertAttr attr_col) { + TextureDataR8G8B8* tex = (TextureDataR8G8B8*)ug; + if (TextureDataR8G8B8_is_inside(tex, x, y)) { + *TextureDataR8G8B8_at(tex, x, y) = (cvec3){255, (S32)roundf(attr_col.x * 255), (S32)roundf(attr_col.y * 255)}; + } +} + +void draw_cool_triangle(TextureDataR8G8B8* tex, vec2 A, vec2 B, vec2 C) { + marie_rasterize_triangle_with_attr((MariePlaneVertAttr){.pos = A, .attr = {A.x / 1000, A.y / 1000, 0, 1}}, + (MariePlaneVertAttr){.pos = B, .attr = {B.x / 1000, B.y / 1000, 0, 1}}, + (MariePlaneVertAttr){.pos = C, .attr = {C.x / 1000, C.y / 1000, 0, 1}}, + (FnMarieRasterizerCallback){.fn = draw_cool_triangle_h_frag, .guest = (void*)tex}); +} int main() { - TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(20, 10, 2, 6); - TextureDataR8_write_to_file(&tex_1, "log_10_2_6_TEMPLATE.r8"); - TextureDataR8_drop(tex_1); + // TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(20, 10, 2, 6); + // TextureDataR8_write_to_file(&tex_1, "log_10_2_6_TEMPLATE.r8"); + // TextureDataR8_drop(tex_1); + TextureDataR8G8B8 t = TextureDataR8G8B8_new(1000, 1000);\ + vec2 center = {500, 500}; + for (int i = 0; i < 70; i++) { + float a1 = (float)i * 2 * M_PIf / 70; + float a2 = (float)(i + 1) * 2 * M_PIf / 70; + vec2 A = vec2_add_vec2(center, vec2_mul_scal((vec2){cosf(a1), sinf(a1)}, 480)); + vec2 B = vec2_add_vec2(center, vec2_mul_scal((vec2){cosf(a2), sinf(a2)}, 480)); + draw_cool_triangle(&t, B, A, center); + } + TextureDataR8G8B8_write_to_file(&t, "experiment.r8g8b8"); + TextureDataR8G8B8_drop(t); return 0; } diff --git a/src/l2/tests/test_textures/bitmap_converter.py b/src/l2/tests/test_textures/bitmap_converter.py index b7dae80..8cc0983 100755 --- a/src/l2/tests/test_textures/bitmap_converter.py +++ b/src/l2/tests/test_textures/bitmap_converter.py @@ -31,7 +31,7 @@ from PIL import Image RAW_FORMATS = { ".r8g8b8a8": {"pix_size": 4, "mode": "RGBA"}, - ".r8b8g8": {"pix_size": 3, "mode": "RGB"}, + ".r8g8b8": {"pix_size": 3, "mode": "RGB"}, ".r8": {"pix_size": 1, "mode": "L"}, } diff --git a/src/l2/tests/test_textures/experiment.r8g8b8 b/src/l2/tests/test_textures/experiment.r8g8b8 new file mode 100644 index 0000000..4358011 Binary files /dev/null and b/src/l2/tests/test_textures/experiment.r8g8b8 differ