diff --git a/src/l2/alice/assets.h b/src/l2/alice/assets.h index 6fc14ff..3700016 100644 --- a/src/l2/alice/assets.h +++ b/src/l2/alice/assets.h @@ -34,14 +34,14 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) { } typedef struct { - GenericMeshTopology topology; + VecU8 topology_path; VecU8 diffuse_texture_path; VecU8 normal_texture_path; VecU8 specular_texture_path; -} GenericMeshAndTextureFilePath; +} AliceGenericMeshPath; -void GenericMeshInSceneTemplate_drop(GenericMeshAndTextureFilePath self) { - GenericMeshTopology_drop(self.topology); +void AliceGenericMeshPath_drop(AliceGenericMeshPath self) { + VecU8_drop(self.topology_path); VecU8_drop(self.diffuse_texture_path); VecU8_drop(self.normal_texture_path); VecU8_drop(self.specular_texture_path); diff --git a/src/l2/alice/model_file.h b/src/l2/alice/model_file.h new file mode 100644 index 0000000..2a71bae --- /dev/null +++ b/src/l2/alice/model_file.h @@ -0,0 +1,108 @@ +#ifndef prototype1_src_l2_alice_model_file_h +#define prototype1_src_l2_alice_model_file_h + +#include "../../l1/system/fileio.h" +#include "assets.h" +#include "stdalign.h" + +static_assert(sizeof(float) == 4, "..."); +static_assert(sizeof(GenericMeshVertexInc) == 4 * (3 + 2), "..."); +static_assert(alignof(GenericMeshVertexInc) == 4, "..."); +static_assert(sizeof(ShinyMeshVertexInc) == 4 * (3), "..."); +static_assert(alignof(ShinyMeshVertexInc) == 4, "..."); + +/* Yes, at this point I really started thinking that maybe I should have written Alice as a template */ + +/* Works only within one machine. todo: rewrite to use .obj after the session is over */ +void alice_write_generic_mesh_to_file(GenericMeshTopology model, VecU8 file_path){ + U64 byte_size = sizeof(U64) * 2 + + sizeof(GenericMeshVertexInc) * model.vertices.len + sizeof(U32) * model.indexes.len; + VecU8 res = VecU8_new_zeroinit(byte_size); + U8* buf = res.buf; + *(U64*)buf = model.vertices.len; + buf += sizeof(U64); + *(U64*)buf = model.indexes.len; + buf += sizeof(U64); + memcpy(buf, model.vertices.buf, model.vertices.len * sizeof(GenericMeshVertexInc)); + buf += model.vertices.len * sizeof(GenericMeshVertexInc); + memcpy(buf, model.indexes.buf, model.indexes.len * sizeof(U32)); + VecU8_append(&file_path, 0); + write_whole_file_or_abort((const char*)file_path.buf, VecU8_to_span(&res)); + GenericMeshTopology_drop(model); + VecU8_drop(file_path); + VecU8_drop(res); +} + +GenericMeshTopology alice_expect_read_generic_mesh_from_file(VecU8 file_path){ + VecU8 read = read_file_by_path(file_path); + U8* buf = read.buf; + U64 remaining = read.len; + if (remaining < sizeof(U64) * 2) { + abortf("Too short\n"); + } + U64 vertices_len = *(U64*)buf; + buf += sizeof(U64); + U64 indexes_len = *(U64*)buf; + buf += sizeof(U64); + if (vertices_len > 1000000 || indexes_len > 1000000) { + abortf("Model is too big\n"); + } + remaining -= sizeof(U64) * 2; + if (remaining != vertices_len * sizeof(GenericMeshVertexInc) + indexes_len * sizeof(U32)) { + abortf("Incorrect file size\n"); + } + VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new_zeroinit(vertices_len); + memcpy(vertices.buf, buf, vertices_len * sizeof(GenericMeshVertexInc)); + buf += vertices_len * sizeof(GenericMeshVertexInc); + VecU32 indexes = VecU32_new_zeroinit(indexes_len); + memcpy(indexes.buf, buf, indexes_len * sizeof(U32)); + return (GenericMeshTopology){.vertices = vertices, .indexes = indexes}; +} + +void alice_write_shiny_mesh_to_file(ShinyMeshTopology model, VecU8 file_path){ + U64 byte_size = sizeof(U64) * 2 + + sizeof(ShinyMeshVertexInc) * model.vertices.len + sizeof(U32) * model.indexes.len; + VecU8 res = VecU8_new_zeroinit(byte_size); + U8* buf = res.buf; + *(U64*)buf = model.vertices.len; + buf += sizeof(U64); + *(U64*)buf = model.indexes.len; + buf += sizeof(U64); + memcpy(buf, model.vertices.buf, model.vertices.len * sizeof(ShinyMeshVertexInc)); + buf += model.vertices.len * sizeof(ShinyMeshVertexInc); + memcpy(buf, model.indexes.buf, model.indexes.len * sizeof(U32)); + VecU8_append(&file_path, 0); + write_whole_file_or_abort((const char*)file_path.buf, VecU8_to_span(&res)); + ShinyMeshTopology_drop(model); + VecU8_drop(file_path); + VecU8_drop(res); +} + +ShinyMeshTopology alice_expect_read_shiny_mesh_from_file(VecU8 file_path){ + VecU8 read = read_file_by_path(file_path); + U8* buf = read.buf; + U64 remaining = read.len; + if (remaining < sizeof(U64) * 2) { + abortf("Too short\n"); + } + U64 vertices_len = *(U64*)buf; + buf += sizeof(U64); + U64 indexes_len = *(U64*)buf; + buf += sizeof(U64); + if (vertices_len > 10000 || indexes_len > 10000) + abortf("Model is too big\n"); + remaining -= sizeof(U64) * 2; + if (remaining != vertices_len * sizeof(ShinyMeshVertexInc) + indexes_len * sizeof(U32)) { + abortf("Incorrect file size\n"); + } + VecShinyMeshVertexInc vertices = VecShinyMeshVertexInc_new_zeroinit(vertices_len); + memcpy(vertices.buf, buf, vertices_len * sizeof(ShinyMeshVertexInc)); + buf += vertices_len * sizeof(ShinyMeshVertexInc); + VecU32 indexes = VecU32_new_zeroinit(indexes_len); + memcpy(indexes.buf, buf, indexes_len * sizeof(U32)); + return (ShinyMeshTopology){.vertices = vertices, .indexes = indexes}; +} + +/* No beauty, just pure brute force */ + +#endif \ No newline at end of file diff --git a/src/l2/allie/Allie.hs b/src/l2/allie/Allie.hs index cbf0c9b..8472418 100644 --- a/src/l2/allie/Allie.hs +++ b/src/l2/allie/Allie.hs @@ -7,6 +7,8 @@ module Allie (justFuckingDoSomething) where +import Geom + import Data.Word (Word8, Word16, Word32, Word64) import Data.Int (Int8, Int16, Int32, Int64) import Foreign.Ptr (Ptr, FunPtr, nullPtr, plusPtr, castPtr) @@ -17,8 +19,9 @@ import qualified Data.Text import Data.Text.Encoding (encodeUtf8) import Data.ByteString (useAsCStringLen) -data AliceOpaque -type Alice = Ptr AliceOpaque +--import Geom + +type Alice = Ptr Word8 foreign import ccall "Alice_new" newAlice :: IO Alice @@ -27,6 +30,18 @@ data AliceAnotherFrameCap s = AliceAnotherFrameCap Alice foreign import ccall "wrapper" allieMkAliceOnWaylandKeyboardKey :: (Alice -> IO ()) -> IO (FunPtr (Alice -> IO ())) foreign import ccall "wrapper" allieMkAliceOnAnotherFrame :: (Alice -> IO ()) -> IO (FunPtr (Alice -> IO ())) +-- All of that is inside Alice. They hold pointers to Alice +type LucyFontFace = Ptr Word8 +-- Actually stores a pointer to rb-tree node in LucyFontFace tree. Must not be deleted by without caution +type LucyFontFaceFixedSize = Ptr Word8 + +type AliceGenericMeshHand = Ptr Word8 + +type AliceShinyMeshHand = Ptr Word8 + +alicePipeline0PointLightMaxCount :: Int +alicePipeline0PointLightMaxCount = 120 + data Callbacks = Callbacks { onWaylandKeyboardKey :: (Alice -> IO ()), onAnotherFrame :: (forall s. AliceAnotherFrameCap s -> IO ()) @@ -59,13 +74,18 @@ foreign import ccall "allie_Alice_add_screen_text_label" allieAliceAddScreenText aliceAddScreenTextLabel :: AliceAnotherFrameCap s -> String -> IO () aliceAddScreenTextLabel (AliceAnotherFrameCap alice) str = useAsCStringLen (encodeUtf8 $ Data.Text.pack $ str) $ \(cstr, len) -> allieAliceAddScreenTextLabel alice (castPtr cstr) (fromIntegral len) +my2onAnotherFrame :: p -> IO () +my2onAnotherFrame alicePerm = putStrLn "ahahhahah" + +--allieRunAlice :: Callbacks -> + -- Function to run the main loop with callbacks justFuckingDoSomething :: IO () justFuckingDoSomething = do alice <- newAlice state <- newIORef 67 -- Create the Callbacks structure. - let callbacks = Callbacks myonKeyboardKey myonAnotherFrame where + let callbacks = Callbacks myonKeyboardKey my2onAnotherFrame where myonKeyboardKey _ = do old <- readIORef state writeIORef state (old + 1) diff --git a/src/l2/allie/Geom.hs b/src/l2/allie/Geom.hs new file mode 100644 index 0000000..1041842 --- /dev/null +++ b/src/l2/allie/Geom.hs @@ -0,0 +1,44 @@ +module Geom(Vec2(..), Vec3(..), Vec4(..), Mat4(..), Addable(..), Multipliable(..)) where + +data Vec2 = Vec2 !Float !Float + deriving (Eq, Show) + +data Vec3 = Vec3 !Float !Float !Float + deriving (Eq, Show) + +data Vec4 = Vec4 !Float !Float !Float !Float + deriving (Eq, Show) + +infixl 6 ^+^ +class Addable a where + (^+^) :: a -> a -> a + +instance Addable Vec2 where + (Vec2 ax ay) ^+^ (Vec2 bx by) = Vec2 (ax + bx) (ay + by) + +instance Addable Vec3 where + (Vec3 ax ay az) ^+^ (Vec3 bx by bz) = + Vec3 (ax + bx) (ay + by) (az + bz) + +instance Addable Vec4 where + (Vec4 a1 a2 a3 a4) ^+^ (Vec4 b1 b2 b3 b4) = + Vec4 (a1 + b1) (a2 + b2) (a3 + b3) (a4 + b4) + + +infixl 7 ^*^ +class Multipliable a b c where + (^*^) :: a -> b -> c + +instance Multipliable Vec2 Float Vec2 where + (Vec2 ax ay) ^*^ b = Vec2 (ax * b) (ay * b) + +instance Multipliable Vec3 Float Vec3 where + (Vec3 ax ay az) ^*^ b = Vec3 (ax * b) (ay * b) (az * b) + +instance Multipliable Vec4 Float Vec4 where + (Vec4 ax ay az aw) ^*^ b = Vec4 (ax * b) (ay * b) (az * b) (aw * b) + +data Mat4 = Mat4 !Vec4 !Vec4 !Vec4 !Vec4 + +mat4Transit :: Vec3 -> Mat4 +mat4Transit (Vec3 x y z) = Mat4 (Vec4 1 0 0 0) (Vec4 0 1 0 0) (Vec4 0 0 1 0) (Vec4 x y z 1) diff --git a/src/l2/allie/allie.c b/src/l2/allie/allie.c index 996d4d9..c2e07a6 100644 --- a/src/l2/allie/allie.c +++ b/src/l2/allie/allie.c @@ -1,5 +1,4 @@ -#include "../alice/assets.h" -#include "../anne/r4_models.h" // todo: this is very illegal, this is very-very illegal. Please, don't do this +#include "../alice/model_file.h" #include "../../l1/marie/geom_alg_utils.h" #include "../margaret/vulkan_utils.h" #include "../lucy/glyph_render.h" @@ -820,35 +819,30 @@ struct Alice { VkFramebuffer IT1_framebuffer; VkDescriptorSet descriptor_set_for_pipeline_0b; VkDescriptorSet descriptor_set_for_pipeline_1; - - /* todo: it is not actually a part of engine code, it is an app code. I will delete it */ - LucyFace font_face; - RBTreeNodeLucyFaceFixedSize* font_face_of_size_40; - - ListNodeAliceGenericMeshHand* model_gen; - ListNodeAliceShinyMeshHand* model_sh; }; -ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, GenericMeshAndTextureFilePath mt){ +ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, AliceGenericMeshPath paths){ + GenericMeshTopology topology = alice_expect_read_generic_mesh_from_file(paths.topology_path); + ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand)); AliceGenericMeshHand* mm = &mm_node->el; - mm->indexes = mt.topology.indexes.len; + mm->indexes = topology.indexes.len; mm->instance_attr.count = 0; mm->instance_attr.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 69); mm->instance_attr.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, 69); mm->staging_vbo = MargaretBufAllocator_alloc(&alice->staging_buffers, - mt.topology.vertices.len * sizeof(GenericMeshVertex)); + topology.vertices.len * sizeof(GenericMeshVertex)); mm->staging_ebo = MargaretBufAllocator_alloc(&alice->staging_buffers, - mt.topology.indexes.len * sizeof(U32)); + topology.indexes.len * sizeof(U32)); // todo: change this, I don't like this at all :( - mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&mt.diffuse_texture_path)); - mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&mt.normal_texture_path)); - mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&mt.specular_texture_path)); - VecU8_drop(mt.diffuse_texture_path); - VecU8_drop(mt.normal_texture_path); - VecU8_drop(mt.specular_texture_path); + mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&paths.diffuse_texture_path)); + mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&paths.normal_texture_path)); + mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&paths.specular_texture_path)); + VecU8_drop(paths.diffuse_texture_path); + VecU8_drop(paths.normal_texture_path); + VecU8_drop(paths.specular_texture_path); mm->staging_diffuse_tex_buf = MargaretBufAllocator_alloc(&alice->staging_buffers, mm->pixels_diffuse.pixels.len * sizeof(cvec4)); @@ -858,9 +852,9 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, GenericMeshAn mm->pixels_specular.pixels.len * sizeof(U8)); mm->vbo = MargaretBufAllocator_alloc(&alice->dev_local_buffers, - mt.topology.vertices.len * sizeof(GenericMeshVertex)); + topology.vertices.len * sizeof(GenericMeshVertex)); mm->ebo = MargaretBufAllocator_alloc(&alice->dev_local_buffers, - mt.topology.indexes.len * sizeof(U32)); + topology.indexes.len * sizeof(U32)); mm->diffuse_texture = MargaretImgAllocator_alloc(&alice->dev_local_images, mm->pixels_diffuse.width, mm->pixels_diffuse.height, @@ -879,20 +873,20 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, GenericMeshAn /* We allocated enough memory, but now it's time to actually fill staging buffers */ /* Filleing staging VBO */ - assert(mm->staging_vbo.len >= mt.topology.vertices.len * sizeof(GenericMeshVertex)); - assert(mm->vbo.len >= mt.topology.vertices.len * sizeof(GenericMeshVertex)); + assert(mm->staging_vbo.len >= topology.vertices.len * sizeof(GenericMeshVertex)); + assert(mm->vbo.len >= topology.vertices.len * sizeof(GenericMeshVertex)); GenericMeshVertex* staging_vbo = (GenericMeshVertex*)MargaretSubbuf_get_mapped(&mm->staging_vbo); - for (U64 i = 0; i < mt.topology.vertices.len; i++) { - staging_vbo[i].base = mt.topology.vertices.buf[i]; + for (U64 i = 0; i < topology.vertices.len; i++) { + staging_vbo[i].base = topology.vertices.buf[i]; } - assert(mt.topology.indexes.len % 3 == 0); - for (size_t ti = 0; ti * 3 < mt.topology.indexes.len; ti++) { - U32 v0 = mt.topology.indexes.buf[ti * 3 + 0]; - U32 v1 = mt.topology.indexes.buf[ti * 3 + 1]; - U32 v2 = mt.topology.indexes.buf[ti * 3 + 2]; - const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&mt.topology.vertices, v0); - const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&mt.topology.vertices, v1); - const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&mt.topology.vertices, v2); + assert(topology.indexes.len % 3 == 0); + for (size_t ti = 0; ti * 3 < topology.indexes.len; ti++) { + U32 v0 = topology.indexes.buf[ti * 3 + 0]; + U32 v1 = topology.indexes.buf[ti * 3 + 1]; + U32 v2 = topology.indexes.buf[ti * 3 + 2]; + const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&topology.vertices, v0); + const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&topology.vertices, v1); + const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&topology.vertices, v2); vec3 dp1 = vec3_minus_vec3(A1->pos, A0->pos); vec3 dp2 = vec3_minus_vec3(A2->pos, A0->pos); float du1 = A1->tex.x - A0->tex.x; @@ -909,11 +903,11 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, GenericMeshAn staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y; } /* Filling EBO is easy */ - assert(mt.topology.indexes.len == mm->indexes); - size_t ebo_len = mt.topology.indexes.len * sizeof(U32); + assert(topology.indexes.len == mm->indexes); + size_t ebo_len = topology.indexes.len * sizeof(U32); assert(mm->ebo.len >= ebo_len); U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo); - memcpy(staging_ebo, mt.topology.indexes.buf, ebo_len); + memcpy(staging_ebo, topology.indexes.buf, ebo_len); /* Filling staging textures from memory pixel data */ /* todo: do it immediately ON THE READ */ memcpy(MargaretSubbuf_get_mapped(&mm->staging_diffuse_tex_buf), mm->pixels_diffuse.pixels.buf, @@ -999,7 +993,9 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, GenericMeshAn return mm_node; } -ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, ShinyMeshTopology topology){ +ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, VecU8 path){ + ShinyMeshTopology topology = alice_expect_read_shiny_mesh_from_file(path); + ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand)); AliceShinyMeshHand* mm = &mm_node->el; @@ -1558,18 +1554,11 @@ void alice_frame_drawing(Alice* alice) { alice->callbacks.on_another_frame(alice); margaret_reset_and_begin_command_buffer(alice->transfer_command_buf); - AliceScene__another_frame(alice); - LucyGlyphCache_another_frame(&alice->lucy_cache); - // LucyRenderer_clear(&alice->lucy_renderer); - // LucyRenderer_add_text(&alice->lucy_renderer, alice->font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, - // VecU8_to_span(&alice->scene.text_on_screen), (ivec2){10, 10}); LucyRenderer_another_frame(&alice->lucy_renderer); margaret_end_command_buffer(alice->transfer_command_buf); - alice_reset_and_record_command_buffer_0(alice, t_mat); - alice_reset_and_record_command_buffer_1(alice, *VecVkFramebuffer_at(&alice->swfb.framebuffers, ij)); check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ @@ -2066,6 +2055,8 @@ Alice* Alice_new(){ alice->shiny_models = AliceAllMeshesShiny_new(); alice->pipeline0_ubo.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, sizeof(Pipeline0UBO)); alice->pipeline0_ubo.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, sizeof(Pipeline0UBO)); + Pipeline0UBO* ubo0 = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + ubo0->point_light_count = ubo0->spotlight_count = 0; alice->cam_info = AliceCamVerticalControl_new(); alice->rendering_config = AliceRenderConfig_new(); @@ -2097,77 +2088,31 @@ Alice* Alice_new(){ alice->wl.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); alice->wl.frame_count_since_key = 0; /* Alice initialization complete */ - /* todo: delete exaple data initialization. Yes, this is not part of an engine. It is an example I need to delete this */ - alice->font_face = LucyFace_new(alice->ft_library, &alice->lucy_cache, - VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", root_dir)); - alice->font_face_of_size_40 = LucyFace_of_size(&alice->font_face, 40); - { - VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new(); - VecU32Segment ranges_needed = VecU32Segment_new(); - VecU32Segment_append(&ranges_needed, (U32Segment){.start = 32, .len = 126 - 32 + 1}); - VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ - .sized_face = alice->font_face_of_size_40, .codepoint_ranges = ranges_needed, - }); - LucyGlyphCache_add_glyphs(lucy_requests); - } - { - alice->model_gen = Alice_add_generic_mesh(alice, GenericMeshAndTextureFilePath_for_log(root_dir, 10, 2, 6)); - AliceGenericMeshHand_resize_instance_arr(alice, &alice->model_gen->el, 100); - - for (int X = 0; X < 10; X++) { - for (int Z = 0; Z < 10; Z++) { - AliceGenericMeshHand_set(&alice->model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){ - .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}), - }); - } - } - - alice->model_sh = Alice_add_shiny_mesh(alice, generate_shiny_cube(0.3f)); - AliceShinyMeshHand_resize_instance_arr(alice, &alice->model_sh->el, 100); - - for (int X = 0; X < 10; X++) { - for (int Z = 0; Z < 10; Z++) { - AliceShinyMeshHand_set(&alice->model_sh->el, X * 10 + Z, (ShinyMeshInstanceInc){ - .color_on = {0, 1, 0}, .color_off = {0.3f, 0.6f, 0.3f}, - .model_t = marie_translation_mat4((vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}), - }); - } - } - - Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); - assert(pipeline_0_ubo_point_light_max_count >= 100); - ubo->point_light_count = 100; - ubo->spotlight_count = 0; - for (int X = 0; X < 10; X++) { - for (int Z = 0; Z < 10; Z++) { - ubo->point_light_arr[X * 10 + Z] = (Pipeline0PointLight){ - .pos = (vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}, - .color = {5, 5, 5} - }; - } - } - ubo->point_light_arr[0].color = (vec3){100, 100, 100}; - } - - LucyRenderer_add_text(&alice->lucy_renderer, alice->font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, - cstr("Bebra budet\notnyahana"), (ivec2){10, 10}); - return alice; } +void Alice_set_point_light_count(Alice* alice, int new_count){ + Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(new_count <= pipeline_0_ubo_point_light_max_count); + ubo->point_light_count = new_count; +} + +void Alice_set_point_light(Alice* alice, int index, Pipeline0PointLight data){ + Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(index < pipeline_0_ubo_point_light_max_count); + ubo->point_light_arr[index] = data; +} + + void Alice_clear_screen_text(Alice* alice){ LucyRenderer_clear(&alice->lucy_renderer); } -void Alice_add_screen_text_label(Alice* alice, SpanU8 text){ - LucyRenderer_add_text(&alice->lucy_renderer, alice->font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, - text, (ivec2){10, 10}); -} - -void allie_Alice_add_screen_text_label(Alice* alice, const U8* data, U64 len){ - Alice_add_screen_text_label(alice, (SpanU8){data, len}); +void Alice_add_screen_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color, SpanU8 text, ivec2 start_pos){ + LucyRenderer_add_text(&alice->lucy_renderer, ffs, color, 0, text, start_pos); } +/* This function actually consumes alice handler */ void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key; alice->callbacks.on_another_frame = callbacks->on_another_frame; @@ -2218,5 +2163,5 @@ void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { // if (alice->wl.wl_seat) // wl_seat_destroy(alice->wl.wl_seat); // wl_registry_destroy(alice->wl.wl_registry); - // wl_display_disconnect(alice->wl.wl_display); + wl_display_disconnect(alice->wl.wl_display); } diff --git a/src/l2/anne/r4.h b/src/l2/anne/r4.h index bb8afdf..b91a45f 100644 --- a/src/l2/anne/r4.h +++ b/src/l2/anne/r4.h @@ -1,7 +1,7 @@ #ifndef prototype1_src_l2_anne_r4_h #define prototype1_src_l2_anne_r4_h -#include "r4_models.h" +#include "../alice/assets.h" #include "../../../gen/l1/pixel_masses.h" #include "../marie/rasterization.h" #include "../marie/texture_processing.h" @@ -526,9 +526,149 @@ TextureDataR8G8B8A8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_res return res; } + + +GenericMeshTopology generate_one_fourth_of_a_cylinder(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); + float tex_width = 2 * r + w; + float tex_height = 2 * r + (float)k * l; + + const vec2 v0tex = {r / tex_width, r / tex_height}; + const vec2 v1tex = {(r + w) / tex_width, r / tex_height}; + const vec2 v2tex = {r / tex_width, 2 * r / tex_height}; + const vec2 v3tex = {(r + w) / tex_width, 2 * r / tex_height}; + VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new_reserved(8 + 4 * k + (k + 2) * 2); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, r, 0}, .tex = v2tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, r, 0}, .tex = v3tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, -r}, .tex = {r / tex_width, 0}}); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = {(r + w) / tex_width, 0}}); + + for (U32 i = 0; i < k; i++) { + for (int j = 0; j < 2; j++) { + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ + .pos = {0, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r}, + .tex = {v2tex.x, v2tex.y + (float)(i + j) * l / tex_height} + }); + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ + .pos = {w, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r}, + .tex = {v3tex.x, v3tex.y + (float)(i + j) * l / tex_height} + }); + } + } + assert(vertices.len == 8 + 4 * k); + + for (U32 i = 0; i <= k; i++) { + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ + .pos = {0, cosf(a * (float)i) * r, -sinf(a * (float)i) * r}, + .tex = (vec2){ (r - r *sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height}, + }); + } + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); + for (U32 i = 0; i <= k; i++) { + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ + .pos = {w, cosf(a * (float)i) * r, -sinf(a * (float)i) * r}, + .tex = (vec2){ (r + w + r * sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height}, + }); + } + VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); + assert(vertices.len == 8 + 4 * k + (k + 2) * 2); + + VecU32 indexes = VecU32_new_reserved(3*(4+2*k+2*k)); + U32 _span_0[] = {7, 5, 4, 7, 4, 6, 1, 3, 0, 3, 2, 0}; + VecU32_append_span(&indexes, (SpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)}); + for (U32 i = 0; i < k; i++) { + U32 _span_1[] = { + 8 + 4 * k + k + 1, 8 + 4 * k + i, 8 + 4 * k + i + 1, + 8 + 4 * k + 2 * k + 3, 8 + 4 * k + (k + 2) + i + 1, 8 + 4 * k + (k + 2) + i, + 8 + 4 * i + 0, 8 + 4 * i + 1, 8 + 4 * i + 3, + 8 + 4 * i + 0, 8 + 4 * i + 3, 8 + 4 * i + 2, + }; + VecU32_append_span(&indexes, (SpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)}); + } + return (GenericMeshTopology){.vertices = vertices, .indexes = indexes}; +} + +U32 quad_to_triangles_conv_arr[6] = {0, 1, 2, 0, 2, 3}; + +ShinyMeshTopology generate_shiny_cube(float r) { + ShinyMeshVertexInc vert[24] = { + {{+r, +r, +r}}, + {{+r, -r, +r}}, + {{+r, -r, -r}}, + {{+r, +r, -r}}, + + {{-r, -r, -r}}, + {{-r, -r, +r}}, + {{-r, +r, +r}}, + {{-r, +r, -r}}, + + {{+r, +r, +r}}, + {{+r, +r, -r}}, + {{-r, +r, -r}}, + {{-r, +r, +r}}, + + {{-r, -r, -r}}, + {{+r, -r, -r}}, + {{+r, -r, +r}}, + {{-r, -r, +r}}, + + {{+r, +r, +r}}, + {{-r, +r, +r}}, + {{-r, -r, +r}}, + {{+r, -r, +r}}, + + {{-r, -r, -r}}, + {{-r, +r, -r}}, + {{+r, +r, -r}}, + {{+r, -r, -r}}, + }; + VecShinyMeshVertexInc vertices_vec = VecShinyMeshVertexInc_from_span( + (SpanShinyMeshVertexInc){ .data = vert, .len = ARRAY_SIZE(vert) }); + VecU32 indexes_vec = VecU32_new_reserved(36); + for (U32 f = 0; f < 6; f++) { + for (U32 j = 0; j < 6; j++) + VecU32_append(&indexes_vec, f * 4 + quad_to_triangles_conv_arr[j]); + } + return (ShinyMeshTopology){ .vertices = vertices_vec, .indexes = indexes_vec}; +} + +typedef struct { + int face; + /* There is a counterclockwise one-to-one correspondence between vertexes of face and edges of face */ + int vert_on_it; +} CubeVertOfFace; + +CubeVertOfFace CubeVertOfFace_jump(CubeVertOfFace vert) { + const CubeVertOfFace cube_detour_get_neighbour_face[6][4] = { + {{4, 3}, {3, 1}, {5, 2}, {2, 0}}, + {{3, 3}, {4, 1}, {2, 2}, {5, 0}}, + {{0, 3}, {5, 1}, {1, 2}, {4, 0}}, + {{5, 3}, {0, 1}, {4, 2}, {1, 0}}, + {{2, 3}, {1, 1}, {3, 2}, {0, 0}}, + {{1, 3}, {2, 1}, {0, 2}, {3, 0}} + }; + return cube_detour_get_neighbour_face[vert.face][vert.vert_on_it]; +} + +U32 CubeVertOfFace_to_vid(CubeVertOfFace vert) { + return 4 * vert.face + vert.vert_on_it; +} + +CubeVertOfFace CubeVertOfFace_next(CubeVertOfFace vert) { + return (CubeVertOfFace){vert.face, (vert.vert_on_it + 1) % 4}; +} + + #include "../../../gen/l1/margaret/png_pixel_masses.h" #include "../marie/texture_processing.h" #include "../../l1/system/fsmanip.h" +#include "../alice/model_file.h" void for_log(U64 w, U64 r, U64 k) { { @@ -549,16 +689,19 @@ void for_log(U64 w, U64 r, U64 k) { TextureDataR8G8B8A8_drop(fixed_tex); TextureDataR8G8B8A8_drop(tex); } + GenericMeshTopology top = generate_one_fourth_of_a_cylinder((float)w, (float)r, k); + alice_write_generic_mesh_to_file(top, VecU8_fmt("l2/models/log_%u_%u_%u.AliceGenericMesh", w, r, k)); } + + /* We are on l2 */ int gen_assets_for_r4() { + mkdir_nofail("l2/models"); mkdir_nofail("l2/textures"); mkdir_nofail("l2/textures/r4"); for_log(10, 2, 6); - // for_log(5, 5, 10); - // for_log(1, 10, 4); - // for_log(2, 1, 6); + alice_write_shiny_mesh_to_file(generate_shiny_cube(0.3f), vcstr("l2/models/cube.AliceShinyMesh")); return 0; } diff --git a/src/l2/anne/r4_models.h b/src/l2/anne/r4_models.h deleted file mode 100644 index eec0cad..0000000 --- a/src/l2/anne/r4_models.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef prototype1_src_l2_anne_r4_models_h -#define prototype1_src_l2_anne_r4_models_h - -#include "../alice/assets.h" -#include "../../l1/core/VecU8_as_str.h" - -GenericMeshTopology generate_one_fourth_of_a_cylinder(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); - float tex_width = 2 * r + w; - float tex_height = 2 * r + (float)k * l; - - const vec2 v0tex = {r / tex_width, r / tex_height}; - const vec2 v1tex = {(r + w) / tex_width, r / tex_height}; - const vec2 v2tex = {r / tex_width, 2 * r / tex_height}; - const vec2 v3tex = {(r + w) / tex_width, 2 * r / tex_height}; - VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new_reserved(8 + 4 * k + (k + 2) * 2); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, r, 0}, .tex = v2tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, r, 0}, .tex = v3tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, -r}, .tex = {r / tex_width, 0}}); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = {(r + w) / tex_width, 0}}); - - for (U32 i = 0; i < k; i++) { - for (int j = 0; j < 2; j++) { - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ - .pos = {0, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r}, - .tex = {v2tex.x, v2tex.y + (float)(i + j) * l / tex_height} - }); - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ - .pos = {w, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r}, - .tex = {v3tex.x, v3tex.y + (float)(i + j) * l / tex_height} - }); - } - } - assert(vertices.len == 8 + 4 * k); - - for (U32 i = 0; i <= k; i++) { - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ - .pos = {0, cosf(a * (float)i) * r, -sinf(a * (float)i) * r}, - .tex = (vec2){ (r - r *sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height}, - }); - } - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex}); - for (U32 i = 0; i <= k; i++) { - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){ - .pos = {w, cosf(a * (float)i) * r, -sinf(a * (float)i) * r}, - .tex = (vec2){ (r + w + r * sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height}, - }); - } - VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex}); - assert(vertices.len == 8 + 4 * k + (k + 2) * 2); - - VecU32 indexes = VecU32_new_reserved(3*(4+2*k+2*k)); - U32 _span_0[] = {7, 5, 4, 7, 4, 6, 1, 3, 0, 3, 2, 0}; - VecU32_append_span(&indexes, (SpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)}); - for (U32 i = 0; i < k; i++) { - U32 _span_1[] = { - 8 + 4 * k + k + 1, 8 + 4 * k + i, 8 + 4 * k + i + 1, - 8 + 4 * k + 2 * k + 3, 8 + 4 * k + (k + 2) + i + 1, 8 + 4 * k + (k + 2) + i, - 8 + 4 * i + 0, 8 + 4 * i + 1, 8 + 4 * i + 3, - 8 + 4 * i + 0, 8 + 4 * i + 3, 8 + 4 * i + 2, - }; - VecU32_append_span(&indexes, (SpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)}); - } - return (GenericMeshTopology){.vertices = vertices, .indexes = indexes}; -} - -U32 quad_to_triangles_conv_arr[6] = {0, 1, 2, 0, 2, 3}; - -ShinyMeshTopology generate_shiny_cube(float r) { - ShinyMeshVertexInc vert[24] = { - {{+r, +r, +r}}, - {{+r, -r, +r}}, - {{+r, -r, -r}}, - {{+r, +r, -r}}, - - {{-r, -r, -r}}, - {{-r, -r, +r}}, - {{-r, +r, +r}}, - {{-r, +r, -r}}, - - {{+r, +r, +r}}, - {{+r, +r, -r}}, - {{-r, +r, -r}}, - {{-r, +r, +r}}, - - {{-r, -r, -r}}, - {{+r, -r, -r}}, - {{+r, -r, +r}}, - {{-r, -r, +r}}, - - {{+r, +r, +r}}, - {{-r, +r, +r}}, - {{-r, -r, +r}}, - {{+r, -r, +r}}, - - {{-r, -r, -r}}, - {{-r, +r, -r}}, - {{+r, +r, -r}}, - {{+r, -r, -r}}, - }; - VecShinyMeshVertexInc vertices_vec = VecShinyMeshVertexInc_from_span( - (SpanShinyMeshVertexInc){ .data = vert, .len = ARRAY_SIZE(vert) }); - VecU32 indexes_vec = VecU32_new_reserved(36); - for (U32 f = 0; f < 6; f++) { - for (U32 j = 0; j < 6; j++) - VecU32_append(&indexes_vec, f * 4 + quad_to_triangles_conv_arr[j]); - } - return (ShinyMeshTopology){ .vertices = vertices_vec, .indexes = indexes_vec}; -} - -typedef struct { - int face; - /* There is a counterclockwise one-to-one correspondence between vertexes of face and edges of face */ - int vert_on_it; -} CubeVertOfFace; - -CubeVertOfFace CubeVertOfFace_jump(CubeVertOfFace vert) { - const CubeVertOfFace cube_detour_get_neighbour_face[6][4] = { - {{4, 3}, {3, 1}, {5, 2}, {2, 0}}, - {{3, 3}, {4, 1}, {2, 2}, {5, 0}}, - {{0, 3}, {5, 1}, {1, 2}, {4, 0}}, - {{5, 3}, {0, 1}, {4, 2}, {1, 0}}, - {{2, 3}, {1, 1}, {3, 2}, {0, 0}}, - {{1, 3}, {2, 1}, {0, 2}, {3, 0}} - }; - return cube_detour_get_neighbour_face[vert.face][vert.vert_on_it]; -} - -U32 CubeVertOfFace_to_vid(CubeVertOfFace vert) { - return 4 * vert.face + vert.vert_on_it; -} - -CubeVertOfFace CubeVertOfFace_next(CubeVertOfFace vert) { - return (CubeVertOfFace){vert.face, (vert.vert_on_it + 1) % 4}; -} - -// todo: yes, it is AGAINST THE RULES to take from l3 when being on l2, but we fjsdafklj lI WILL REMOVE THIS OK, MAN CALM DOWN -GenericMeshAndTextureFilePath GenericMeshAndTextureFilePath_for_log(SpanU8 root_dir, U64 w, U64 r, U64 k) { - return (GenericMeshAndTextureFilePath){.topology = generate_one_fourth_of_a_cylinder((float)w, (float)r, k), - .diffuse_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_diffuse.png", root_dir, w, r, k), - .normal_texture_path = VecU8_fmt("%s/gen/l2/textures/r4/log_%u_%u_%u_NORMAL.png", root_dir, w, r, k), - .specular_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_specular.png", root_dir, w, r, k), - }; -} - -// todo: separate model data generation and create a function that writes it to .obj file -// todo numero 2: stop generating model data on the fly in r4 and start loading it from generated file - - -#endif diff --git a/src/l3/r4/r4.c b/src/l3/r4/r4.c index 1ad2117..f40ccf0 100644 --- a/src/l3/r4/r4.c +++ b/src/l3/r4/r4.c @@ -1,5 +1,14 @@ #include "../../l2/allie/allie.c" +AliceGenericMeshPath AliceGenericMeshPath_for_log(SpanU8 root_dir, U64 w, U64 r, U64 k) { + return (AliceGenericMeshPath){ + .topology_path = VecU8_fmt("%s/gen/l2/models/log_%u_%u_%u.AliceGenericMesh", root_dir, w, r, k), + .diffuse_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_diffuse.png", root_dir, w, r, k), + .normal_texture_path = VecU8_fmt("%s/gen/l2/textures/r4/log_%u_%u_%u_NORMAL.png", root_dir, w, r, k), + .specular_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_specular.png", root_dir, w, r, k), + }; +} + void main_h_on_wayland_keyboard_key(Alice* alice){ } @@ -10,6 +19,58 @@ void main_h_on_another_frame(Alice* alice){ int main(){ Alice* alice = Alice_new(); + + LucyFace font_face = LucyFace_new(alice->ft_library, &alice->lucy_cache, + VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", cstr("."))); + RBTreeNodeLucyFaceFixedSize* font_face_of_size_40 = LucyFace_of_size(&font_face, 40); + VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new(); + VecU32Segment ranges_needed = VecU32Segment_new(); + VecU32Segment_append(&ranges_needed, (U32Segment){.start = 32, .len = 126 - 32 + 1}); + VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ + .sized_face = font_face_of_size_40, .codepoint_ranges = ranges_needed, + }); + LucyGlyphCache_add_glyphs(lucy_requests); + + ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6)); + AliceGenericMeshHand_resize_instance_arr(alice, &model_gen->el, 100); + + for (int X = 0; X < 10; X++) { + for (int Z = 0; Z < 10; Z++) { + AliceGenericMeshHand_set(&model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){ + .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}), + }); + } + } + + ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(alice, vcstr("./gen/l2/models/cube.AliceShinyMesh")); + AliceShinyMeshHand_resize_instance_arr(alice, &model_sh->el, 100); + + for (int X = 0; X < 10; X++) { + for (int Z = 0; Z < 10; Z++) { + AliceShinyMeshHand_set(&model_sh->el, X * 10 + Z, (ShinyMeshInstanceInc){ + .color_on = {0, 1, 0}, .color_off = {0.3f, 0.6f, 0.3f}, + .model_t = marie_translation_mat4((vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}), + }); + } + } + + Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(pipeline_0_ubo_point_light_max_count >= 100); + ubo->point_light_count = 100; + ubo->spotlight_count = 0; + for (int X = 0; X < 10; X++) { + for (int Z = 0; Z < 10; Z++) { + ubo->point_light_arr[X * 10 + Z] = (Pipeline0PointLight){ + .pos = (vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}, + .color = {5, 5, 5} + }; + } + } + ubo->point_light_arr[0].color = (vec3){100, 100, 100}; + + LucyRenderer_add_text(&alice->lucy_renderer, font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, + cstr("Bebra budet\notnyahana"), (ivec2){10, 10}); + Alice_mainloop(alice, &(AliceCallbacks){ .on_wl_keyboard_key = main_h_on_wayland_keyboard_key, .on_another_frame = main_h_on_another_frame,