#include "FaceApp.h" #include "hardcode_data.h" #include #include #include #include FaceApp* FaceApp::faceIns = nullptr; FaceApp::FaceApp(/* args */) { faceIns = this; } FaceApp::~FaceApp() { } void ReceiveFacePoint(float* pos, int pointCount, int width, int height) { FaceApp* self = FaceApp::Get(); if (self != nullptr) { FaceApp::Get()->update_face_vertex_buffer(pos, pointCount); } } // 定义帧数据结构 struct FrameData { uint8_t* data; int width; int height; int rowStride; size_t dataSize; FrameData(uint8_t* d, int w, int h, int rs, size_t ds) : data(nullptr), width(w), height(h), rowStride(rs), dataSize(ds) { // 深拷贝数据 if (d && ds > 0) { data = new uint8_t[dataSize]; memcpy(data, d, dataSize); } } ~FrameData() { if (data) { delete[] data; data = nullptr; } } // 禁止拷贝构造和赋值(使用移动语义) FrameData(const FrameData&) = delete; FrameData& operator=(const FrameData&) = delete; // 移动构造 FrameData(FrameData&& other) noexcept : data(other.data), width(other.width), height(other.height), rowStride(other.rowStride), dataSize(other.dataSize) { other.data = nullptr; } // 移动赋值 FrameData& operator=(FrameData&& other) noexcept { if (this != &other) { if (data) delete[] data; data = other.data; width = other.width; height = other.height; rowStride = other.rowStride; dataSize = other.dataSize; other.data = nullptr; } return *this; } }; // 全局队列和互斥锁 std::queue frameQueue; std::mutex queueMutex; const int MAX_QUEUE_SIZE = 4; void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize) { if (!FaceApp::Get()->isInited()) { return; } std::lock_guard lock(queueMutex); // 添加新帧数据到队列 frameQueue.emplace(data, width, height, rowStride, dataSize); // 如果队列大小达到阈值,开始处理最旧的一帧 if (frameQueue.size() >= MAX_QUEUE_SIZE) { Texture& tex_bg = FaceApp::Get()->tex_bg; FrameData& oldestFrame = frameQueue.front(); FaceApp::Get()->processWithVulkan( oldestFrame.data, oldestFrame.width, oldestFrame.height, oldestFrame.rowStride, oldestFrame.dataSize, tex_bg, false ); frameQueue.pop(); } } bool FaceApp::LoadOBJ(const std::string& filename, std::vector& vertices, std::vector& indices) { // 临时存储从OBJ文件读取的原始数据 std::vector temp_positions; std::vector temp_texcoords; std::vector temp_normals; // 用于处理顶点索引 std::vector vertexIndices, uvIndices, normalIndices; std::vector data = readFile(filename); // 将 vector 转换为以 null 结尾的字符串(安全做法) std::string content(data.begin(), data.end()); std::istringstream iss(content); // 用字符串创建字符串流 std::string line; while (std::getline(iss, line)) { // 跳过空行和注释行 if (line.empty() || line[0] == '#') { continue; } std::istringstream iss(line); std::string type; iss >> type; if (type == "v") { // 顶点位置 float x, y, z; iss >> x >> y >> z; temp_positions.push_back(x); temp_positions.push_back(y); temp_positions.push_back(z); } else if (type == "vt") { // 纹理坐标 float u, v; iss >> u >> v; temp_texcoords.push_back(u); temp_texcoords.push_back(1 - v); } else if (type == "vn") { // 法线 float nx, ny, nz; iss >> nx >> ny >> nz; temp_normals.push_back(nx); temp_normals.push_back(ny); temp_normals.push_back(nz); } else if (type == "f") { // 面(三角形) std::string vertex1, vertex2, vertex3; iss >> vertex1 >> vertex2 >> vertex3; // 处理每个顶点的索引 for (const std::string& vertex : { vertex1, vertex2, vertex3 }) { std::istringstream viss(vertex); std::string v, vt, vn; // 解析顶点索引格式:v/vt/vn 或 v//vn 或 v std::getline(viss, v, '/'); std::getline(viss, vt, '/'); std::getline(viss, vn, '/'); int posIndex = std::stoi(v) - 1; // OBJ索引从1开始 int texIndex = -1, normIndex = -1; if (!vt.empty()) texIndex = std::stoi(vt) - 1; if (!vn.empty()) normIndex = std::stoi(vn) - 1; vertexIndices.push_back(posIndex); uvIndices.push_back(texIndex); normalIndices.push_back(normIndex); } } } // 创建顶点数据 vertices.clear(); indices.clear(); // 用于去重的哈希映射 std::map vertexMap; for (size_t i = 0; i < vertexIndices.size(); i++) { int posIndex = vertexIndices[i]; int texIndex = uvIndices[i]; int normIndex = normalIndices[i]; // 创建唯一标识符 std::string vertexKey = std::to_string(posIndex) + "/" + std::to_string(texIndex) + "/" + std::to_string(normIndex); // 检查是否已经存在相同的顶点 if (vertexMap.find(vertexKey) != vertexMap.end()) { // 使用现有顶点的索引 indices.push_back(vertexMap[vertexKey]); } else { // 创建新顶点 TextureLoadingVertexStructure vertex; // 设置位置 if (posIndex >= 0 && posIndex * 3 + 2 < temp_positions.size()) { vertex.pos[0] = temp_positions[posIndex * 3]; vertex.pos[1] = temp_positions[posIndex * 3 + 1]; vertex.pos[2] = temp_positions[posIndex * 3 + 2]; } else { vertex.pos[0] = vertex.pos[1] = vertex.pos[2] = 0.0f; } // 设置纹理坐标 if (texIndex >= 0 && texIndex * 2 + 1 < temp_texcoords.size()) { vertex.uv[0] = temp_texcoords[texIndex * 2]; vertex.uv[1] = temp_texcoords[texIndex * 2 + 1]; } else { vertex.uv[0] = vertex.uv[1] = 0.0f; } // 设置法线 if (normIndex >= 0 && normIndex * 3 + 2 < temp_normals.size()) { vertex.normal[0] = temp_normals[normIndex * 3]; vertex.normal[1] = temp_normals[normIndex * 3 + 1]; vertex.normal[2] = temp_normals[normIndex * 3 + 2]; } else { vertex.normal[0] = vertex.normal[1] = 0.0f; vertex.normal[2] = 1.0f; // 默认法线 } // 添加新顶点并记录索引 uint32_t newIndex = static_cast(vertices.size()); vertices.push_back(vertex); indices.push_back(newIndex); obj_vertices_map[newIndex] = posIndex; vertexMap[vertexKey] = newIndex; } } return true; } void FaceApp::create_face_pipelines() { VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; input_assembly_state.flags = 0; input_assembly_state.primitiveRestartEnable = VK_FALSE; VkPipelineRasterizationStateCreateInfo rasterization_state{}; rasterization_state.sType = 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.flags = 0; rasterization_state.depthClampEnable = VK_FALSE; rasterization_state.lineWidth = 1.0f; rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; VkPipelineColorBlendAttachmentState colorBlendAttachment{}; colorBlendAttachment.blendEnable = VK_TRUE; colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; // 常用的Alpha混合公式 colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; VkPipelineColorBlendStateCreateInfo colorBlending{}; colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlending.logicOpEnable = VK_FALSE; colorBlending.attachmentCount = 1; colorBlending.pAttachments = &colorBlendAttachment; // Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {}; depth_stencil_state.sType = 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_GREATER; depth_stencil_state.front = depth_stencil_state.back; depth_stencil_state.back.compareOp = VK_COMPARE_OP_ALWAYS; VkPipelineViewportStateCreateInfo viewport_state{}; viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewport_state.viewportCount = 1; viewport_state.scissorCount = 1; viewport_state.flags = 0; VkPipelineMultisampleStateCreateInfo multisample_state{}; multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisample_state.flags = 0; // 动态定义视口和剪裁,暂时用不到 //std::vector dynamic_state_enables = { // VK_DYNAMIC_STATE_VIEWPORT, // VK_DYNAMIC_STATE_SCISSOR }; //VkPipelineDynamicStateCreateInfo dynamic_state{}; //dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; //dynamic_state.pDynamicStates = dynamic_state_enables.data(); //dynamic_state.dynamicStateCount = static_cast(dynamic_state_enables.size()); //dynamic_state.flags = 0; // 视口状态 VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = (float)swapChainExtent.width; viewport.height = (float)swapChainExtent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = { 0, 0 }; scissor.extent = swapChainExtent; VkPipelineViewportStateCreateInfo viewportState{}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportState.viewportCount = 1; viewportState.pViewports = &viewport; viewportState.scissorCount = 1; viewportState.pScissors = &scissor; std::vector vertShaderCode; std::vector fragShaderCode; if (kThick) { vertShaderCode = readFile("shaders/texture_thick.vert.spv"); fragShaderCode = readFile("shaders/texture_thick.frag.spv"); } else { vertShaderCode = readFile("shaders/texture.vert.spv"); fragShaderCode = readFile("shaders/texture.frag.spv"); } VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode); VkShaderModule fragShaderModule = createShaderModule(this->device, fragShaderCode); VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; vertShaderStageInfo.module = vertShaderModule; vertShaderStageInfo.pName = "main"; VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; fragShaderStageInfo.module = fragShaderModule; fragShaderStageInfo.pName = "main"; VkPipelineShaderStageCreateInfo shader_stages[] = { vertShaderStageInfo, fragShaderStageInfo }; // Vertex bindings and attributes std::vector vertex_input_bindings{};; VkVertexInputBindingDescription vertex_input_binding_description{}; vertex_input_binding_description.binding = 0; vertex_input_binding_description.stride = sizeof(TextureLoadingVertexStructure); vertex_input_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; vertex_input_bindings.push_back(vertex_input_binding_description); std::vector vertex_input_attributes{}; VkVertexInputAttributeDescription viaPos{}; viaPos.location = 0; viaPos.binding = 0; viaPos.format = VK_FORMAT_R32G32B32_SFLOAT; viaPos.offset = offsetof(TextureLoadingVertexStructure, pos); vertex_input_attributes.push_back(viaPos); VkVertexInputAttributeDescription viaUv{}; viaUv.location = 1; viaUv.binding = 0; viaUv.format = VK_FORMAT_R32G32_SFLOAT; viaUv.offset = offsetof(TextureLoadingVertexStructure, uv); vertex_input_attributes.push_back(viaUv); VkVertexInputAttributeDescription viaNormal{}; viaNormal.location = 2; viaNormal.binding = 0; viaNormal.format = VK_FORMAT_R32G32B32_SFLOAT; viaNormal.offset = offsetof(TextureLoadingVertexStructure, normal); vertex_input_attributes.push_back(viaNormal); VkPipelineVertexInputStateCreateInfo vertex_input_state{}; vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertex_input_state.vertexBindingDescriptionCount = static_cast(vertex_input_bindings.size()); vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); vertex_input_state.vertexAttributeDescriptionCount = static_cast(vertex_input_attributes.size()); vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); VkGraphicsPipelineCreateInfo pipeline_create_info{}; pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipeline_create_info.layout = m_pipelineLayout; pipeline_create_info.renderPass = renderPass; pipeline_create_info.flags = 0; pipeline_create_info.basePipelineIndex = -1; pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_create_info.pVertexInputState = &vertex_input_state; pipeline_create_info.pInputAssemblyState = &input_assembly_state; pipeline_create_info.pRasterizationState = &rasterization_state; pipeline_create_info.pColorBlendState = &colorBlending; //&color_blend_state; pipeline_create_info.pMultisampleState = &multisample_state; pipeline_create_info.pViewportState = &viewport_state; pipeline_create_info.pDepthStencilState = &depth_stencil_state; //pipeline_create_info.pDynamicState = &dynamic_state; pipeline_create_info.pViewportState = &viewportState; pipeline_create_info.stageCount = 2; pipeline_create_info.pStages = shader_stages; VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &m_graphicsPipeline)); } void FaceApp::setup_descriptor_pool() { // 保守估计:假设每个描述符集可能有多个绑定 const uint32_t setsCount = kMaxTexture; const uint32_t multiplier = 3; // 安全系数 std::vector pool_sizes = { { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = setsCount * multiplier }, { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = setsCount * multiplier }, // 如果需要其他类型的描述符,在这里添加 }; VkDescriptorPoolCreateInfo descriptor_pool_info{}; descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptor_pool_info.poolSizeCount = static_cast(pool_sizes.size()); descriptor_pool_info.pPoolSizes = pool_sizes.data(); descriptor_pool_info.maxSets = setsCount * 2; // 额外预留一些集合 descriptor_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool)); } void FaceApp::setup_descriptor_set_layout() { VkDescriptorSetLayoutBinding set_layout_binding_vertex{}; set_layout_binding_vertex.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; set_layout_binding_vertex.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; set_layout_binding_vertex.binding = 0; set_layout_binding_vertex.descriptorCount = 1; VkDescriptorSetLayoutBinding set_layout_binding_fragment{}; set_layout_binding_fragment.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; set_layout_binding_fragment.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; set_layout_binding_fragment.binding = 1; set_layout_binding_fragment.descriptorCount = 1; if (kThick) { // 添加第二个纹理绑定点 VkDescriptorSetLayoutBinding set_layout_binding_fragment1{}; set_layout_binding_fragment1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; set_layout_binding_fragment1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; set_layout_binding_fragment1.binding = 2; set_layout_binding_fragment1.descriptorCount = 1; std::vector set_layout_bindings{ set_layout_binding_vertex , set_layout_binding_fragment, set_layout_binding_fragment1 }; VkDescriptorSetLayoutCreateInfo descriptor_layout{}; descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptor_layout.pBindings = set_layout_bindings.data(); descriptor_layout.bindingCount = static_cast(set_layout_bindings.size()); VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout)); } else { std::vector set_layout_bindings{ set_layout_binding_vertex , set_layout_binding_fragment }; VkDescriptorSetLayoutCreateInfo descriptor_layout{}; descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptor_layout.pBindings = set_layout_bindings.data(); descriptor_layout.bindingCount = static_cast(set_layout_bindings.size()); VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout)); } VkPipelineLayoutCreateInfo pipeline_layout_create_info{}; pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_create_info.setLayoutCount = 1; pipeline_layout_create_info.pSetLayouts = &m_descriptorSetLayout; VkPushConstantRange pushConstantRange{}; pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; pushConstantRange.offset = 0; pushConstantRange.size = sizeof(float); pipeline_layout_create_info.pushConstantRangeCount = 1; pipeline_layout_create_info.pPushConstantRanges = &pushConstantRange; VK_CHECK(vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &m_pipelineLayout)); } void FaceApp::setup_descriptor_set() { m_descriptor_sets.resize(kMaxTexture); std::vector layouts(kMaxTexture, m_descriptorSetLayout); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = descriptor_pool; alloc_info.pSetLayouts = layouts.data(); alloc_info.descriptorSetCount = m_descriptor_sets.size(); VK_CHECK(vkAllocateDescriptorSets(device, &alloc_info, m_descriptor_sets.data())); for (int i = 0; i < kMaxTexture; ++i) { VkDescriptorBufferInfo buffer_descriptor{}; buffer_descriptor.buffer = uniform_buffer_vs; buffer_descriptor.range = VK_WHOLE_SIZE; buffer_descriptor.offset = 0; VkDescriptorImageInfo image_descriptor; image_descriptor.imageView = m_texs[i].view; image_descriptor.sampler = m_texs[i].sampler; image_descriptor.imageLayout = m_texs[i].image_layout; VkWriteDescriptorSet write_descriptor_set_uniform{}; write_descriptor_set_uniform.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptor_set_uniform.dstSet = m_descriptor_sets[i]; write_descriptor_set_uniform.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; write_descriptor_set_uniform.dstBinding = 0; write_descriptor_set_uniform.pBufferInfo = &buffer_descriptor; write_descriptor_set_uniform.descriptorCount = 1; VkWriteDescriptorSet write_descriptor_set_image{}; write_descriptor_set_image.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptor_set_image.dstSet = m_descriptor_sets[i]; write_descriptor_set_image.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write_descriptor_set_image.dstBinding = 1; write_descriptor_set_image.pImageInfo = &image_descriptor; write_descriptor_set_image.descriptorCount = 1; if (kThick) { // 第二个纹理描述符 - 假设你的第二个纹理变量名为 tex_demo1 VkDescriptorImageInfo image_descriptor1; image_descriptor1.imageView = m_texs_ex[i].view; image_descriptor1.sampler = m_texs_ex[i].sampler; image_descriptor1.imageLayout = m_texs_ex[i].image_layout; // 添加第二个纹理的写入描述符 VkWriteDescriptorSet write_descriptor_set_image1{}; write_descriptor_set_image1.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptor_set_image1.dstSet = m_descriptor_sets[i]; write_descriptor_set_image1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write_descriptor_set_image1.dstBinding = 2; // 绑定到位置2 write_descriptor_set_image1.pImageInfo = &image_descriptor1; write_descriptor_set_image1.descriptorCount = 1; std::vector write_descriptor_sets = { write_descriptor_set_uniform, write_descriptor_set_image, write_descriptor_set_image1, // 添加第二个纹理 }; vkUpdateDescriptorSets(device, static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); } else { std::vector write_descriptor_sets = { write_descriptor_set_uniform, write_descriptor_set_image, }; vkUpdateDescriptorSets(device, static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); } } } void FaceApp::render(VkCommandBuffer commandBuffer, long long frameTime) { static long long game_time = 0; game_time += frameTime; long long actionTime = (1000 / _initArg.action_fps); if (game_time > actionTime) { _curTexIndex++; if (_curTexIndex >= _curMotion.png_num) { _curTexIndex = 0; } game_time = game_time - actionTime; } std::unique_lock lock(mtx); std::unique_lock lock_point(mtx_point); //Application::render(commandBuffer); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout_bg, 0, 1, &m_descriptor_set_bg, 0, NULL); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline_bg); vkCmdPushConstants(commandBuffer, m_pipelineLayout_bg, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &myFloatValue); vkCmdDraw(commandBuffer, 6, 1, 0, 0); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_sets[_curTexIndex], 0, NULL); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); vkCmdPushConstants(commandBuffer, m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &myFloatValue); VkDeviceSize offsets[1] = { 0 }; VkBuffer vertexBuffers[] = { m_vertexBuffer }; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32); #ifdef _WIN32 vkCmdDrawIndexed(commandBuffer, obj_indices.size(), 1, 0, 0, 0); #else if (getCurrentTimeMillis() - last_update_time < 2000) { vkCmdDrawIndexed(commandBuffer, obj_indices.size(), 1, 0, 0, 0); } #endif } void FaceApp::createVmaAllocator() { //VmaAllocatorCreateInfo allocatorInfo = {}; //allocatorInfo.physicalDevice = physicalDevice; //allocatorInfo.device = device; //allocatorInfo.instance = instance; //allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0; //vmaCreateAllocator(&allocatorInfo, &allocator); // 1. 设置 Vulkan 函数指针 VmaVulkanFunctions vulkanFunctions{}; vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr; vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr; // 2. 配置 Allocator VmaAllocatorCreateInfo allocatorInfo{}; allocatorInfo.physicalDevice = physicalDevice; allocatorInfo.device = device; allocatorInfo.instance = instance; allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0; allocatorInfo.pVulkanFunctions = &vulkanFunctions; VkResult result = vmaCreateAllocator(&allocatorInfo, &allocator); } void FaceApp::initVulkan() { Application::initVulkan(); createVmaAllocator(); LoadOBJ("face_picture_3dmax.obj", obj_vertices, obj_indices); m_texs.resize(kMaxTexture); m_texs_ex.resize(kMaxTexture); for (int i = 0; i < kMaxTexture; ++i) { loadTexture("demo0.png", m_texs[i], true); loadTexture("demo0_ex.png", m_texs_ex[i], true); } loadTexture("out.png", tex_bg, true); createVertexBuffer(); createUniformBuffer(); setup_descriptor_pool(); setup_descriptor_set_layout(); setup_descriptor_set(); create_face_pipelines(); setup_descriptor_set_layout_bg(); setup_descriptor_set_bg(); create_pipelines_bg(); uploadVertexData(); last_update_time = getCurrentTimeMillis(); changeMotion(_initArg.motion); faceAppInited = true; #if _WIN32 std::vector floatArray; std::string& str = HardCodeData::Get().face_result_point_str; std::stringstream ss(str); std::string token; while (std::getline(ss, token, ',')) { floatArray.push_back(std::stof(token)); } //ReceiveFacePoint(floatArray.data(), floatArray.size() / 3, 480, 480); #endif } void FaceApp::update_uniform_buffers() { uint32_t width = 480; uint32_t height = 480; float zoom = 2; // Vertex shader ubo_vs.projection = glm::perspective(glm::radians(60.0f), static_cast(width) / static_cast(height), 0.001f, 256.0f); glm::mat4 view_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, zoom)); ubo_vs.model = view_matrix * glm::translate(glm::mat4(1.0f), camera_pos); ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); ubo_vs.view_pos = glm::vec4(0.0f, 0.0f, -zoom, 0.0f); memcpy(uniform_buffer_mapped, &ubo_vs, sizeof(ubo_vs)); } void FaceApp::createVertexBuffer() { VkDeviceSize vertexBufferSize = sizeof(TextureLoadingVertexStructure) * obj_vertices.size(); VkDeviceSize indexBufferSize = sizeof(uint32_t) * obj_indices.size(); VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; bufferInfo.size = vertexBufferSize; bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VmaAllocationCreateInfo allocInfo = {}; allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_vertexBuffer, &m_vertexBufferAllocation, nullptr); bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_stagingBuffer, &m_stagingBufferAllocation, nullptr); bufferInfo.size = indexBufferSize; bufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_indexBuffer, &m_indexBufferAllocation, nullptr); } void FaceApp::uploadVertexData() { void* data; vmaMapMemory(allocator, m_stagingBufferAllocation, &data); memcpy(data, obj_vertices.data(), sizeof(TextureLoadingVertexStructure) * obj_vertices.size()); vmaUnmapMemory(allocator, m_stagingBufferAllocation); copyBuffer(m_stagingBuffer, m_vertexBuffer, sizeof(TextureLoadingVertexStructure) * obj_vertices.size()); vmaMapMemory(allocator, m_stagingBufferAllocation, &data); memcpy(data, obj_indices.data(), sizeof(uint32_t) * obj_indices.size()); vmaUnmapMemory(allocator, m_stagingBufferAllocation); copyBuffer(m_stagingBuffer, m_indexBuffer, sizeof(uint32_t) * obj_indices.size()); } void FaceApp::update_face_vertex_buffer(float* pos, int pointCount) { if(!isInited()) { return; } std::lock_guard lock(mtx_point); last_update_time = getCurrentTimeMillis(); for (int i = 0; i < obj_vertices.size(); ++i) { int face_index = obj_vertices_map[HardCodeData::Get().indexMap[i]]; float x = pos[face_index * 3 + 0]; float y = pos[face_index * 3 + 1]; float z = pos[face_index * 3 + 2]; obj_vertices[i].pos[0] = x; obj_vertices[i].pos[1] = y; obj_vertices[i].pos[2] = z; } calculateVertexNormals(obj_vertices, obj_indices); uploadVertexData(); } void FaceApp::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { VkCommandBuffer commandBuffer = beginSingleTimeCommands(); VkBufferCopy copyRegion = {}; copyRegion.size = size; vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); endSingleTimeCommands(commandBuffer); } VkCommandBuffer FaceApp::beginSingleTimeCommands() { VkCommandBufferAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandPool = commandPool; allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; vkBeginCommandBuffer(commandBuffer, &beginInfo); return commandBuffer; } void FaceApp::endSingleTimeCommands(VkCommandBuffer commandBuffer) { vkEndCommandBuffer(commandBuffer); VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); vkQueueWaitIdle(graphicsQueue); vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); } void FaceApp::createUniformBuffer() { VkDeviceSize bufferSize = sizeof(ubo_vs); VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; bufferInfo.size = bufferSize; bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VmaAllocationCreateInfo allocInfo = {}; allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; // 创建缓冲区和内存分配 vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &uniform_buffer_vs, &uniform_buffer_allocation, nullptr); // 映射内存以便直接写入 vmaMapMemory(allocator, uniform_buffer_allocation, &uniform_buffer_mapped); update_uniform_buffers(); } void FaceApp::create_pipelines_bg() { VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; input_assembly_state.flags = 0; input_assembly_state.primitiveRestartEnable = VK_FALSE; VkPipelineRasterizationStateCreateInfo rasterization_state{}; rasterization_state.sType = 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.flags = 0; rasterization_state.depthClampEnable = VK_FALSE; rasterization_state.lineWidth = 1.0f; VkPipelineColorBlendAttachmentState colorBlendAttachment{}; colorBlendAttachment.blendEnable = VK_FALSE; colorBlendAttachment.colorWriteMask = 0xf; VkPipelineColorBlendStateCreateInfo colorBlending{}; colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlending.attachmentCount = 1; colorBlending.pAttachments = &colorBlendAttachment; VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {}; depth_stencil_state.sType = 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_GREATER; depth_stencil_state.front = depth_stencil_state.back; depth_stencil_state.back.compareOp = VK_COMPARE_OP_ALWAYS; VkPipelineViewportStateCreateInfo viewport_state{}; viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewport_state.viewportCount = 1; viewport_state.scissorCount = 1; viewport_state.flags = 0; VkPipelineMultisampleStateCreateInfo multisample_state{}; multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisample_state.flags = 0; // 视口状态 VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = (float)swapChainExtent.width; viewport.height = (float)swapChainExtent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = { 0, 0 }; scissor.extent = swapChainExtent; VkPipelineViewportStateCreateInfo viewportState{}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportState.viewportCount = 1; viewportState.pViewports = &viewport; viewportState.scissorCount = 1; viewportState.pScissors = &scissor; auto vertShaderCode = readFile("shaders/bg.vert.spv"); auto fragShaderCode = readFile("shaders/bg.frag.spv"); VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode); VkShaderModule fragShaderModule = createShaderModule(this->device, fragShaderCode); VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; vertShaderStageInfo.module = vertShaderModule; vertShaderStageInfo.pName = "main"; VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; fragShaderStageInfo.module = fragShaderModule; fragShaderStageInfo.pName = "main"; VkPipelineShaderStageCreateInfo shader_stages[] = { vertShaderStageInfo, fragShaderStageInfo }; VkPipelineVertexInputStateCreateInfo vertex_input_state{}; vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; VkGraphicsPipelineCreateInfo pipeline_create_info{}; pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipeline_create_info.layout = m_pipelineLayout_bg; pipeline_create_info.renderPass = renderPass; pipeline_create_info.flags = 0; pipeline_create_info.basePipelineIndex = -1; pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_create_info.pVertexInputState = &vertex_input_state; pipeline_create_info.pInputAssemblyState = &input_assembly_state; pipeline_create_info.pRasterizationState = &rasterization_state; pipeline_create_info.pColorBlendState = &colorBlending; //&color_blend_state; pipeline_create_info.pMultisampleState = &multisample_state; pipeline_create_info.pViewportState = &viewport_state; pipeline_create_info.pDepthStencilState = &depth_stencil_state; //pipeline_create_info.pDynamicState = &dynamic_state; pipeline_create_info.pViewportState = &viewportState; pipeline_create_info.stageCount = 2; pipeline_create_info.pStages = shader_stages; VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &m_graphicsPipeline_bg)); } void FaceApp::setup_descriptor_set_layout_bg() { VkDescriptorSetLayoutBinding set_layout_binding{}; set_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; set_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; set_layout_binding.binding = 0; set_layout_binding.descriptorCount = 1; std::vector set_layout_bindings ={set_layout_binding }; VkDescriptorSetLayoutCreateInfo descriptor_layout{}; descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptor_layout.pBindings = set_layout_bindings.data(); descriptor_layout.bindingCount = static_cast(set_layout_bindings.size()); VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout_bg)); VkPipelineLayoutCreateInfo pipeline_layout_create_info{}; pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_create_info.setLayoutCount = 1; pipeline_layout_create_info.pSetLayouts = &m_descriptorSetLayout_bg; VkPushConstantRange pushConstantRange{}; pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // 只在片段着色器中使用 pushConstantRange.offset = 0; pushConstantRange.size = sizeof(float); // 或者 sizeof(PushConstants) pipeline_layout_create_info.pushConstantRangeCount = 1; pipeline_layout_create_info.pPushConstantRanges = &pushConstantRange; VK_CHECK(vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &m_pipelineLayout_bg)); } void FaceApp::setup_descriptor_set_bg() { VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = descriptor_pool; alloc_info.pSetLayouts = &m_descriptorSetLayout_bg; alloc_info.descriptorSetCount = 1; VK_CHECK(vkAllocateDescriptorSets(device, &alloc_info, &m_descriptor_set_bg)); VkDescriptorImageInfo image_descriptor; image_descriptor.imageView = tex_bg.view; image_descriptor.sampler = tex_bg.sampler; image_descriptor.imageLayout = tex_bg.image_layout; VkWriteDescriptorSet write_descriptor_set{}; write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptor_set.dstSet = m_descriptor_set_bg; write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write_descriptor_set.dstBinding = 0; write_descriptor_set.pImageInfo = &image_descriptor; write_descriptor_set.descriptorCount = 1; std::vector write_descriptor_sets = { write_descriptor_set }; vkUpdateDescriptorSets(device, static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); } void FaceApp::cleanup() { vkDeviceWaitIdle(device); vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyPipeline(device, m_graphicsPipeline, nullptr); vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr); //vmaUnmapMemory(allocator, m_stagingBufferAllocation); //vmaUnmapMemory(allocator, uniform_buffer_allocation); //vmaDestroyBuffer(allocator, uniform_buffer_vs, uniform_buffer_allocation); //vmaDestroyBuffer(allocator, m_indexBuffer, m_indexBufferAllocation); //vmaDestroyBuffer(allocator, m_vertexBuffer, m_vertexBufferAllocation); //vmaDestroyBuffer(allocator, m_stagingBuffer, m_stagingBufferAllocation); vkDestroyDescriptorSetLayout(device, m_descriptorSetLayout, nullptr); Application::cleanup(); } void FaceApp::SetInitArg(const char* arg) { _initArg = json::parse(arg); } void FaceApp::changeMotion(const char* json) { Motion motion = json::parse(json); changeMotion(motion); } void FaceApp::changeMotion(Motion& motion) { if (_curMotion.getMotionId() == motion.getMotionId()) { return; } _curMotion = motion; for (int i = 0; i < _curMotion.png_num; ++i) { #ifdef _WIN32 //string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type; string path = "pic"; string path_name = path + "/" + _curMotion.png_name;// +std::to_string(i) + ".png"; loadTextureExample(UTF8ToWideString(path_name), m_texs[i], true); if (kThick) { string path_name_ex = path + "/" + _curMotion.png_name + std::to_string(i) + "_thick.png"; loadTextureExample(UTF8ToWideString(path_name_ex), m_texs_ex[i], true); } #else //string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type; string path = "pic"; string path_name = path + "/" + _curMotion.png_name;// +std::to_string(i) + ".png"; loadTexture(path_name, m_texs[i], true); if (kThick) { loadTexture(path_name, m_texs_ex[i], true); } #endif // _WIN32 } }