加入渲染点的代码
This commit is contained in:
@@ -43,6 +43,15 @@ TextureLoading::~TextureLoading()
|
||||
vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_bg, nullptr);
|
||||
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_bg, nullptr);
|
||||
if (point_pipeline) {
|
||||
vkDestroyPipeline(get_device().get_handle(), point_pipeline, nullptr);
|
||||
}
|
||||
if (point_pipeline_layout) {
|
||||
vkDestroyPipelineLayout(get_device().get_handle(), point_pipeline_layout, nullptr);
|
||||
}
|
||||
if (point_descriptor_set_layout) {
|
||||
vkDestroyDescriptorSetLayout(get_device().get_handle(), point_descriptor_set_layout, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_texture(texture);
|
||||
@@ -51,6 +60,9 @@ TextureLoading::~TextureLoading()
|
||||
vertex_buffer.reset();
|
||||
index_buffer.reset();
|
||||
uniform_buffer_vs.reset();
|
||||
|
||||
|
||||
point_vertex_buffer.reset(); // BufferC 会自动清理
|
||||
//stop();
|
||||
}
|
||||
|
||||
@@ -490,14 +502,16 @@ void TextureLoading::build_command_buffers()
|
||||
vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.background);
|
||||
vkCmdDraw(draw_cmd_buffers[i], 6, 1, 0, 0);
|
||||
|
||||
vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, NULL);
|
||||
vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid);
|
||||
//vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, NULL);
|
||||
//vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid);
|
||||
|
||||
VkDeviceSize offsets[1] = { 0 };
|
||||
vkCmdBindVertexBuffers(draw_cmd_buffers[i], 0, 1, vertex_buffer->get(), offsets);
|
||||
vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32);
|
||||
//VkDeviceSize offsets[1] = { 0 };
|
||||
//vkCmdBindVertexBuffers(draw_cmd_buffers[i], 0, 1, vertex_buffer->get(), offsets);
|
||||
//vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0);
|
||||
//vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0);
|
||||
|
||||
draw_point_cloud(draw_cmd_buffers[i]);
|
||||
|
||||
draw_ui(draw_cmd_buffers[i]);
|
||||
|
||||
@@ -510,8 +524,15 @@ void TextureLoading::build_command_buffers()
|
||||
void TextureLoading::draw()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
std::unique_lock<std::mutex> lock_point(mtx_point);
|
||||
ApiVulkanSample::prepare_frame();
|
||||
|
||||
// --- 新增:在命令缓冲区中绘制点云 ---
|
||||
// 在 build_command_buffers 中已经构建了命令缓冲区,但点数据是动态的。
|
||||
// 因此,我们在这里重新记录命令缓冲区。
|
||||
// 注意:更高效的做法是使用动态顶点缓冲区或间接绘制,但对于 Demo 来说,重新记录是可以接受的。
|
||||
build_command_buffers(); // 重新构建所有命令缓冲区以包含最新的点云
|
||||
|
||||
// Command buffer to be submitted to the queue
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
|
||||
@@ -918,6 +939,10 @@ bool TextureLoading::prepare(const vkb::ApplicationOptions& options)
|
||||
setup_descriptor_set();
|
||||
setup_descriptor_set_bg();
|
||||
build_command_buffers();
|
||||
|
||||
setup_point_descriptor_set_layout();
|
||||
setup_point_descriptor_set();
|
||||
prepare_point_pipeline();
|
||||
prepared = true;
|
||||
//start();
|
||||
return true;
|
||||
@@ -996,6 +1021,16 @@ void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowS
|
||||
TextureLoading::Get()->processWithVulkan(data, width, height, rowStride, dataSize, cam_tex);
|
||||
}
|
||||
|
||||
void ReceiveFacePoint(float* pos, int pointCount, int width, int height)
|
||||
{
|
||||
//for (int i = 0; i < pointCount; i++) {
|
||||
// float x = pos[i * 3];
|
||||
// float y = pos[i * 3 + 1];
|
||||
// float z = pos[i * 3 + 2];
|
||||
//}
|
||||
TextureLoading::Get()->update_point_vertex_buffer(pos, pointCount);
|
||||
}
|
||||
|
||||
void TextureLoading::processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
@@ -1289,3 +1324,247 @@ void TextureLoading::transitionImageLayout(VkCommandBuffer commandBuffer, VkImag
|
||||
vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0,
|
||||
0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
|
||||
void TextureLoading::setup_point_descriptor_set_layout()
|
||||
{
|
||||
// --- 修改:为点云 UBO 创建描述符集布局绑定,指向 binding 0 ---
|
||||
VkDescriptorSetLayoutBinding ubo_layout_binding{};
|
||||
ubo_layout_binding.binding = 0; // 与着色器中的 layout(binding = 0) 匹配
|
||||
ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
ubo_layout_binding.descriptorCount = 1;
|
||||
ubo_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // 仅在顶点着色器中使用
|
||||
ubo_layout_binding.pImmutableSamplers = nullptr;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layout_info{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
layout_info.bindingCount = 1;
|
||||
layout_info.pBindings = &ubo_layout_binding; // 指向我们的 UBO 绑定
|
||||
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &layout_info, nullptr, &point_descriptor_set_layout));
|
||||
// --- 修改结束 ---
|
||||
}
|
||||
|
||||
void TextureLoading::setup_point_descriptor_set()
|
||||
{
|
||||
// --- 修改:分配点云描述符集 ---
|
||||
VkDescriptorSetAllocateInfo alloc_info{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
alloc_info.descriptorPool = descriptor_pool; // 使用您已有的描述符池
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &point_descriptor_set_layout;
|
||||
|
||||
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &point_descriptor_set));
|
||||
// --- 修改结束 ---
|
||||
|
||||
// --- 新增:更新点云描述符集,指向已有的 uniform_buffer_vs ---
|
||||
update_point_descriptor_set(); // 调用辅助函数进行更新
|
||||
// --- 新增结束 ---
|
||||
}
|
||||
|
||||
|
||||
// --- 新增:更新点云描述符集以指向 uniform_buffer_vs 的辅助函数 ---
|
||||
void TextureLoading::update_point_descriptor_set()
|
||||
{
|
||||
if (!uniform_buffer_vs) { // 检查主 UBO 缓冲区是否存在
|
||||
LOGW("Main uniform buffer (uniform_buffer_vs) not created yet, cannot update point descriptor set.");
|
||||
return;
|
||||
}
|
||||
|
||||
VkDescriptorBufferInfo buffer_info{};
|
||||
buffer_info.buffer = uniform_buffer_vs->get_handle();
|
||||
// 关键:指定要绑定的 UBO 数据在缓冲区中的范围
|
||||
// 我们绑定整个 ubo_vs,因为着色器只访问前两个 mat4,其余部分被忽略但不影响
|
||||
buffer_info.offset = 0;
|
||||
buffer_info.range = sizeof(ubo_vs); // 绑定整个结构体
|
||||
|
||||
VkWriteDescriptorSet descriptor_write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
|
||||
descriptor_write.dstSet = point_descriptor_set; // 目标描述符集
|
||||
descriptor_write.dstBinding = 0; // 目标绑定 (binding = 0)
|
||||
descriptor_write.dstArrayElement = 0; // 数组元素索引 (非数组)
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptor_write.descriptorCount = 1; // 更新一个描述符
|
||||
descriptor_write.pBufferInfo = &buffer_info; // 指向缓冲区信息
|
||||
// pImageInfo 和 pTexelBufferView 对于 Uniform Buffer 不需要
|
||||
|
||||
vkUpdateDescriptorSets(get_device().get_handle(), 1, &descriptor_write, 0, nullptr);
|
||||
}
|
||||
// --- 新增结束 ---
|
||||
|
||||
void TextureLoading::prepare_point_pipeline()
|
||||
{
|
||||
// 创建管线布局
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_create_info{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
pipeline_layout_create_info.setLayoutCount = 1;
|
||||
pipeline_layout_create_info.pSetLayouts = &point_descriptor_set_layout;
|
||||
// 没有 push constants
|
||||
pipeline_layout_create_info.pushConstantRangeCount = 0;
|
||||
pipeline_layout_create_info.pPushConstantRanges = nullptr;
|
||||
|
||||
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &point_pipeline_layout));
|
||||
|
||||
// 加载着色器
|
||||
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages;
|
||||
shader_stages[0] = load_shader("pointcloud.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
shader_stages[1] = load_shader("pointcloud.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
// 顶点输入绑定描述 (告诉 Vulkan 顶点数据的格式)
|
||||
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;
|
||||
|
||||
// 顶点输入属性描述 (告诉 Vulkan 每个属性在顶点结构中的位置)
|
||||
std::array<VkVertexInputAttributeDescription, 2> 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<uint32_t>(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_POINT_LIST; // 关键:绘制点
|
||||
input_assembly_state.primitiveRestartEnable = VK_FALSE;
|
||||
|
||||
// 视口和裁剪
|
||||
VkPipelineViewportStateCreateInfo viewport_state{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||
viewport_state.viewportCount = 1;
|
||||
viewport_state.scissorCount = 1;
|
||||
|
||||
// 光栅化
|
||||
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 扩展来支持更宽的线
|
||||
|
||||
// 多重采样
|
||||
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_TRUE;
|
||||
depth_stencil_state.depthWriteEnable = VK_TRUE;
|
||||
depth_stencil_state.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; // 或 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<VkDynamicState> 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<uint32_t>(dynamic_state_enables.size());
|
||||
dynamic_state.pDynamicStates = dynamic_state_enables.data();
|
||||
|
||||
// 创建图形管线
|
||||
VkGraphicsPipelineCreateInfo pipeline_create_info{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||
pipeline_create_info.stageCount = static_cast<uint32_t>(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 = point_pipeline_layout;
|
||||
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, &point_pipeline));
|
||||
}
|
||||
|
||||
void TextureLoading::update_point_vertex_buffer(float* pos, int pointCount)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx_point);
|
||||
if (pointCount <= 0) {
|
||||
point_count = 0;
|
||||
return; // 没有点数据,无需更新
|
||||
}
|
||||
|
||||
point_count = pointCount;
|
||||
|
||||
// 1. 准备顶点数据
|
||||
std::vector<PointVertex> vertices(point_count);
|
||||
// 假设 pos 数组是 [x0,y0,z0,x1,y1,z1,...]
|
||||
// 为了可视化,这里简单地将坐标映射为颜色 (0-1范围)
|
||||
float min_x = std::numeric_limits<float>::max(), max_x = std::numeric_limits<float>::lowest();
|
||||
float min_y = std::numeric_limits<float>::max(), max_y = std::numeric_limits<float>::lowest();
|
||||
float min_z = std::numeric_limits<float>::max(), max_z = std::numeric_limits<float>::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 (!point_vertex_buffer || point_vertex_buffer->get_size() < buffer_size) {
|
||||
// 如果缓冲区不存在或太小,则重新创建
|
||||
point_vertex_buffer.reset();
|
||||
point_vertex_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
|
||||
buffer_size,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VMA_MEMORY_USAGE_CPU_TO_GPU // CPU 可写,GPU 可读
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 将数据复制到缓冲区
|
||||
void* mapped_data = point_vertex_buffer->map();
|
||||
if (mapped_data) {
|
||||
memcpy(mapped_data, vertices.data(), buffer_size);
|
||||
point_vertex_buffer->unmap();
|
||||
}
|
||||
else {
|
||||
LOGE("Failed to map point vertex buffer for update.");
|
||||
}
|
||||
}
|
||||
|
||||
void TextureLoading::draw_point_cloud(VkCommandBuffer command_buffer)
|
||||
{
|
||||
if (point_count == 0 || !point_vertex_buffer) {
|
||||
return; // 没有点或缓冲区未准备好
|
||||
}
|
||||
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, point_pipeline);
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, point_pipeline_layout, 0, 1, &point_descriptor_set, 0, nullptr);
|
||||
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, point_vertex_buffer->get(), offsets);
|
||||
|
||||
vkCmdDraw(command_buffer, point_count, 1, 0, 0); // 绘制 point_count 个顶点
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user