diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d6175a..7591810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ add_executable(1_test src/l1_4/tests/t1.c) add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c) -target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon) +target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng) add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) target_link_libraries(0r_tex_init_prep -lm -lpng) diff --git a/src/l2/margaret/png_pixel_masses.h b/src/l2/margaret/png_pixel_masses.h index f335ddc..9fbc9c2 100644 --- a/src/l2/margaret/png_pixel_masses.h +++ b/src/l2/margaret/png_pixel_masses.h @@ -75,7 +75,7 @@ void TextureDataR8G8B8A8_write_to_png_nofail(const TextureDataR8G8B8A8* self, Sp ResultVoidOrVecU8 res = TextureDataR8G8B8A8_write_to_png(self, filename); if (res.variant == Result_Err) { SpanU8_fprint(VecU8_to_span(&res.err), stderr); - abortf("TextureDataR8G8B8A8_write_to_png"); + abortf(" TextureDataR8G8B8A8_write_to_png\n"); } } @@ -199,7 +199,7 @@ ResultVoidOrVecU8 MargaretPromisedPngR8G8B8A8_finish(MargaretPromisedPngR8G8B8A8 row_pointers = calloc(dim.height, sizeof(row_pointers)); for (U32 y = 0; y < dim.height; y++) { - row_pointers[y] = ((png_bytep)buffer) + 4 * dim.width * y; + row_pointers[dim.height - 1 - y] = ((png_bytep)buffer) + 4 * dim.width * y; } png_read_image(self.pngshka, row_pointers); png_read_end(self.pngshka, self.end_info); @@ -240,13 +240,13 @@ TextureDataR8G8B8A8 TextureDataR8G8B8A8_read_from_png_nofail(SpanU8 name) { ResultMargaretPromisedPngR8G8B8A8OrVecU8 res_1 = MargaretPromisedPngR8G8B8A8_begin(name); if (res_1.variant == Result_Err) { SpanU8_fprint(VecU8_to_span(&res_1.err), stderr); - abortf("MargaretPromisedPngR8G8B8A8_begin"); + abortf(" MargaretPromisedPngR8G8B8A8_begin\n"); } /* res_1 invalidated, we moved ownership to _finish methos */ ResultTextureDataR8G8B8A8OrVecU8 res_2 = MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(res_1.ok); if (res_2.variant == Result_Err) { SpanU8_fprint(VecU8_to_span(&res_2.err), stderr); - abortf("MargaretPromisedPngR8G8B8A8_finish (into TextureData)"); + abortf(" MargaretPromisedPngR8G8B8A8_finish (into TextureData)\n"); } return res_2.ok; } diff --git a/src/l2/marie/texture_processing.h b/src/l2/marie/texture_processing.h new file mode 100644 index 0000000..26b177d --- /dev/null +++ b/src/l2/marie/texture_processing.h @@ -0,0 +1,65 @@ +#ifndef PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H +#define PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H + +#include "../../../gen/l1/pixel_masses.h" + +void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) { + U64 width = self->width; + U64 height = TextureDataR8G8B8A8_get_height(self); + U64 cell_width = MAX_U64(1, width / 350); + U64 cell_height = MAX_U64(1, cell_width * 14 / 8); + for (U64 CY = 0; CY < height; CY += cell_height) { + for (U64 CX = 0; CX < width; CX += cell_width) { + float lum = 0; + for (U64 j = 0; j < cell_height; j++) { + U64 y = cell_height * CY + j; + if (y >= height) + continue; + for (U64 i = 0; i < cell_width; i++) { + U64 x = cell_width * CX + i; + if (x >= width) + continue; + cvec4 pix = *TextureDataR8G8B8A8_at(self, x, y); + lum += (float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f; + } + } + lum /= (float)cell_width * (float)cell_height; + printf("%s", lum > 0.95 ? "@" : (lum > 0.8 ? "#" : (lum > 0.65 ? "*" : (lum > 0.4 ? "_" : (lum > 0.2 ? "." : " "))))); + } + printf("\n"); + } +} + +/* Fixes several of my generated textures */ +NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(const TextureDataR8G8B8A8* self) { + S32 width = (S32)self->width; + S32 height = (S32)TextureDataR8G8B8A8_get_height(self); + TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width, height); + // S32 chain[9][2] = {{0, 0}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}}; + for (S32 y = 0; y < height; y++) { + for (S32 x = 0; x < width;) { + cvec4 p = *TextureDataR8G8B8A8_at(self, x, y); + cvec4* r = TextureDataR8G8B8A8_mat(&res, x, y); + if (p.w != 255) { + for (S32 i = -1; i <= 1; i++) { + for (S32 j = -1; j <= 1; j++) { + S32 X = x + i, Y = y + i; + if (X < 0 || X >= width || Y < 0 || Y >= height || i == 0 || y == 0) + continue; + cvec4 n = *TextureDataR8G8B8A8_at(self, X, Y); + if (n.w == 255) { + *r = n; + goto done; + } + } + } + } + *r = p; + done: + x++; + } + } + return res; +} + +#endif \ No newline at end of file diff --git a/src/l2/tests/r0/r0.c b/src/l2/tests/r0/r0.c index e457e76..e47d1cc 100644 --- a/src/l2/tests/r0/r0.c +++ b/src/l2/tests/r0/r0.c @@ -10,6 +10,8 @@ #include "../../../../gen/l_wl_protocols/xdg-shell-client.h" #include +#include "../../margaret/png_pixel_masses.h" + // todo: generate this structure in l2 typedef struct { VkPipelineLayout pipeline_layout; @@ -1766,10 +1768,10 @@ int main() { // todo: generate more cool shiny models // todo: learn how to use libpng - state.vk_ctx.cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_file("textures/log_10_2_6.r8g8b8a8"); + 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_file("textures/log_10_2_6_NORMAL.r8g8b8a8"); + state.vk_ctx.cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("textures/log_10_2_6_NORMAL.png")); // todo: kill myself (update: still WiP) diff --git a/src/l2/tests/r0/r0_assets.h b/src/l2/tests/r0/r0_assets.h index 9a0bc3d..b95802c 100644 --- a/src/l2/tests/r0/r0_assets.h +++ b/src/l2/tests/r0/r0_assets.h @@ -466,20 +466,22 @@ typedef struct { } FnNormalVectorGenCallback; typedef struct { - TextureDataR8G8B8* tex; + TextureDataR8G8B8A8* tex; FnNormalVectorGenCallback my_client; } draw_polygon_on_normal_texture_smooth_param_surf_H_DrawGuest; void draw_polygon_on_normal_texture_smooth_param_surf_h_draw_cb(void* ug, S32 x, S32 y, vec4 attr) { draw_polygon_on_normal_texture_smooth_param_surf_H_DrawGuest* g = ug; vec3 normal = g->my_client.fn(g->my_client.guest, (vec2){attr.x, attr.y}); - *TextureDataR8G8B8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(normal); + cvec3 ans = compress_normal_vec_into_norm_texel(normal); + *TextureDataR8G8B8A8_mat(g->tex, x, y) = (cvec4){ans.x, ans.y, ans.z, 255}; } void draw_polygon_on_normal_texture_smooth_param_surf( - TextureDataR8G8B8* tex, vec2 pa, vec2 pb, vec2 pc, mat3x2 trop, FnNormalVectorGenCallback cb + TextureDataR8G8B8A8* tex, vec2 pa, vec2 pb, vec2 pc, mat3x2 trop, FnNormalVectorGenCallback cb ) { draw_polygon_on_normal_texture_smooth_param_surf_H_DrawGuest aboba = {.tex = tex, .my_client = cb}; + // todo: generate rasterization function (with different precision + different attributes) marie_rasterize_triangle_with_attr( (MariePlaneVertAttr){.pos = mat3x2_mul_vec3(trop, vec2_and_one(pa)), .attr = {pa.x, pa.y, 0, 0} }, (MariePlaneVertAttr){.pos = mat3x2_mul_vec3(trop, vec2_and_one(pb)), .attr = {pb.x, pb.y, 0, 0} }, @@ -520,16 +522,16 @@ void draw_polygon_on_normal_texture_nat_cords_exaggerated_param_surf( typedef struct { - TextureDataR8G8B8* tex; + TextureDataR8G8B8A8* tex; cvec3 normal_compr; } draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest; void draw_polygon_on_normal_texture_absolutely_flat_h_draw_cb(void* ug, S32 x, S32 y, vec4 attr) { draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest* g = ug; - *TextureDataR8G8B8_mat(g->tex, x, y) = g->normal_compr; + *TextureDataR8G8B8A8_mat(g->tex, x, y) = (cvec4){g->normal_compr.x, g->normal_compr.y, g->normal_compr.z, 255}; } -void draw_polygon_on_normal_texture_nat_cords_absolutely_flat(TextureDataR8G8B8* tex, +void draw_polygon_on_normal_texture_nat_cords_absolutely_flat(TextureDataR8G8B8A8* tex, vec2 ta, vec2 tb, vec2 tc, vec3 c_normal ) { draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest aboba = {tex, compress_normal_vec_into_norm_texel(c_normal)}; @@ -538,7 +540,7 @@ void draw_polygon_on_normal_texture_nat_cords_absolutely_flat(TextureDataR8G8B8* .fn = draw_polygon_on_normal_texture_absolutely_flat_h_draw_cb, .guest = (void*)&aboba}); } -void draw_polygon_on_normal_texture_absolutely_flat(TextureDataR8G8B8* tex, +void draw_polygon_on_normal_texture_absolutely_flat(TextureDataR8G8B8A8* tex, vec2 pa, vec2 pb, vec2 pc, mat3x2 trop, vec3 c_normal ) { draw_polygon_on_normal_texture_nat_cords_absolutely_flat(tex, mat3x2_mul_vec3(trop, vec2_and_one(pa)), @@ -564,7 +566,7 @@ vec3 draw_polygon_on_normal_texture_flat_param_surf_h_draw_cb(void* ug, vec2 p) } /* The simplest case of normal texture generation: for a smooth flat surface of a polygon */ -void draw_polygon_on_normal_texture_flat_param_surf(TextureDataR8G8B8* tex, vec2 pa, vec2 pb, vec2 pc, mat3x2 trop, +void draw_polygon_on_normal_texture_flat_param_surf(TextureDataR8G8B8A8* tex, vec2 pa, vec2 pb, vec2 pc, mat3x2 trop, mat3 surf_orient, FnHeightMapGradFlatSurfCallback height_map_cb ) { draw_polygon_on_normal_texture_flat_param_surf_H_DrawGuest aboba = {surf_orient, height_map_cb}; @@ -628,7 +630,7 @@ vec2 height_map_cb_that_uses_bublazhuzhka(void* ug, vec2 v) { return Bublazhuzhka_get_derivative(bzh, v); } -TextureDataR8G8B8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { +TextureDataR8G8B8A8 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 * sinf(M_PI_4f / (float)k); @@ -641,7 +643,7 @@ TextureDataR8G8B8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_resol // const vec2 v3tex = {r + w, 2 * r}; const vec2 v4tex = {r, 0}; const vec2 v5tex = {r + w, 0}; - TextureDataR8G8B8 res = TextureDataR8G8B8_new(width_pix, height_pix); + TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width_pix, height_pix); Bublazhuzhka crap_on_the_back_side = fill_rectangle_with_crap(w, r); mat3x2 trop_back_side = {.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)}; diff --git a/src/l2/tests/r0/r0_tex_init_prep.c b/src/l2/tests/r0/r0_tex_init_prep.c index 9ba97fe..d96de16 100644 --- a/src/l2/tests/r0/r0_tex_init_prep.c +++ b/src/l2/tests/r0/r0_tex_init_prep.c @@ -1,57 +1,26 @@ #include "r0_assets.h" #include "../../marie/rasterization.h" #include "../../margaret/png_pixel_masses.h" - -// todo: move it to some other file -void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) { - U64 width = self->width; - U64 height = TextureDataR8G8B8A8_get_height(self); - U64 cell_width = MAX_U64(1, width / 350); - U64 cell_height = MAX_U64(1, cell_width * 14 / 8); - for (U64 CY = 0; CY < height; CY += cell_height) { - for (U64 CX = 0; CX < width; CX += cell_width) { - float lum = 0; - for (U64 j = 0; j < cell_height; j++) { - U64 y = cell_height * CY + j; - if (y >= height) - continue; - for (U64 i = 0; i < cell_width; i++) { - U64 x = cell_width * CX + i; - if (x >= width) - continue; - cvec4 pix = *TextureDataR8G8B8A8_at(self, x, y); - lum += (float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f; - } - } - lum /= (float)cell_width * (float)cell_height; - printf("%s", lum > 0.95 ? "@" : (lum > 0.8 ? "#" : (lum > 0.65 ? "*" : (lum > 0.4 ? "_" : (lum > 0.2 ? "." : " "))))); - } - printf("\n"); - } -} +#include "../../marie/texture_processing.h" void model_1_template() { - TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 tex_1_big = TextureDataR8G8B8A8_new(tex_1.width, TextureDataR8_get_height(&tex_1)); - for (size_t i = 0; i < tex_1.pixels.len; i++) { - U8 g = *VecU8_at(&tex_1.pixels, i); + 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}; } TextureDataR8G8B8A8_write_to_png_nofail(&tex_1_big, cstr("textures/log_10_2_6_TEMPLATE.png")); TextureDataR8G8B8A8_drop(tex_1_big); - TextureDataR8_drop(tex_1); + TextureDataR8_drop(tex); } void model_1_normal() { - TextureDataR8G8B8 tex_2 = generate_normal_tex_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 tex_2_big = TextureDataR8G8B8A8_new(tex_2.width, TextureDataR8G8B8_get_height(&tex_2)); - for (size_t i = 0; i < tex_2.pixels.len; i++) { - cvec3 rgb = *Veccvec3_at(&tex_2.pixels, i); - *Veccvec4_mat(&tex_2_big.pixels, i) = (cvec4){rgb.x, rgb.y, rgb.z, 255}; - } - TextureDataR8G8B8A8_write_to_png_nofail(&tex_2_big, cstr("textures/log_10_2_6_NORMAL.png")); - TextureDataR8G8B8A8_drop(tex_2_big); - TextureDataR8G8B8_drop(tex_2); + 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() { diff --git a/src/l2/tests/r0/textures/log_10_2_6.png b/src/l2/tests/r0/textures/log_10_2_6.png index 1f54ae0..b2432a5 100644 Binary files a/src/l2/tests/r0/textures/log_10_2_6.png and b/src/l2/tests/r0/textures/log_10_2_6.png differ diff --git a/src/l2/tests/r0/textures/test.png b/src/l2/tests/r0/textures/test.png deleted file mode 100644 index b120b8e..0000000 Binary files a/src/l2/tests/r0/textures/test.png and /dev/null differ