From cf07788d74c6b23f2da30f90ba9ee7b04b7f1136 Mon Sep 17 00:00:00 2001 From: xiangsilian Date: Sun, 21 Sep 2025 19:05:18 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=BB=E7=BA=BF=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=86=99=E5=AE=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samples/api/texture_loading/CMakeLists.txt | 2 + .../api/texture_loading/texture_loading.cpp | 272 +++++++++++++++++- samples/api/texture_loading/texture_loading.h | 15 + 3 files changed, 283 insertions(+), 6 deletions(-) diff --git a/samples/api/texture_loading/CMakeLists.txt b/samples/api/texture_loading/CMakeLists.txt index ab43932..2403f27 100644 --- a/samples/api/texture_loading/CMakeLists.txt +++ b/samples/api/texture_loading/CMakeLists.txt @@ -32,6 +32,8 @@ add_sample_with_tags( "texture_loading/glsl/bg.frag" "texture_loading/glsl/pointcloud.vert" "texture_loading/glsl/pointcloud.frag" + "texture_loading/glsl/point_line.vert" + "texture_loading/glsl/point_line.frag" SHADER_FILES_HLSL "texture_loading/hlsl/texture.vert.hlsl" "texture_loading/hlsl/texture.frag.hlsl") \ No newline at end of file diff --git a/samples/api/texture_loading/texture_loading.cpp b/samples/api/texture_loading/texture_loading.cpp index fdcc76c..bc303be 100644 --- a/samples/api/texture_loading/texture_loading.cpp +++ b/samples/api/texture_loading/texture_loading.cpp @@ -40,19 +40,23 @@ TextureLoading::~TextureLoading() vkDestroyPipeline(get_device().get_handle(), pipelines.solid, nullptr); vkDestroyPipeline(get_device().get_handle(), pipelines.background, nullptr); vkDestroyPipeline(get_device().get_handle(), pipelines.point, nullptr); + vkDestroyPipeline(get_device().get_handle(), pipelines.line, nullptr); vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr); vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_bg, nullptr); vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_point, nullptr); + vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_point_line, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_bg, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_point, nullptr); + vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_point_line, nullptr); } destroy_texture(texture); destroy_texture(texture_point); + destroy_texture(texture_point_line); destroy_texture(cam_text); vertex_buffer.reset(); @@ -580,7 +584,8 @@ void TextureLoading::build_command_buffers() //vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0); - draw_point_cloud(draw_cmd_buffers[i]); + //draw_point_cloud(draw_cmd_buffers[i]); + draw_point_cloud_line(draw_cmd_buffers[i]); //draw_ui(draw_cmd_buffers[i]); @@ -658,8 +663,8 @@ void TextureLoading::setup_descriptor_pool() // Example uses one ubo and one image sampler std::vector pool_sizes = { - vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4) }; + vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 6), + vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) }; VkDescriptorPoolCreateInfo descriptor_pool_create_info = vkb::initializers::descriptor_pool_create_info( @@ -866,6 +871,77 @@ void TextureLoading::setup_descriptor_set_point() vkUpdateDescriptorSets(get_device().get_handle(), static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); } + +void TextureLoading::setup_descriptor_set_layout_point_line() +{ + std::vector set_layout_bindings = + { + // Binding 0 : Vertex shader uniform buffer + vkb::initializers::descriptor_set_layout_binding( + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + VK_SHADER_STAGE_VERTEX_BIT, + 0), + // Binding 1 : Fragment shader image sampler + vkb::initializers::descriptor_set_layout_binding( + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + VK_SHADER_STAGE_FRAGMENT_BIT, + 1) + }; + + VkDescriptorSetLayoutCreateInfo descriptor_layout = + vkb::initializers::descriptor_set_layout_create_info( + set_layout_bindings.data(), + static_cast(set_layout_bindings.size())); + + VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout_point_line)); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info = + vkb::initializers::pipeline_layout_create_info( + &descriptor_set_layout_point_line, + 1); + + VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout_point_line)); +} + + +void TextureLoading::setup_descriptor_set_point_line() +{ + VkDescriptorSetAllocateInfo alloc_info = + vkb::initializers::descriptor_set_allocate_info( + descriptor_pool, + &descriptor_set_layout_point_line, + 1); + + VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set_point_line)); + + VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*uniform_buffer_vs_point); + + + VkDescriptorImageInfo image_descriptor; + image_descriptor.imageView = texture_point_line.view; + image_descriptor.sampler = texture_point_line.sampler; + image_descriptor.imageLayout = texture_point_line.image_layout; + + std::vector write_descriptor_sets = + { + // Binding 0 : Vertex shader uniform buffer + vkb::initializers::write_descriptor_set( + descriptor_set_point, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, + &buffer_descriptor), + // Binding 1 : Fragment shader texture sampler + // Fragment shader: layout (binding = 1) uniform sampler2D samplerColor; + vkb::initializers::write_descriptor_set( + descriptor_set_point, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // The descriptor set will use a combined image sampler (sampler and image could be split) + 1, // Shader binding point 1 + &image_descriptor) // Pointer to the descriptor image for our texture + }; + + vkUpdateDescriptorSets(get_device().get_handle(), static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); +} + // Prepare and initialize uniform buffer containing shader uniforms void TextureLoading::prepare_uniform_buffers() { @@ -901,8 +977,6 @@ void TextureLoading::prepare_uniform_buffers_point() sizeof(ubo_vs_point), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); - - update_uniform_buffers_point(60, -0.5, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 2); } @@ -1208,6 +1282,95 @@ void TextureLoading::prepare_pipeline_point() } +void TextureLoading::prepare_pipeline_point_line() +{ + + VkVertexInputBindingDescription vertex_input_binding_description{}; + vertex_input_binding_description.binding = 0; + vertex_input_binding_description.stride = sizeof(PointVertex); + vertex_input_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + std::array vertex_input_attributes = { + VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(PointVertex, x)}, + VkVertexInputAttributeDescription{1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(PointVertex, r)} + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + vertex_input_state.vertexBindingDescriptionCount = 1; + vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding_description; + vertex_input_state.vertexAttributeDescriptionCount = static_cast(vertex_input_attributes.size()); + vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); + + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; + input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + input_assembly_state.primitiveRestartEnable = VK_FALSE; + + // 光栅化 + VkPipelineRasterizationStateCreateInfo rasterization_state{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; + rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + rasterization_state.cullMode = VK_CULL_MODE_NONE; // 通常不对点进行剔除 + rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterization_state.lineWidth = 1.0f; // 可以通过 VkPhysicalDeviceFeatures::wideLines 扩展来支持更宽的线 + + // 视口和裁剪 + VkPipelineViewportStateCreateInfo viewport_state{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; + viewport_state.viewportCount = 1; + viewport_state.scissorCount = 1; + + + // 多重采样 + VkPipelineMultisampleStateCreateInfo multisample_state{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; + multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + // 深度和模板测试 (通常对点云启用深度测试) + VkPipelineDepthStencilStateCreateInfo depth_stencil_state{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + depth_stencil_state.depthTestEnable = VK_FALSE; + depth_stencil_state.depthWriteEnable = VK_FALSE; + depth_stencil_state.depthCompareOp = VK_COMPARE_OP_ALWAYS; // 或 VK_COMPARE_OP_LESS + depth_stencil_state.depthBoundsTestEnable = VK_FALSE; + depth_stencil_state.stencilTestEnable = VK_FALSE; + + // 颜色混合 (点通常不需要混合) + VkPipelineColorBlendAttachmentState blend_attachment_state{}; + blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + blend_attachment_state.blendEnable = VK_FALSE; + + VkPipelineColorBlendStateCreateInfo color_blend_state{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; + color_blend_state.attachmentCount = 1; + color_blend_state.pAttachments = &blend_attachment_state; + + // 动态状态 (视口和裁剪矩形将在命令缓冲区中设置) + std::vector dynamic_state_enables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + dynamic_state.dynamicStateCount = static_cast(dynamic_state_enables.size()); + dynamic_state.pDynamicStates = dynamic_state_enables.data(); + + // 加载着色器 + std::array shader_stages; + shader_stages[0] = load_shader("texture_loading", "point_line.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shader_stages[1] = load_shader("texture_loading", "point_line.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + // 创建图形管线 + VkGraphicsPipelineCreateInfo pipeline_create_info{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + pipeline_create_info.stageCount = static_cast(shader_stages.size()); + pipeline_create_info.pStages = shader_stages.data(); + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly_state; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pRasterizationState = &rasterization_state; + pipeline_create_info.pMultisampleState = &multisample_state; + pipeline_create_info.pDepthStencilState = &depth_stencil_state; + pipeline_create_info.pColorBlendState = &color_blend_state; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.layout = pipeline_layout_point_line; + pipeline_create_info.renderPass = render_pass; // 使用主渲染通道 + pipeline_create_info.subpass = 0; // 主子通道 + + VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &pipelines.line)); +} + + bool TextureLoading::prepare(const vkb::ApplicationOptions& options) { @@ -1231,12 +1394,20 @@ bool TextureLoading::prepare(const vkb::ApplicationOptions& options) dataSize = arrowImage.size(); processWithVulkan(arrowImage.data(), width, height, rowStride, dataSize, texture_point); + width = 256; + height = 256; + rowStride = width * 4; + auto lineImage = generateSimpleTestImage(width, height, 80); + dataSize = lineImage.size(); + processWithVulkan(lineImage.data(), width, height, rowStride, dataSize, texture_point_line); + load_texture(); generate_quad(); prepare_uniform_buffers(); prepare_uniform_buffers_point(); + setup_descriptor_pool(); setup_descriptor_set_layout(); @@ -1248,9 +1419,13 @@ bool TextureLoading::prepare(const vkb::ApplicationOptions& options) setup_descriptor_set_layout_point(); setup_descriptor_set_point(); + setup_descriptor_set_layout_point_line(); + setup_descriptor_set_point_line(); + prepare_pipelines(); prepare_pipeline_bg(); prepare_pipeline_point(); + prepare_pipeline_point_line(); float z = -2.0f; float testPoint[] = { @@ -1259,13 +1434,17 @@ bool TextureLoading::prepare(const vkb::ApplicationOptions& options) 0.1,0.1,z, 0.2,0.2,z, 0.3,0.3,z, - 0.5,0.5,z, + 0,0.5,z, 1,1,z, }; int pointCount = sizeof(testPoint) / (3*4); update_point_vertex_buffer(testPoint, pointCount); + + update_point_vertex_buffer_line(testPoint, pointCount); prepared = true; + + update_uniform_buffers_point(50, -0.5, -0.5, 0, 1, 1, 1, 0, 0, 0, 0, 0, -1); //start(); return true; } @@ -1751,6 +1930,72 @@ void TextureLoading::update_point_vertex_buffer(float* pos, int pointCount) } } + +void TextureLoading::update_point_vertex_buffer_line(float* pos, int count) +{ + std::lock_guard lock(mtx_point_line); + if (count <= 0) { + point_count_line = 0; + return; // 没有点数据,无需更新 + } + + point_count_line = count; + + // 1. 准备顶点数据 + std::vector vertices(point_count); + float min_x = std::numeric_limits::max(), max_x = std::numeric_limits::lowest(); + float min_y = std::numeric_limits::max(), max_y = std::numeric_limits::lowest(); + float min_z = std::numeric_limits::max(), max_z = std::numeric_limits::lowest(); + + for (int i = 0; i < point_count; ++i) { + float x = pos[i * 3 + 0]; + float y = pos[i * 3 + 1]; + float z = pos[i * 3 + 2]; + min_x = std::min(min_x, x); max_x = std::max(max_x, x); + min_y = std::min(min_y, y); max_y = std::max(max_y, y); + min_z = std::min(min_z, z); max_z = std::max(max_z, z); + } + float range_x = max_x - min_x; + float range_y = max_y - min_y; + float range_z = max_z - min_z; + if (range_x == 0) range_x = 1.0f; // 防止除零 + if (range_y == 0) range_y = 1.0f; + if (range_z == 0) range_z = 1.0f; + + for (int i = 0; i < point_count; ++i) { + vertices[i].x = pos[i * 3 + 0]; + vertices[i].y = pos[i * 3 + 1]; + vertices[i].z = pos[i * 3 + 2]; + // 简单颜色映射 + vertices[i].r = (vertices[i].x - min_x) / range_x; + vertices[i].g = (vertices[i].y - min_y) / range_y; + vertices[i].b = (vertices[i].z - min_z) / range_z; + } + + // 2. 更新或创建顶点缓冲区 + VkDeviceSize buffer_size = sizeof(PointVertex) * point_count; + + if (!vertex_buffer_point_line || vertex_buffer_point_line->get_size() < buffer_size) { + // 如果缓冲区不存在或太小,则重新创建 + vertex_buffer_point_line.reset(); + vertex_buffer_point_line = std::make_unique(get_device(), + buffer_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VMA_MEMORY_USAGE_CPU_TO_GPU // CPU 可写,GPU 可读 + ); + } + + // 3. 将数据复制到缓冲区 + void* mapped_data = vertex_buffer_point_line->map(); + if (mapped_data) { + memcpy(mapped_data, vertices.data(), buffer_size); + vertex_buffer_point->unmap(); + } + else { + LOGE("Failed to map point vertex buffer for update."); + } +} + void TextureLoading::draw_point_cloud(VkCommandBuffer command_buffer) { if (point_count == 0 || !vertex_buffer_point) { @@ -1766,3 +2011,18 @@ void TextureLoading::draw_point_cloud(VkCommandBuffer command_buffer) vkCmdDraw(command_buffer, point_count, 1, 0, 0); // 绘制 point_count 个顶点 } +void TextureLoading::draw_point_cloud_line(VkCommandBuffer command_buffer) +{ + if (point_count_line == 0 || !vertex_buffer_point_line) { + return; // 没有点或缓冲区未准备好 + } + + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.line); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_point_line, 0, 1, &descriptor_set_point_line, 0, nullptr); + + VkDeviceSize offsets[] = { 0 }; + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffer_point_line->get(), offsets); + + vkCmdDraw(command_buffer, point_count_line, 1, 0, 0); // 绘制 point_count 个顶点 +} + diff --git a/samples/api/texture_loading/texture_loading.h b/samples/api/texture_loading/texture_loading.h index 8a49058..d83d2fd 100644 --- a/samples/api/texture_loading/texture_loading.h +++ b/samples/api/texture_loading/texture_loading.h @@ -56,6 +56,7 @@ public: Texture texture = { 0 }; Texture texture_point = { 0 }; + Texture texture_point_line = { 0 }; Texture cam_text = { 0 }; std::unique_ptr vertex_buffer; @@ -65,6 +66,9 @@ public: std::unique_ptr vertex_buffer_point; uint32_t point_count = 0; + std::unique_ptr vertex_buffer_point_line; + uint32_t point_count_line = 0; + struct { glm::mat4 projection; @@ -92,20 +96,24 @@ public: VkPipeline solid; VkPipeline background; VkPipeline point; + VkPipeline line; } pipelines; VkPipelineLayout pipeline_layout; VkPipelineLayout pipeline_layout_bg; VkPipelineLayout pipeline_layout_point; + VkPipelineLayout pipeline_layout_point_line; VkDescriptorSet descriptor_set; VkDescriptorSet descriptor_set_bg; VkDescriptorSet descriptor_set_point; + VkDescriptorSet descriptor_set_point_line; VkDescriptorSetLayout descriptor_set_layout; VkDescriptorSetLayout descriptor_set_layout_bg; VkDescriptorSetLayout descriptor_set_layout_point; + VkDescriptorSetLayout descriptor_set_layout_point_line; static TextureLoading* Get() { return this_instance; @@ -122,6 +130,7 @@ public: void draw(); void draw_point_cloud(VkCommandBuffer command_buffer); + void draw_point_cloud_line(VkCommandBuffer command_buffer); void generate_quad(); void setup_descriptor_pool(); @@ -135,6 +144,9 @@ public: void setup_descriptor_set_layout_point(); void setup_descriptor_set_point(); + void setup_descriptor_set_layout_point_line(); + void setup_descriptor_set_point_line(); + void prepare_uniform_buffers(); void update_uniform_buffers(); @@ -145,6 +157,7 @@ public: void prepare_pipelines(); void prepare_pipeline_bg(); void prepare_pipeline_point(); + void prepare_pipeline_point_line(); bool prepare(const vkb::ApplicationOptions& options) override; @@ -163,6 +176,7 @@ public: public: void update_point_vertex_buffer(float* pos, int pointCount); + void update_point_vertex_buffer_line(float* pos, int pointCount_line); private: std::thread workerThread; bool running = false; @@ -172,6 +186,7 @@ public: //void start(); std::mutex mtx; std::mutex mtx_point; + std::mutex mtx_point_line; std::mutex mtx_mvp; //void stop(); //void updateTexture();