diff --git a/app/src/main/assets/demo0.png b/app/src/main/assets/demo0.png index 3b1b712..c306a61 100644 Binary files a/app/src/main/assets/demo0.png and b/app/src/main/assets/demo0.png differ diff --git a/app/src/main/assets/demo0_ex.png b/app/src/main/assets/demo0_ex.png new file mode 100644 index 0000000..e8e1067 Binary files /dev/null and b/app/src/main/assets/demo0_ex.png differ diff --git a/app/src/main/assets/shaders/texture.frag b/app/src/main/assets/shaders/texture.frag index 6943e81..4b643fd 100644 --- a/app/src/main/assets/shaders/texture.frag +++ b/app/src/main/assets/shaders/texture.frag @@ -1,6 +1,7 @@ #version 450 layout (binding = 1) uniform sampler2D samplerColor; +layout (binding = 2) uniform sampler2D samplerColor_ex; layout (location = 0) in vec2 inUV; layout (location = 1) in vec3 inNormal; @@ -11,16 +12,27 @@ layout (location = 0) out vec4 outFragColor; void main() { vec4 color = texture(samplerColor, inUV); + vec4 color_ex = texture(samplerColor_ex, inUV); vec3 N = normalize(inNormal); vec4 textureColor = color; - if (textureColor.a < 0.1) { + + //if (textureColor.a < 0.1) + //{ //textureColor = vec4(0.2, 0.2, 0.2, 0.5); - discard; - } + // discard; + //} + + // 计算与 (0,0,1) 的点乘 + float ndot = dot(N, vec3(0.0, 0.0, -1.0)); + + // 保证结果 >= 0 + ndot = max(ndot, 0.0); - outFragColor = textureColor; + vec4 blendedColor = mix(color_ex, color, ndot); + + outFragColor = blendedColor; // outFragColor = vec4(1, 0, 0, 1); } \ No newline at end of file diff --git a/app/src/main/assets/shaders/texture.frag.spv b/app/src/main/assets/shaders/texture.frag.spv index dfcd420..6bbc39d 100644 Binary files a/app/src/main/assets/shaders/texture.frag.spv and b/app/src/main/assets/shaders/texture.frag.spv differ diff --git a/vulkan/AppBase.cpp b/vulkan/AppBase.cpp index 0beef78..ae9f0c8 100644 --- a/vulkan/AppBase.cpp +++ b/vulkan/AppBase.cpp @@ -335,4 +335,113 @@ void AppBase::pickPhysicalDevice(VkPhysicalDevice& physicalDevice, VkSurfaceKHR& if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } +} + + +// 璁$畻闈㈢殑娉曠嚎 +void AppBase::calculateFaceNormal(const TextureLoadingVertexStructure& v0, + const TextureLoadingVertexStructure& v1, + const TextureLoadingVertexStructure& v2, + float* outNormal) +{ + // 璁$畻涓や釜杈瑰悜閲 + float edge1[3] = { v1.pos[0] - v0.pos[0], v1.pos[1] - v0.pos[1], v1.pos[2] - v0.pos[2] }; + float edge2[3] = { v2.pos[0] - v0.pos[0], v2.pos[1] - v0.pos[1], v2.pos[2] - v0.pos[2] }; + + // 鍙夌Н璁$畻娉曠嚎 + outNormal[0] = edge1[1] * edge2[2] - edge1[2] * edge2[1]; + outNormal[1] = edge1[2] * edge2[0] - edge1[0] * edge2[2]; + outNormal[2] = edge1[0] * edge2[1] - edge1[1] * edge2[0]; + + // 褰掍竴鍖 + float length = std::sqrt(outNormal[0] * outNormal[0] + + outNormal[1] * outNormal[1] + + outNormal[2] * outNormal[2]); + + if (length > 0.0f) { + outNormal[0] /= length; + outNormal[1] /= length; + outNormal[2] /= length; + } +} + +// 璁$畻鎵鏈夐《鐐圭殑娉曠嚎 +void AppBase::calculateVertexNormals(std::vector& obj_vertices, + const std::vector& obj_indices) +{ + // 楠岃瘉绱㈠紩鏁伴噺鏄3鐨勫嶆暟 + if (obj_indices.size() % 3 != 0) { + return; // 鎴栬呮姏鍑哄紓甯 + } + + // 涓烘瘡涓《鐐瑰垱寤烘硶绾跨疮鍔犲櫒鍜岃鏁 + std::vector> normalSums(obj_vertices.size(), { 0.0f, 0.0f, 0.0f }); + std::vector normalCounts(obj_vertices.size(), 0); + + // 閬嶅巻鎵鏈変笁瑙掑舰 + for (size_t i = 0; i < obj_indices.size(); i += 3) { + uint32_t idx0 = obj_indices[i]; + uint32_t idx1 = obj_indices[i + 1]; + uint32_t idx2 = obj_indices[i + 2]; + + // 楠岃瘉绱㈠紩鏈夋晥鎬 + if (idx0 >= obj_vertices.size() || idx1 >= obj_vertices.size() || idx2 >= obj_vertices.size()) { + continue; + } + + // 鑾峰彇涓夎褰㈢殑涓変釜椤剁偣 + const auto& v0 = obj_vertices[idx0]; + const auto& v1 = obj_vertices[idx1]; + const auto& v2 = obj_vertices[idx2]; + + // 璁$畻闈㈢殑娉曠嚎 + float faceNormal[3]; + calculateFaceNormal(v0, v1, v2, faceNormal); + + // 灏嗛潰娉曠嚎绱姞鍒版瘡涓《鐐 + for (int j = 0; j < 3; j++) { + normalSums[idx0][j] += faceNormal[j]; + normalSums[idx1][j] += faceNormal[j]; + normalSums[idx2][j] += faceNormal[j]; + } + + normalCounts[idx0]++; + normalCounts[idx1]++; + normalCounts[idx2]++; + } + + // 璁$畻姣忎釜椤剁偣鐨勫钩鍧囨硶绾垮苟褰掍竴鍖 + for (size_t i = 0; i < obj_vertices.size(); i++) { + if (normalCounts[i] > 0) { + // 璁$畻骞冲潎鍊 + float avgNormal[3] = { + normalSums[i][0] / normalCounts[i], + normalSums[i][1] / normalCounts[i], + normalSums[i][2] / normalCounts[i] + }; + + // 褰掍竴鍖 + float length = std::sqrt(avgNormal[0] * avgNormal[0] + + avgNormal[1] * avgNormal[1] + + avgNormal[2] * avgNormal[2]); + + if (length > 0.0f) { + obj_vertices[i].normal[0] = avgNormal[0] / length; + obj_vertices[i].normal[1] = avgNormal[1] / length; + obj_vertices[i].normal[2] = avgNormal[2] / length; + } + else { + // 濡傛灉娉曠嚎闀垮害涓0锛岃缃负榛樿鍊 + obj_vertices[i].normal[0] = 0.0f; + obj_vertices[i].normal[1] = 1.0f; + obj_vertices[i].normal[2] = 0.0f; + } + } + else { + // 濡傛灉娌℃湁闈娇鐢ㄨ繖涓《鐐癸紝璁剧疆榛樿娉曠嚎 + obj_vertices[i].normal[0] = 0.0f; + obj_vertices[i].normal[1] = 1.0f; + obj_vertices[i].normal[2] = 0.0f; + } + } } \ No newline at end of file diff --git a/vulkan/AppBase.h b/vulkan/AppBase.h index 39a63fa..11126bc 100644 --- a/vulkan/AppBase.h +++ b/vulkan/AppBase.h @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include void VK_CHECK(VkResult ret); @@ -51,6 +54,13 @@ struct QueueFamilyIndices { } }; +struct TextureLoadingVertexStructure +{ + float pos[3]; + float uv[2]; + float normal[3]; +}; + class AppBase { public: @@ -81,6 +91,15 @@ protected: bool enableValidationLayers = true; VkDebugUtilsMessengerEXT debugMessenger; + + + // 璁$畻闈㈢殑娉曠嚎 + void calculateFaceNormal(const TextureLoadingVertexStructure& v0, const TextureLoadingVertexStructure& v1, const TextureLoadingVertexStructure& v2, float* outNormal); + + + // 璁$畻鎵鏈夐《鐐圭殑娉曠嚎 + void calculateVertexNormals(std::vector& obj_vertices, const std::vector& obj_indices); + }; #endif // VULKAN_UTILS_H \ No newline at end of file diff --git a/vulkan/FaceApp.cpp b/vulkan/FaceApp.cpp index 4781a37..b60d57f 100644 --- a/vulkan/FaceApp.cpp +++ b/vulkan/FaceApp.cpp @@ -408,7 +408,14 @@ void FaceApp::setup_descriptor_set_layout() set_layout_binding_fragment.binding = 1; set_layout_binding_fragment.descriptorCount = 1; - std::vector set_layout_bindings{ set_layout_binding_vertex , set_layout_binding_fragment}; + // 娣诲姞绗簩涓汗鐞嗙粦瀹氱偣 + 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{}; @@ -457,6 +464,12 @@ void FaceApp::setup_descriptor_set() image_descriptor.sampler = tex_demo0.sampler; image_descriptor.imageLayout = tex_demo0.image_layout; + // 绗簩涓汗鐞嗘弿杩扮 - 鍋囪浣犵殑绗簩涓汗鐞嗗彉閲忓悕涓 tex_demo1 + VkDescriptorImageInfo image_descriptor1; + image_descriptor1.imageView = tex_demo0_ex.view; + image_descriptor1.sampler = tex_demo0_ex.sampler; + image_descriptor1.imageLayout = tex_demo0_ex.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_set; @@ -474,10 +487,20 @@ void FaceApp::setup_descriptor_set() write_descriptor_set_image.pImageInfo = &image_descriptor; write_descriptor_set_image.descriptorCount = 1; + // 娣诲姞绗簩涓汗鐞嗙殑鍐欏叆鎻忚堪绗 + VkWriteDescriptorSet write_descriptor_set_image1{}; + write_descriptor_set_image1.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptor_set_image1.dstSet = m_descriptor_set; + 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_image, + write_descriptor_set_image1, // 娣诲姞绗簩涓汗鐞 }; vkUpdateDescriptorSets(device, static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); @@ -489,13 +512,13 @@ void FaceApp::render(VkCommandBuffer commandBuffer) 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); + //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); + //vkCmdPushConstants(commandBuffer, m_pipelineLayout_bg, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &myFloatValue); - vkCmdDraw(commandBuffer, 6, 1, 0, 0); + //vkCmdDraw(commandBuffer, 6, 1, 0, 0); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_set, 0, NULL); @@ -550,6 +573,8 @@ void FaceApp::initVulkan() createVmaAllocator(); LoadOBJ("face_picture_3dmax.obj", obj_vertices, obj_indices); loadTexture("demo0.png", tex_demo0, true); + loadTexture("demo0_ex.png", tex_demo0_ex, true); + loadTexture("out.png", tex_bg, false); createVertexBuffer(); createUniformBuffer(); @@ -665,7 +690,7 @@ void FaceApp::update_face_vertex_buffer(float* pos, int pointCount) obj_vertices[i].pos[1] = y; obj_vertices[i].pos[2] = z; } - + calculateVertexNormals(obj_vertices, obj_indices); uploadVertexData(); } diff --git a/vulkan/FaceApp.h b/vulkan/FaceApp.h index 0584700..927b38e 100644 --- a/vulkan/FaceApp.h +++ b/vulkan/FaceApp.h @@ -8,12 +8,7 @@ #include #include -struct TextureLoadingVertexStructure -{ - float pos[3]; - float uv[2]; - float normal[3]; -}; + struct PushConstants { float myValue; @@ -101,6 +96,7 @@ private: void createUniformBuffer(); Texture tex_demo0 = {0}; + Texture tex_demo0_ex = { 0 }; bool faceAppInited = false; float myFloatValue = 1.5f;