diff --git a/src/l1/anne/alice.h b/src/l1/anne/alice.h index 474344f..74fafe0 100644 --- a/src/l1/anne/alice.h +++ b/src/l1/anne/alice.h @@ -16,7 +16,6 @@ void generate_code_for_alice_on_l1(){ generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceTextureUplOnce"), true, false); /* Engine stuff */ - // todo: yes, maybe right now it is not primitive but I surely will make it primitive someday. Right now I don't care generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){ .T = cstr("AliceGenericMeshHand"), .t_primitive = true}, true); generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){ @@ -28,4 +27,6 @@ void generate_code_for_alice_on_l1(){ generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ .T = cstr("GenericMeshTopology") }); + + generate_eve_span_company_for_primitive(l, ns, cstr("AliceTextureSlot"), true, false); } diff --git a/src/l2/alice/assets.h b/src/l2/alice/assets.h index ce9fdef..a30c9fc 100644 --- a/src/l2/alice/assets.h +++ b/src/l2/alice/assets.h @@ -34,7 +34,6 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) { /* non-primitive */ typedef struct { - VecU8 diffuse_texture_path; VecU8 normal_texture_path; VecU8 specular_texture_path; } AliceGenericMeshTexturePaths; diff --git a/src/l2/alice/engine.h b/src/l2/alice/engine.h index 953c99b..fbcf9e8 100644 --- a/src/l2/alice/engine.h +++ b/src/l2/alice/engine.h @@ -6,31 +6,15 @@ #include "transfer_in_mainloop.h" #include "../lucy/glyph_render.h" -typedef struct { - /* Each generic model has its own descriptor set - * It's because it has its own textures. But it also has copies of references to light UBO - * Because I am to lazy to create two set layouts for generic model pipeline */ - VkDescriptorSet p_0a_set_1; -} AliceGenericMeshMemDependantVkObj; - typedef struct { size_t indexes; - // todo: replace TextureDataXXX with MargaretPngPromises - TextureDataR8G8B8A8 pixels_diffuse; - TextureDataR8G8B8A8 pixels_normal; - TextureDataR8 pixels_specular; - MargaretSubbuf vbo; MargaretSubbuf ebo; - MargaretTexture diffuse_texture; - MargaretTexture normal_texture; - MargaretTexture specular_texture; - PatriciaBuf instance_attr; - AliceGenericMeshMemDependantVkObj mem_dependant_vk_obj; + U32 diffuse_tex_slot, normal_tex_slot, specular_tex_slot; } AliceGenericMeshHand; #include "../../../gen/l1/eve/alice/ListAliceGenericMeshHand.h" @@ -174,6 +158,9 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_ return render_pass; } +#define ALICE_MAX_TEXTURES_COUNT 600 + + VkDescriptorSetLayout alice_create_pipline0_desc_set0_layout(VkDevice device) { VkDescriptorSetLayout pipeline0_desc_set0_layout; check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ @@ -196,50 +183,43 @@ VkDescriptorSetLayout alice_create_pipline0_desc_set0_layout(VkDevice device) { return pipeline0_desc_set0_layout; } +VkDescriptorSetLayout alice_create_pipeline0_desc_set1_layout(VkDevice device, U32 max_textures_cnt) { + VkDescriptorSetLayout pipeline0_desc_set0_layout; + check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = &(VkDescriptorSetLayoutBindingFlagsCreateInfo){ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .bindingCount = 1, + .pBindingFlags = (VkDescriptorBindingFlags[]){ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT } + }, + .bindingCount = 1, + .pBindings = (VkDescriptorSetLayoutBinding[]){ + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = max_textures_cnt, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + } + }, + }, NULL, &pipeline0_desc_set0_layout) == VK_SUCCESS); + return pipeline0_desc_set0_layout; +} + typedef struct { VkPipelineLayout pipeline_layout; VkPipeline pipeline; - VkDescriptorSetLayout desc_set_0b1_layout; } AlicePipeline0a; void AlicePipeline0a_destroy(VkDevice device, AlicePipeline0a hands) { vkDestroyPipeline(device, hands.pipeline, NULL); vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(device, hands.desc_set_0b1_layout, NULL); } AlicePipeline0a create_graphics_pipeline_0a( - VkDevice device, SpanU8 root_dir, VkDescriptorSetLayout pipline0_desc_set0_layout, + VkDevice device, SpanU8 root_dir, + VkDescriptorSetLayout pipline0_desc_set0_layout, VkDescriptorSetLayout pipeline0_desc_set1_layout, VkRenderPass render_pass, uint32_t subpass ) { - VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - { - .binding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - { - .binding = 2, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - }; - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), - .pBindings = bindings_for_my_descr_set_layout, - }; - VkDescriptorSetLayout my_descriptor_set_layout; - check(vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) == VK_SUCCESS); - VkPushConstantRange pc_ranges[] = { { .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, @@ -247,13 +227,16 @@ AlicePipeline0a create_graphics_pipeline_0a( }, { .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, .offset = sizeof(mat4), .size = sizeof(vec3) - }, + }, { + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = sizeof(mat4) + sizeof(vec3), .size = sizeof(U32) * 3 + } }; VkPipelineLayoutCreateInfo layout_crinfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 2, - .pSetLayouts = (VkDescriptorSetLayout[]){pipline0_desc_set0_layout, my_descriptor_set_layout}, + .pSetLayouts = (VkDescriptorSetLayout[]){pipline0_desc_set0_layout, pipeline0_desc_set1_layout}, .pushConstantRangeCount = ARRAY_SIZE(pc_ranges), .pPushConstantRanges = pc_ranges, }; @@ -338,8 +321,7 @@ AlicePipeline0a create_graphics_pipeline_0a( .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes, .depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false }); - return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline, - .desc_set_0b1_layout = my_descriptor_set_layout}; + return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline}; } typedef struct { @@ -696,7 +678,7 @@ float AliceWaylandApp_get_elapsed_time(const AliceWaylandApp* self){ } /* They are actually MutRef, but who cares lol, we won't have such distinction here anytime soon, so we shorten - * it to Ref (whil keeping in kind that it is actually MutRef) + * it to Ref (while keeping in kind that it is actually MutRef). Also, these lines do nothing useful */ typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand; #include "../../../gen/l1/eve/alice/VecRefListNodeAliceGenericMeshHand.h" @@ -704,6 +686,12 @@ typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand; typedef struct ListNodeAliceShinyMeshHand* RefListNodeAliceShinyMeshHand; #include "../../../gen/l1/eve/alice/VecRefListNodeAliceShinyMeshHand.h" +typedef struct { + bool is_some; + MargaretTexture tex; +} AliceTextureSlot; + +#include "../../../gen/l1/eve/alice/VecAliceTextureSlot.h" struct Alice { AliceCallbacks callbacks; @@ -721,6 +709,8 @@ struct Alice { VkRenderPass render_pass_0; // One descriptor set found in all shaders of pipeline0 VkDescriptorSetLayout pipeline0_desc_set0_layout; + // This one contains textures + VkDescriptorSetLayout pipeline0_desc_set1_layout; // Features it's own descriptor set layout + built on top of pipeline0_desc_set0_layout AlicePipeline0a pipeline_hands_0a; // No personal descriptor set layouts (though it borrows pipeline0_desc_set0_layout) @@ -747,6 +737,8 @@ struct Alice { Abigail abigail; AlicePipline0LightConf pipeline0_light_conf; + VecAliceTextureSlot texture_slots; + ListAliceGenericMeshHand generic_models; ListAliceShinyMeshHand shiny_models; AliceCamVerticalControl cam_info; @@ -764,7 +756,8 @@ struct Alice { VkImageView zbuffer_view; VkImageView IT1_view; VkFramebuffer IT1_framebuffer; - VkDescriptorSet descriptor_set_for_pipeline_0; + VkDescriptorSet descriptor_set0_for_pipeline_0; + VkDescriptorSet descriptor_set1_for_pipeline_0; VkDescriptorSet descriptor_set_for_pipeline_1; /* You see, there are two places when user can write to transfer_command_buffer: When Alice is initialized, but @@ -775,274 +768,6 @@ struct Alice { bool transfer_command_buf_already_reset; }; -ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const GenericMeshTopology* topology, - AliceGenericMeshTexturePaths t_paths - ){ - - ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand)); - AliceGenericMeshHand* mm = &mm_node->el; - mm->indexes = topology->indexes.len; - mm->instance_attr.count = 0; - mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 200); - mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 200); - - // todo: change this, I don't like this at all :( - mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.diffuse_texture_path)); - mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.normal_texture_path)); - mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&t_paths.specular_texture_path)); - VecU8_drop(t_paths.diffuse_texture_path); - VecU8_drop(t_paths.normal_texture_path); - VecU8_drop(t_paths.specular_texture_path); - - GenericMeshVertex* staging_vbo; - mm->vbo = Abigail_register_new_buffer(&alice->abigail, - topology->vertices.len * sizeof(GenericMeshVertex), - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, - (void**)&staging_vbo /* We return values here */); - - U32* staging_ebo; - mm->ebo = Abigail_register_new_buffer(&alice->abigail, - topology->indexes.len * sizeof(U32), - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, - (void**)&staging_ebo /* We return values here */); - - void* diffuse_tex_staging; - mm->diffuse_texture = Abigail_register_new_texture(&alice->abigail, - mm->pixels_diffuse.width, mm->pixels_diffuse.height, - sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, - &diffuse_tex_staging); - void *normal_tex_staging; - mm->normal_texture = Abigail_register_new_texture(&alice->abigail, - mm->pixels_normal.width, mm->pixels_normal.height, - sizeof(cvec4), VK_FORMAT_R8G8B8A8_UNORM, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, - &normal_tex_staging); - void* specular_tex_staging; - mm->specular_texture = Abigail_register_new_texture(&alice->abigail, - mm->pixels_specular.width, mm->pixels_specular.height, - sizeof(U8), VK_FORMAT_R8_UNORM, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, - &specular_tex_staging); - - assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex)); - /* We allocated enough memory, but now it's time to actually fill staging buffers */ - /* Filling staging VBO */ - for (U64 i = 0; i < topology->vertices.len; i++) { - staging_vbo[i].base = topology->vertices.buf[i]; - } - 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; - float dv1 = A1->tex.y - A0->tex.y; - float du2 = A2->tex.x - A0->tex.x; - float dv2 = A2->tex.y - A0->tex.y; - vec3 norm = vec3_normalize(vec3_cross(dp1, dp2)); - mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2( - mat2_inverse(mat2_new(du1, dv1, du2, dv2)), - mat2x3_transpose((mat2x3){.x = dp1, .y = dp2}) - )); - staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm; - staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x; - staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y; - } - /* Filling EBO is easy */ - assert(topology->indexes.len == mm->indexes); - size_t ebo_len = topology->indexes.len * sizeof(U32); - memcpy(staging_ebo, topology->indexes.buf, ebo_len); - /* Filling staging textures from memory pixel data */ - /* todo: do it immediately ON THE READ */ - memcpy(diffuse_tex_staging, mm->pixels_diffuse.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse)); - memcpy(normal_tex_staging, mm->pixels_normal.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_normal)); - memcpy(specular_tex_staging, mm->pixels_specular.pixels.buf, - TextureDataR8_get_size_in_bytes(&mm->pixels_specular)); - // todo: that is about time when we can delete mm->pixels_* buffers. They are still wasting space out there - // todo: BUt I won't do it, because I chose inplace texture reading (from png) - - /* But now we are filling AliceGenericMeshMemDependantVkObj. If we ever gonna do defragmentation, - * this step would have to be repeated */ - - VkDescriptorSet P = margaret_allocate_descriptor_set(alice->device, - alice->descriptor_pool, alice->pipeline_hands_0a.desc_set_0b1_layout); - mm->mem_dependant_vk_obj.p_0a_set_1 = P; - - VkWriteDescriptorSet writes_in_descriptor_set[] = { - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &(VkDescriptorImageInfo){ - .sampler = alice->linear_sampler, .imageView = mm->diffuse_texture.view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P, - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &(VkDescriptorImageInfo){ - .sampler = alice->nearest_sampler, .imageView = mm->normal_texture.view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P, - .dstBinding = 2, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &(VkDescriptorImageInfo){ - .sampler = alice->nearest_sampler, .imageView = mm->specular_texture.view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }, - }, - }; - vkUpdateDescriptorSets(alice->device, ARRAY_SIZE(writes_in_descriptor_set), writes_in_descriptor_set, 0, NULL); - - ListAliceGenericMeshHand_insert_node(&alice->generic_models, mm_node); - return mm_node; -} - -ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTopology* topology){ - ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand)); - AliceShinyMeshHand* mm = &mm_node->el; - - mm->indexes = topology->indexes.len; - - mm->instance_attr.count = 0; - mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 128); - mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 128); - - ShinyMeshVertex* staging_vbo; - mm->vbo = Abigail_register_new_buffer(&alice->abigail, - topology->vertices.len * sizeof(ShinyMeshVertex), - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, - (void**)&staging_vbo); - - U32* staging_ebo; - mm->ebo = Abigail_register_new_buffer(&alice->abigail, - topology->indexes.len * sizeof(U32), - alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, - (void**)&staging_ebo); - - assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex)); - /* We allocated enough memory, now it's time to actually fill staging buffers */ - /* And we start by filling staging VBO */ - for (U64 i = 0; i < topology->vertices.len; i++) { - staging_vbo[i].base = topology->vertices.buf[i]; - } - 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]; - vec3 p0 = VecShinyMeshVertexInc_at(&topology->vertices, v0)->pos; - vec3 p1 = VecShinyMeshVertexInc_at(&topology->vertices, v1)->pos; - vec3 p2 = VecShinyMeshVertexInc_at(&topology->vertices, v2)->pos; - vec3 norm = vec3_normalize(vec3_cross(vec3_minus_vec3(p1, p0), vec3_minus_vec3(p2, p0))); - staging_vbo[v0].normal = staging_vbo[v1].normal = staging_vbo[v2].normal = norm; - } - - /* Filling staging EBO is super-duper easy */ - assert(topology->indexes.len == mm->indexes); - size_t ebo_len = topology->indexes.len * sizeof(U32); - memcpy(staging_ebo, topology->indexes.buf, ebo_len); - - ListAliceShinyMeshHand_insert_node(&alice->shiny_models, mm_node); - return mm_node; -} - -// todo: write deletion after I separate textures from Meshes -void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) { - AliceGenericMeshHand* mm = &hand->el; - MargaretBufAllocator_free(alice->dev_local_buffers, mm->vbo); - MargaretBufAllocator_free(alice->dev_local_buffers, mm->ebo); - MargaretImgAllocator_free(alice->dev_local_images, mm->diffuse_texture.img.a); - MargaretImgAllocator_free(alice->dev_local_images, mm->normal_texture.img.a); - MargaretImgAllocator_free(alice->dev_local_images, mm->specular_texture.img.a); - - MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); - MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); - // todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture. - // todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would - // todo: be primitive again, without stupid crap - ListAliceGenericMeshHand_erase_by_it(&alice->generic_models, hand); -} - -/* Be careful to only delete meshes when you actually allowed to do so */ -void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) { - AliceShinyMeshHand* mm = &hand->el; - MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.vbo); - MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.ebo); - - MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); - MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); - ListAliceShinyMeshHand_erase_by_it(&alice->shiny_models, hand); -} - - -void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand* self, U64 new_count){ - U64 needed_length = new_count * sizeof(GenericMeshInstance); - if (self->instance_attr.staging.len < needed_length) { - printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n", - self->instance_attr.staging.len, needed_length); - MargaretBufAllocator_expand_or_move_old_host_visible( - alice->staging_buffers, &self->instance_attr.staging, needed_length); - } - self->instance_attr.count = new_count; -} - -void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){ - U64 needed_length = new_count * sizeof(ShinyMeshInstance); - if (self->instance_attr.staging.len < needed_length) { - MargaretBufAllocator_expand_or_move_old_host_visible( - alice->staging_buffers, &self->instance_attr.staging, needed_length); - } - self->instance_attr.count = new_count; -} - -void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){ - assert(instance < self->instance_attr.count); - GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); - staging[instance].base = uncomp; - mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); - staging[instance].normal_t = mat3_new( - tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, - tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, - tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); -} - -void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){ - assert(instance < self->instance_attr.count); - ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); - staging[instance].base = uncomp; - mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); - staging[instance].normal_t = mat3_new( - tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, - tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, - tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); -} - /* No buffer rerecording, no buffer beginning, no buffer ending, * 1) It copies initial generic model and shiny model topology. Textures of generic models included * 2) For all models and for all light sources it copies EVERYTHING. @@ -1132,17 +857,17 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) { vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline); record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent); vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof(mat4), &proj_cam_t); + 0, sizeof(mat4), &proj_cam_t); vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); vkCmdBindDescriptorSets( - alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout, - 0, 1, &alice->descriptor_set_for_pipeline_0, 0, NULL); + alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout, + 0, 2, + (VkDescriptorSet[]){alice->descriptor_set0_for_pipeline_0, alice->descriptor_set1_for_pipeline_0}, + 0, NULL); for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.first; mm_node; mm_node = mm_node->next) { AliceGenericMeshHand* model = &mm_node->el; - VkDescriptorSet descriptor_set1_for_textures = model->mem_dependant_vk_obj.p_0a_set_1; - const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local; vkCmdBindVertexBuffers(alice->rendering_command_buf_0, 0, @@ -1152,9 +877,9 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) { }, (VkDeviceSize[]){ model->vbo.start, dev_local_inst_attr->start }); vkCmdBindIndexBuffer(alice->rendering_command_buf_0, MargaretSubbuf_get_buffer(&model->ebo), model->ebo.start, VK_INDEX_TYPE_UINT32); - vkCmdBindDescriptorSets( - alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout, - 1, 1, &descriptor_set1_for_textures, 0, NULL); + vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, + VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(mat4) + sizeof(vec3), sizeof(U32) * 3, + (U32[]){model->diffuse_tex_slot, model->normal_tex_slot, model->specular_tex_slot}); vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0); } @@ -1166,7 +891,7 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) { sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); vkCmdBindDescriptorSets( alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline_layout, - 0, 1, &alice->descriptor_set_for_pipeline_0, 0, NULL); + 0, 1, &alice->descriptor_set0_for_pipeline_0, 0, NULL); for (ListNodeAliceShinyMeshHand* mm_node = alice->shiny_models.first; mm_node; mm_node = mm_node->next) { const AliceShinyMeshHand* model = &mm_node->el; @@ -1252,7 +977,7 @@ void recreate_swapchain(Alice *alice) { void alice_update_pipe0_set0_descr1(Alice* alice) { vkUpdateDescriptorSets(alice->device, 1, &(VkWriteDescriptorSet){ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = alice->descriptor_set_for_pipeline_0, + .dstSet = alice->descriptor_set0_for_pipeline_0, .dstBinding = 1, .dstArrayElement = 0, .descriptorCount = 1, @@ -1277,15 +1002,17 @@ void alice_create_mem_dependant_vk_obj(Alice* alice){ alice->IT1_view, alice->zbuffer_view, alice->render_pass_0, alice->wl.sane_image_extent_limit.width, alice->wl.sane_image_extent_limit.height); - alice->descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set( + alice->descriptor_set0_for_pipeline_0 = margaret_allocate_descriptor_set( alice->device, alice->descriptor_pool, alice->pipeline0_desc_set0_layout); + alice->descriptor_set1_for_pipeline_0 = margaret_allocate_descriptor_set( + alice->device, alice->descriptor_pool, alice->pipeline0_desc_set1_layout); alice->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( alice->device, alice->descriptor_pool, alice->pipeline_hands_1.descriptor_set_layout); VkWriteDescriptorSet writes_in_descriptor_sets[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = alice->descriptor_set_for_pipeline_0, + .dstSet = alice->descriptor_set0_for_pipeline_0, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -1782,7 +1509,9 @@ Alice* Alice_new(){ alice->render_pass_0 = create_render_pass_0(alice->device, alice->IT1_format, alice->zbuffer_format); alice->pipeline0_desc_set0_layout = alice_create_pipline0_desc_set0_layout(alice->device); - alice->pipeline_hands_0a = create_graphics_pipeline_0a(alice->device, root_dir, alice->pipeline0_desc_set0_layout, + alice->pipeline0_desc_set1_layout = alice_create_pipeline0_desc_set1_layout(alice->device, ALICE_MAX_TEXTURES_COUNT); + alice->pipeline_hands_0a = create_graphics_pipeline_0a(alice->device, root_dir, + alice->pipeline0_desc_set0_layout, alice->pipeline0_desc_set1_layout, alice->render_pass_0, 0); alice->pipeline_hands_0b = create_graphics_pipeline_0b(alice->device, root_dir, alice->pipeline0_desc_set0_layout, alice->render_pass_0, 0); @@ -1866,6 +1595,8 @@ Alice* Alice_new(){ alice->pipeline0_light_conf.point_lights.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 1000); alice->pipeline0_light_conf.point_lights.device_local = MargaretBufAllocator_alloc(alice->storage_buffer, 1000); + alice->texture_slots = VecAliceTextureSlot_new_zeroinit(ALICE_MAX_TEXTURES_COUNT); + alice->cam_info = AliceCamVerticalControl_new(); alice->rendering_config = AliceRenderConfig_new(); @@ -1902,6 +1633,259 @@ Alice* Alice_new(){ return alice; } +/* Helper function. Automatically aquires the slot */ +U32 Alice__find_free_texture_slot(Alice* alice) { + for (U32 i = 0; i < alice->texture_slots.len; i++) { + if (!alice->texture_slots.buf[i].is_some) { + return i; + } + } + abortf("Alice textures descriptor array binding ran out of descriptors.\n" + "You should either set this limit to a higher number, or wait till I implement resize\n"); +} + +void Alice__put_img_and_view_into_tex_slot(Alice* alice, U32 slot_id, MargaretTexture tex) { + assert(slot_id < alice->texture_slots.len); + assert(!alice->texture_slots.buf[slot_id].is_some); + alice->texture_slots.buf[slot_id].is_some = true; + vkUpdateDescriptorSets(alice->device, 1, &(VkWriteDescriptorSet){ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = alice->descriptor_set1_for_pipeline_0, + .dstBinding = 0, + .dstArrayElement = slot_id, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &(VkDescriptorImageInfo){ + .sampler = alice->linear_sampler, .imageView = tex.view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }, + }, 0, NULL); + alice->texture_slots.buf[slot_id].tex = tex; +} + +U32 Alice_load_r8g8b8a8_texture(Alice* alice, VecU8 texture_path) { + U32 slot_id = Alice__find_free_texture_slot(alice); + TextureDataR8G8B8A8 pixels = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&texture_path)); + VecU8_drop(texture_path); + void* tex_staging; + MargaretTexture tex = Abigail_register_new_texture(&alice->abigail, + pixels.width, pixels.height, + sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, + &tex_staging); + memcpy(tex_staging, pixels.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&pixels)); + TextureDataR8G8B8A8_drop(pixels); + + Alice__put_img_and_view_into_tex_slot(alice, slot_id, tex); + return slot_id; +} + +U32 Alice_load_r8_texture(Alice* alice, VecU8 texture_path) { + U32 slot_id = Alice__find_free_texture_slot(alice); + TextureDataR8 pixels = TextureDataR8_read_from_png_nofail(VecU8_to_span(&texture_path)); + VecU8_drop(texture_path); + void* tex_staging; + MargaretTexture tex = Abigail_register_new_texture(&alice->abigail, + pixels.width, pixels.height, + sizeof(U8), VK_FORMAT_R8_SRGB, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, + &tex_staging); + memcpy(tex_staging, pixels.pixels.buf, TextureDataR8_get_size_in_bytes(&pixels)); + TextureDataR8_drop(pixels); + + Alice__put_img_and_view_into_tex_slot(alice, slot_id, tex); + return slot_id; +} + +void Alice_delete_texture_from_slot(Alice* alice, U32 slot_id) { + assert(slot_id < alice->texture_slots.len); + assert(!alice->texture_slots.buf[slot_id].is_some); + alice->texture_slots.buf[slot_id].is_some = false; +} + +ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const GenericMeshTopology* topology, + U32 diffuse_tex_slot, U32 normal_tex_slot, U32 specular_tex_slot + ){ + ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand)); + AliceGenericMeshHand* mm = &mm_node->el; + mm->indexes = topology->indexes.len; + mm->instance_attr.count = 0; + mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 200); + mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 200); + + GenericMeshVertex* staging_vbo; + mm->vbo = Abigail_register_new_buffer(&alice->abigail, + topology->vertices.len * sizeof(GenericMeshVertex), + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, + (void**)&staging_vbo /* We return values here */); + + U32* staging_ebo; + mm->ebo = Abigail_register_new_buffer(&alice->abigail, + topology->indexes.len * sizeof(U32), + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, + (void**)&staging_ebo /* We return values here */); + + assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex)); + /* We allocated enough memory, but now it's time to actually fill staging buffers */ + /* Filling staging VBO */ + for (U64 i = 0; i < topology->vertices.len; i++) { + staging_vbo[i].base = topology->vertices.buf[i]; + } + 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; + float dv1 = A1->tex.y - A0->tex.y; + float du2 = A2->tex.x - A0->tex.x; + float dv2 = A2->tex.y - A0->tex.y; + vec3 norm = vec3_normalize(vec3_cross(dp1, dp2)); + mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2( + mat2_inverse(mat2_new(du1, dv1, du2, dv2)), + mat2x3_transpose((mat2x3){.x = dp1, .y = dp2}) + )); + staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm; + staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x; + staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y; + } + /* Filling EBO is easy */ + assert(topology->indexes.len == mm->indexes); + size_t ebo_len = topology->indexes.len * sizeof(U32); + memcpy(staging_ebo, topology->indexes.buf, ebo_len); + + mm->diffuse_tex_slot = diffuse_tex_slot; + mm->normal_tex_slot = normal_tex_slot; + mm->specular_tex_slot = specular_tex_slot; + + ListAliceGenericMeshHand_insert_node(&alice->generic_models, mm_node); + return mm_node; +} + +ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTopology* topology){ + ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand)); + AliceShinyMeshHand* mm = &mm_node->el; + + mm->indexes = topology->indexes.len; + + mm->instance_attr.count = 0; + mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 128); + mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 128); + + ShinyMeshVertex* staging_vbo; + mm->vbo = Abigail_register_new_buffer(&alice->abigail, + topology->vertices.len * sizeof(ShinyMeshVertex), + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, + (void**)&staging_vbo); + + U32* staging_ebo; + mm->ebo = Abigail_register_new_buffer(&alice->abigail, + topology->indexes.len * sizeof(U32), + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, + (void**)&staging_ebo); + + assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex)); + /* We allocated enough memory, now it's time to actually fill staging buffers */ + /* And we start by filling staging VBO */ + for (U64 i = 0; i < topology->vertices.len; i++) { + staging_vbo[i].base = topology->vertices.buf[i]; + } + 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]; + vec3 p0 = VecShinyMeshVertexInc_at(&topology->vertices, v0)->pos; + vec3 p1 = VecShinyMeshVertexInc_at(&topology->vertices, v1)->pos; + vec3 p2 = VecShinyMeshVertexInc_at(&topology->vertices, v2)->pos; + vec3 norm = vec3_normalize(vec3_cross(vec3_minus_vec3(p1, p0), vec3_minus_vec3(p2, p0))); + staging_vbo[v0].normal = staging_vbo[v1].normal = staging_vbo[v2].normal = norm; + } + + /* Filling staging EBO is super-duper easy */ + assert(topology->indexes.len == mm->indexes); + size_t ebo_len = topology->indexes.len * sizeof(U32); + memcpy(staging_ebo, topology->indexes.buf, ebo_len); + + ListAliceShinyMeshHand_insert_node(&alice->shiny_models, mm_node); + return mm_node; +} + +// todo: write deletion after I separate textures from Meshes +void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) { + AliceGenericMeshHand* mm = &hand->el; + MargaretBufAllocator_free(alice->dev_local_buffers, mm->vbo); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->ebo); + + MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); + // todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture. + // todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would + // todo: be primitive again, without stupid crap + ListAliceGenericMeshHand_erase_by_it(&alice->generic_models, hand); +} + +/* Be careful to only delete meshes when you actually allowed to do so */ +void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) { + AliceShinyMeshHand* mm = &hand->el; + MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.vbo); + MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.ebo); + + MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); + ListAliceShinyMeshHand_erase_by_it(&alice->shiny_models, hand); +} + + +void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand* self, U64 new_count){ + U64 needed_length = new_count * sizeof(GenericMeshInstance); + if (self->instance_attr.staging.len < needed_length) { + printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n", + self->instance_attr.staging.len, needed_length); + MargaretBufAllocator_expand_or_move_old_host_visible( + alice->staging_buffers, &self->instance_attr.staging, needed_length); + } + self->instance_attr.count = new_count; +} + +void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){ + U64 needed_length = new_count * sizeof(ShinyMeshInstance); + if (self->instance_attr.staging.len < needed_length) { + MargaretBufAllocator_expand_or_move_old_host_visible( + alice->staging_buffers, &self->instance_attr.staging, needed_length); + } + self->instance_attr.count = new_count; +} + +void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){ + assert(instance < self->instance_attr.count); + GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); + staging[instance].base = uncomp; + mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); + staging[instance].normal_t = mat3_new( + tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, + tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, + tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); +} + +void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){ + assert(instance < self->instance_attr.count); + ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); + staging[instance].base = uncomp; + mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); + staging[instance].normal_t = mat3_new( + tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, + tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, + tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); +} + void Alice_set_point_light_count(Alice* alice, U32 new_count){ check(new_count < 1000000); Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_light_conf.num_ubo_staging); @@ -1922,6 +1906,8 @@ void Alice_set_point_light(Alice* alice, U32 index, Pipeline0PointLight data){ arr[index] = data; } + + /* This function actually consumes alice handler. Alice must not be used after */ void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { alice->callbacks.on_wl_pointer_button = callbacks->on_wl_pointer_button, diff --git a/src/l3/r4/r4.c b/src/l3/r4/r4.c index 91acb83..ce44e8e 100644 --- a/src/l3/r4/r4.c +++ b/src/l3/r4/r4.c @@ -85,6 +85,10 @@ typedef struct{ RBTreeNodeLucyFaceFixedSize* font_face_of_size_40; vec3 hero_pos; + U32 ROA_diffuse_tex_slot; + U32 ROA_normal_tex_slot; + U32 ROA_specular_tex_slot; + ListNodeAliceGenericMeshHand* ROA_mesh; GenericMeshTopology ROA_topology; RigidBodyState ROA_state; @@ -335,12 +339,13 @@ void run_app(){ VecU8 ROA_mesh_path = vcstr("./gen/l2/models/log_10_2_6.AliceGenericMesh"); st.ROA_topology = alice_expect_read_generic_mesh_from_file(ROA_mesh_path); + st.ROA_diffuse_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_diffuse.png")); + st.ROA_normal_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png")); + st.ROA_specular_tex_slot = Alice_load_r8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_specular.png")); + st.ROA_mesh = Alice_add_generic_mesh(st.alice, &st.ROA_topology, - (AliceGenericMeshTexturePaths){ - .diffuse_texture_path = vcstr("./src/l3/textures/log_10_2_6_diffuse.png"), - .normal_texture_path = vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"), - .specular_texture_path = vcstr("./src/l3/textures/log_10_2_6_specular.png") - }); + st.ROA_diffuse_tex_slot, st.ROA_normal_tex_slot, st.ROA_specular_tex_slot); + AliceGenericMeshHand_resize_instance_arr(st.alice, &st.ROA_mesh->el, 1); const float gamma_l_c = 4.f / 3 / M_PIf; st.ROA_state = (RigidBodyState){ diff --git a/src/l_adele/alice/0gen/0gen.frag b/src/l_adele/alice/0gen/0gen.frag index 4008500..517f64d 100644 --- a/src/l_adele/alice/0gen/0gen.frag +++ b/src/l_adele/alice/0gen/0gen.frag @@ -1,4 +1,6 @@ -#version 450 +#version 460 + +#extension GL_EXT_nonuniform_qualifier : require layout(location = 0) in vec3 tang_norm; layout(location = 1) in vec3 tang_U; @@ -6,15 +8,15 @@ layout(location = 2) in vec3 tang_V; layout(location = 3) in vec2 tex; layout(location = 4) in vec3 pos; -/* Right now all in set 0 */ layout(location = 0) out vec4 fin_color; -/* Yes, even these guys */ -layout(set = 1, binding = 0) uniform sampler2D color_tex; -layout(set = 1, binding = 1) uniform sampler2D normal_map; -layout(set = 1, binding = 2) uniform sampler2D specular_map; + +layout(set = 1, binding = 0) uniform sampler2D textures[]; layout(push_constant, std430) uniform pc { layout(offset = 64) vec3 camera_pos; + uint diffuse_tex_slot; + uint normal_tex_slot; + uint specular_tex_slot; }; struct PointLight { @@ -43,7 +45,10 @@ float get_intensity(float dist){ } void main(){ - vec3 compressed_normal = texture(normal_map, tex).xyz; + vec3 compressed_normal = texture(textures[nonuniformEXT(normal_tex_slot)], tex).xyz; + vec3 natural_color = texture(textures[nonuniformEXT(diffuse_tex_slot)], tex).xyz; + float specular_c = texture(textures[nonuniformEXT(specular_tex_slot)], tex).x; + vec3 correct_norm_on_tang = compressed_normal * 2 - 1; vec3 norm = normalize(mat3(tang_U, tang_norm, tang_V) * correct_norm_on_tang); vec3 diffuse_illumination = vec3(0); @@ -63,8 +68,7 @@ void main(){ //for (int i = 0; i < spotlight_count; i++) { // Pipeline0Spotlight lamp = spotlight_arr[i]; //} - vec3 natural_color = texture(color_tex, tex).xyz; - float specular_c = texture(specular_map, tex).x; + vec3 color = natural_color * diffuse_illumination + specular_c * specular_illumination; fin_color = vec4(color, 1); }