通议灵码修改过的。

This commit is contained in:
xsl
2025-09-14 21:52:08 +08:00
parent ef5f391ef5
commit 8e1c574122
2 changed files with 409 additions and 193 deletions
+375 -168
View File
@@ -1,13 +1,11 @@
#include "texture_loading.h"
#include "texture_loading.h"
TextureLoading* TextureLoading::loadTextIns = nullptr;
TextureLoading::TextureLoading()
{
zoom = -2.5f;
rotation = {0.0f, 15.0f, 0.0f};
title = "Texture loading";
zoom = -2.5f;
rotation = { 0.0f, 15.0f, 0.0f };
title = "Texture loading";
loadTextIns = this;
}
@@ -19,9 +17,18 @@ TextureLoading::~TextureLoading()
// Note : Inherited destructor cleans up resources stored in base class
vkDestroyPipeline(get_device().get_handle(), pipelines.solid, nullptr);
if (pipelines.background != VK_NULL_HANDLE) {
vkDestroyPipeline(get_device().get_handle(), pipelines.background, nullptr);
}
vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr);
if (pipeline_layout_bg != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_bg, nullptr);
}
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr);
if (descriptor_set_layout_bg != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_bg, nullptr);
}
}
destroy_texture(texture);
@@ -32,7 +39,7 @@ TextureLoading::~TextureLoading()
}
// Enable physical device features required for this example
void TextureLoading::request_gpu_features(vkb::PhysicalDevice &gpu)
void TextureLoading::request_gpu_features(vkb::PhysicalDevice& gpu)
{
// Enable anisotropic filtering if supported
if (gpu.get_features().samplerAnisotropy)
@@ -43,28 +50,32 @@ void TextureLoading::request_gpu_features(vkb::PhysicalDevice &gpu)
void TextureLoading::destroy_texture(Texture texture)
{
vkDestroyImageView(get_device().get_handle(), texture.view, nullptr);
vkDestroyImage(get_device().get_handle(), texture.image, nullptr);
vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr);
vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr);
if (texture.view != VK_NULL_HANDLE) vkDestroyImageView(get_device().get_handle(), texture.view, nullptr);
if (texture.image != VK_NULL_HANDLE) vkDestroyImage(get_device().get_handle(), texture.image, nullptr);
if (texture.sampler != VK_NULL_HANDLE) vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr);
if (texture.device_memory != VK_NULL_HANDLE) vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr);
// Reset struct
texture = { 0 };
}
void TextureLoading::build_command_buffers()
{
VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();
// 注意:深度缓冲区清除值改为 1.0f (最远)
VkClearValue clear_values[2];
clear_values[0].color = default_clear_color;
clear_values[1].depthStencil = {0.0f, 0};
clear_values[0].color = default_clear_color;
clear_values[1].depthStencil = { 1.0f, 0 }; // 使用 1.0f 作为深度清除值
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
render_pass_begin_info.renderPass = render_pass;
render_pass_begin_info.renderArea.offset.x = 0;
render_pass_begin_info.renderArea.offset.y = 0;
render_pass_begin_info.renderArea.extent.width = width;
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
render_pass_begin_info.renderPass = render_pass;
render_pass_begin_info.renderArea.offset.x = 0;
render_pass_begin_info.renderArea.offset.y = 0;
render_pass_begin_info.renderArea.extent.width = width;
render_pass_begin_info.renderArea.extent.height = height;
render_pass_begin_info.clearValueCount = 2;
render_pass_begin_info.pClearValues = clear_values;
render_pass_begin_info.clearValueCount = 2; // 现在清除颜色和深度
render_pass_begin_info.pClearValues = clear_values;
for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i)
{
@@ -81,16 +92,30 @@ void TextureLoading::build_command_buffers()
VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(draw_cmd_buffers[i], 0, 1, &scissor);
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);
// --- 绘制全屏背景 ---
if (cam_text.image != VK_NULL_HANDLE && cam_text.view != VK_NULL_HANDLE && cam_text.sampler != VK_NULL_HANDLE) {
vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.background);
vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_bg, 0, 1, &descriptor_set_bg, 0, NULL);
// 绘制一个三角形 strip,覆盖整个屏幕 (NDC -1 to 1)
// 顶点顺序: (-1,-1), (1,-1), (-1,1), (1,1)
vkCmdDraw(draw_cmd_buffers[i], 4, 1, 0, 0); // 4 个顶点, 1 个实例, 从索引 0 开始
}
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);
// --- 绘制前景四边形 ---
// 确保前景管线和描述符集有效
if (pipelines.solid != VK_NULL_HANDLE && descriptor_set != VK_NULL_HANDLE &&
vertex_buffer && index_buffer) {
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);
vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0);
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);
draw_ui(draw_cmd_buffers[i]);
vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0);
}
draw_ui(draw_cmd_buffers[i]); // UI 通常在最后绘制
vkCmdEndRenderPass(draw_cmd_buffers[i]);
@@ -98,9 +123,10 @@ void TextureLoading::build_command_buffers()
}
}
// 生成简单的测试图像数据(红绿蓝三色条)
// 生成简单的测试图像数据(红绿蓝三色条)
std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowStride = nullptr) {
int rowStride = width * 4; // RGBA 每个像素4字节
int rowStride = width * 4; // RGBA 每个像素4字节
if (outRowStride) {
*outRowStride = rowStride;
}
@@ -112,27 +138,27 @@ std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowS
for (int x = 0; x < width; x++) {
int pixelOffset = y * rowStride + x * 4;
// 简单分成三个区域:红、绿、蓝
// 简单分成三个区域:红、绿、蓝
if (x < width / 3) {
// 红色区域
// 红色区域
imageData[pixelOffset] = 255; // R
imageData[pixelOffset + 1] = 0; // G
imageData[pixelOffset + 2] = 0; // B
}
else if (x < 2 * width / 3) {
// 绿色区域
// 绿色区域
imageData[pixelOffset] = 0; // R
imageData[pixelOffset + 1] = 255; // G
imageData[pixelOffset + 2] = 0; // B
}
else {
// 蓝色区域
// 蓝色区域
imageData[pixelOffset] = 0; // R
imageData[pixelOffset + 1] = 0; // G
imageData[pixelOffset + 2] = 255; // B
}
imageData[pixelOffset + 3] = 255; // A (完全不透明)
imageData[pixelOffset + 3] = 255; // A (完全不透明)
}
}
@@ -145,7 +171,7 @@ void TextureLoading::draw()
// Command buffer to be submitted to the queue
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
// Submit to queue
VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE));
@@ -157,220 +183,375 @@ void TextureLoading::generate_quad()
{
// Setup vertices for a single uv-mapped quad made from two triangles
std::vector<TextureLoadingVertexStructure> vertices =
{
{{1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{-1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
{{1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}}};
{
{{1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{-1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
{{1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}} };
// Setup indices
std::vector<uint32_t> indices = {0, 1, 2, 2, 3, 0};
index_count = static_cast<uint32_t>(indices.size());
std::vector<uint32_t> indices = { 0, 1, 2, 2, 3, 0 };
index_count = static_cast<uint32_t>(indices.size());
auto vertex_buffer_size = vkb::to_u32(vertices.size() * sizeof(TextureLoadingVertexStructure));
auto index_buffer_size = vkb::to_u32(indices.size() * sizeof(uint32_t));
auto index_buffer_size = vkb::to_u32(indices.size() * sizeof(uint32_t));
// Create buffers
// For the sake of simplicity we won't stage the vertex data to the gpu memory
// Vertex buffer
vertex_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
vertex_buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
vertex_buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
vertex_buffer->update(vertices.data(), vertex_buffer_size);
index_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
index_buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
index_buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
index_buffer->update(indices.data(), index_buffer_size);
}
void TextureLoading::setup_descriptor_pool()
{
// Example uses one ubo and one image sampler
// Example uses one ubo and two image samplers (one for foreground, one for background)
// 增加 Combined Image Sampler 的数量到 2
std::vector<VkDescriptorPoolSize> pool_sizes =
{
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)};
{
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) // 改为 2
};
VkDescriptorPoolCreateInfo descriptor_pool_create_info =
vkb::initializers::descriptor_pool_create_info(
static_cast<uint32_t>(pool_sizes.size()),
pool_sizes.data(),
2);
vkb::initializers::descriptor_pool_create_info(
static_cast<uint32_t>(pool_sizes.size()),
pool_sizes.data(),
2); // 最大描述符集数量改为 2
VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool));
}
void TextureLoading::setup_descriptor_set_layout()
{
// Foreground descriptor set layout (UBO + Texture)
std::vector<VkDescriptorSetLayoutBinding> 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)};
{
// 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 (foreground texture)
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<uint32_t>(set_layout_bindings.size()));
vkb::initializers::descriptor_set_layout_create_info(
set_layout_bindings.data(),
static_cast<uint32_t>(set_layout_bindings.size()));
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout));
// Foreground pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_create_info =
vkb::initializers::pipeline_layout_create_info(
&descriptor_set_layout,
1);
vkb::initializers::pipeline_layout_create_info(
&descriptor_set_layout,
1);
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout));
}
// 新增:设置背景描述符集布局 (仅包含纹理)
void TextureLoading::setup_descriptor_set_layout_bg()
{
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings_bg =
{
// Binding 0 : Fragment shader image sampler (background texture)
vkb::initializers::descriptor_set_layout_binding(
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_SHADER_STAGE_FRAGMENT_BIT,
0) // Binding 0 for background
};
VkDescriptorSetLayoutCreateInfo descriptor_layout_bg =
vkb::initializers::descriptor_set_layout_create_info(
set_layout_bindings_bg.data(),
static_cast<uint32_t>(set_layout_bindings_bg.size()));
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout_bg, nullptr, &descriptor_set_layout_bg));
// Background pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_create_info_bg =
vkb::initializers::pipeline_layout_create_info(
&descriptor_set_layout_bg,
1);
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info_bg, nullptr, &pipeline_layout_bg));
}
void TextureLoading::setup_descriptor_set()
{
// Foreground descriptor set
VkDescriptorSetAllocateInfo alloc_info =
vkb::initializers::descriptor_set_allocate_info(
descriptor_pool,
&descriptor_set_layout,
1);
vkb::initializers::descriptor_set_allocate_info(
descriptor_pool,
&descriptor_set_layout,
1);
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set));
VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*uniform_buffer_vs);
// Setup a descriptor image info for the current texture to be used as a combined image sampler
// Setup a descriptor image info for the current foreground texture
VkDescriptorImageInfo image_descriptor;
image_descriptor.imageView = texture.view; // The image's view (images are never directly accessed by the shader, but rather through views defining subresources)
image_descriptor.sampler = texture.sampler; // The sampler (Telling the pipeline how to sample the texture, including repeat, border, etc.)
image_descriptor.imageLayout = texture.image_layout; // The current layout of the image (Note: Should always fit the actual use, e.g. shader read)
image_descriptor.imageView = texture.view;
image_descriptor.sampler = texture.sampler;
image_descriptor.imageLayout = texture.image_layout;
std::vector<VkWriteDescriptorSet> write_descriptor_sets =
{
// Binding 0 : Vertex shader uniform buffer
vkb::initializers::write_descriptor_set(
descriptor_set,
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,
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
};
{
// Binding 0 : Vertex shader uniform buffer
vkb::initializers::write_descriptor_set(
descriptor_set,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0,
&buffer_descriptor),
// Binding 1 : Fragment shader texture sampler (foreground)
vkb::initializers::write_descriptor_set(
descriptor_set,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1,
&image_descriptor)
};
vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
}
// 新增:设置背景描述符集
void TextureLoading::setup_descriptor_set_bg()
{
// Background descriptor set
VkDescriptorSetAllocateInfo alloc_info_bg =
vkb::initializers::descriptor_set_allocate_info(
descriptor_pool,
&descriptor_set_layout_bg,
1);
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info_bg, &descriptor_set_bg));
// Setup a descriptor image info for the background texture (cam_text)
VkDescriptorImageInfo image_descriptor_bg;
// 注意:这里使用 cam_text
image_descriptor_bg.imageView = cam_text.view;
image_descriptor_bg.sampler = cam_text.sampler;
image_descriptor_bg.imageLayout = cam_text.image_layout; // 应该是 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
std::vector<VkWriteDescriptorSet> write_descriptor_sets_bg =
{
// Binding 0 : Fragment shader texture sampler (background)
vkb::initializers::write_descriptor_set(
descriptor_set_bg,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, // Binding 0 for background
&image_descriptor_bg)
};
vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets_bg.size()), write_descriptor_sets_bg.data(), 0, NULL);
}
void TextureLoading::prepare_pipelines()
{
// --- 前景管线 ---
VkPipelineInputAssemblyStateCreateInfo input_assembly_state =
vkb::initializers::pipeline_input_assembly_state_create_info(
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
0,
VK_FALSE);
vkb::initializers::pipeline_input_assembly_state_create_info(
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
0,
VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterization_state =
vkb::initializers::pipeline_rasterization_state_create_info(
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_NONE,
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0);
vkb::initializers::pipeline_rasterization_state_create_info(
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_NONE, // 保持不变,或根据需要调整
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0);
VkPipelineColorBlendAttachmentState blend_attachment_state =
vkb::initializers::pipeline_color_blend_attachment_state(
0xf,
VK_FALSE);
vkb::initializers::pipeline_color_blend_attachment_state(
0xf,
VK_FALSE);
VkPipelineColorBlendStateCreateInfo color_blend_state =
vkb::initializers::pipeline_color_blend_state_create_info(
1,
&blend_attachment_state);
vkb::initializers::pipeline_color_blend_state_create_info(
1,
&blend_attachment_state);
// Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept
// 前景管线启用深度测试和写入
VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
vkb::initializers::pipeline_depth_stencil_state_create_info(
VK_TRUE,
VK_TRUE,
VK_COMPARE_OP_GREATER);
vkb::initializers::pipeline_depth_stencil_state_create_info(
VK_TRUE, // depthTestEnable
VK_TRUE, // depthWriteEnable
VK_COMPARE_OP_GREATER); // Reversed depth buffer
VkPipelineViewportStateCreateInfo viewport_state =
vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0);
vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0);
VkPipelineMultisampleStateCreateInfo multisample_state =
vkb::initializers::pipeline_multisample_state_create_info(
VK_SAMPLE_COUNT_1_BIT,
0);
vkb::initializers::pipeline_multisample_state_create_info(
VK_SAMPLE_COUNT_1_BIT,
0);
std::vector<VkDynamicState> dynamic_state_enables = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR};
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamic_state =
vkb::initializers::pipeline_dynamic_state_create_info(
dynamic_state_enables.data(),
static_cast<uint32_t>(dynamic_state_enables.size()),
0);
vkb::initializers::pipeline_dynamic_state_create_info(
dynamic_state_enables.data(),
static_cast<uint32_t>(dynamic_state_enables.size()),
0);
// Load shaders
// Load shaders (确保你有对应的 SPIR-V 文件)
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages;
// 假设着色器文件名为 texture.vert.spv 和 texture.frag.spv
shader_stages[0] = load_shader("texture_loading", "texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shader_stages[1] = load_shader("texture_loading", "texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Vertex bindings and attributes
// Vertex bindings and attributes (用于前景 quad)
const std::vector<VkVertexInputBindingDescription> vertex_input_bindings = {
vkb::initializers::vertex_input_binding_description(0, sizeof(TextureLoadingVertexStructure), VK_VERTEX_INPUT_RATE_VERTEX),
vkb::initializers::vertex_input_binding_description(0, sizeof(TextureLoadingVertexStructure), VK_VERTEX_INPUT_RATE_VERTEX),
};
const std::vector<VkVertexInputAttributeDescription> vertex_input_attributes = {
vkb::initializers::vertex_input_attribute_description(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(TextureLoadingVertexStructure, pos)),
vkb::initializers::vertex_input_attribute_description(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(TextureLoadingVertexStructure, uv)),
vkb::initializers::vertex_input_attribute_description(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(TextureLoadingVertexStructure, normal)),
vkb::initializers::vertex_input_attribute_description(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(TextureLoadingVertexStructure, pos)),
vkb::initializers::vertex_input_attribute_description(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(TextureLoadingVertexStructure, uv)),
vkb::initializers::vertex_input_attribute_description(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(TextureLoadingVertexStructure, normal)),
};
VkPipelineVertexInputStateCreateInfo vertex_input_state = vkb::initializers::pipeline_vertex_input_state_create_info();
vertex_input_state.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_input_bindings.size());
vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data();
vertex_input_state.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attributes.size());
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data();
vertex_input_state.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_input_bindings.size());
vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data();
vertex_input_state.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attributes.size());
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data();
VkGraphicsPipelineCreateInfo pipeline_create_info =
vkb::initializers::pipeline_create_info(
pipeline_layout,
render_pass,
0);
vkb::initializers::pipeline_create_info(
pipeline_layout, // 前景管线布局
render_pass,
0);
pipeline_create_info.pVertexInputState = &vertex_input_state;
pipeline_create_info.pVertexInputState = &vertex_input_state;
pipeline_create_info.pInputAssemblyState = &input_assembly_state;
pipeline_create_info.pRasterizationState = &rasterization_state;
pipeline_create_info.pColorBlendState = &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.stageCount = static_cast<uint32_t>(shader_stages.size());
pipeline_create_info.pStages = shader_stages.data();
pipeline_create_info.pColorBlendState = &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.stageCount = static_cast<uint32_t>(shader_stages.size());
pipeline_create_info.pStages = shader_stages.data();
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &pipelines.solid));
}
// 新增:准备背景管线
void TextureLoading::prepare_pipeline_bg()
{
// --- 背景管线 (简单 quad, 全屏覆盖) ---
VkPipelineInputAssemblyStateCreateInfo input_assembly_state_bg =
vkb::initializers::pipeline_input_assembly_state_create_info(
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // 使用 Triangle Strip
0,
VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterization_state_bg =
vkb::initializers::pipeline_rasterization_state_create_info(
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_BACK_BIT, // 通常对全屏 quad 启用背面剔除,但这里可能不需要,因为是屏幕对齐的
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0);
VkPipelineColorBlendAttachmentState blend_attachment_state_bg =
vkb::initializers::pipeline_color_blend_attachment_state(
0xf,
VK_FALSE); // 通常背景不需要混合
VkPipelineColorBlendStateCreateInfo color_blend_state_bg =
vkb::initializers::pipeline_color_blend_state_create_info(
1,
&blend_attachment_state_bg);
// 背景管线配置:启用深度测试,但禁用深度写入,使用 LESS 比较 (或 ALWAYS)
// 这样背景会被绘制,但不会影响前景物体的深度值(如果前景物体 Z 值更近)
VkPipelineDepthStencilStateCreateInfo depth_stencil_state_bg =
vkb::initializers::pipeline_depth_stencil_state_create_info(
VK_TRUE, // depthTestEnable - 启用深度测试
VK_FALSE, // depthWriteEnable - 禁用深度写入,让前景物体能正确遮挡背景
VK_COMPARE_OP_LESS); // 比较操作:如果片段的深度小于深度缓冲区中的值,则通过。
// 结合清除深度为 1.0 和前景使用 GREATER,这应该可以正确工作。
// 或者使用 VK_COMPARE_OP_ALWAYS 来强制绘制背景,忽略深度。
VkPipelineViewportStateCreateInfo viewport_state_bg =
vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0);
VkPipelineMultisampleStateCreateInfo multisample_state_bg =
vkb::initializers::pipeline_multisample_state_create_info(
VK_SAMPLE_COUNT_1_BIT,
0);
// 背景管线不需要动态状态或顶点输入(如果顶点在着色器中生成)
std::vector<VkDynamicState> dynamic_state_enables_bg = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamic_state_bg =
vkb::initializers::pipeline_dynamic_state_create_info(
dynamic_state_enables_bg.data(),
static_cast<uint32_t>(dynamic_state_enables_bg.size()),
0);
// Load shaders for background (你需要创建对应的 SPIR-V 文件)
// 假设着色器文件名为 bg.vert.spv 和 bg.frag.spv
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages_bg;
shader_stages_bg[0] = load_shader("texture_loading", "bg.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shader_stages_bg[1] = load_shader("texture_loading", "bg.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// 背景管线不需要顶点缓冲区输入
VkPipelineVertexInputStateCreateInfo vertex_input_state_bg = vkb::initializers::pipeline_vertex_input_state_create_info();
// vertex_input_state_bg 保持默认空状态即可
VkGraphicsPipelineCreateInfo pipeline_create_info_bg =
vkb::initializers::pipeline_create_info(
pipeline_layout_bg, // 背景管线布局
render_pass,
0);
pipeline_create_info_bg.pVertexInputState = &vertex_input_state_bg; // 空的顶点输入
pipeline_create_info_bg.pInputAssemblyState = &input_assembly_state_bg;
pipeline_create_info_bg.pRasterizationState = &rasterization_state_bg;
pipeline_create_info_bg.pColorBlendState = &color_blend_state_bg;
pipeline_create_info_bg.pMultisampleState = &multisample_state_bg;
pipeline_create_info_bg.pViewportState = &viewport_state_bg;
pipeline_create_info_bg.pDepthStencilState = &depth_stencil_state_bg;
pipeline_create_info_bg.pDynamicState = &dynamic_state_bg;
pipeline_create_info_bg.stageCount = static_cast<uint32_t>(shader_stages_bg.size());
pipeline_create_info_bg.pStages = shader_stages_bg.data();
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info_bg, nullptr, &pipelines.background));
}
// Prepare and initialize uniform buffer containing shader uniforms
void TextureLoading::prepare_uniform_buffers()
{
// Vertex shader uniform buffer block
uniform_buffer_vs = std::make_unique<vkb::core::BufferC>(get_device(),
sizeof(ubo_vs),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
sizeof(ubo_vs),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU);
update_uniform_buffers();
}
@@ -378,7 +559,7 @@ void TextureLoading::prepare_uniform_buffers()
void TextureLoading::update_uniform_buffers()
{
// Vertex shader
ubo_vs.projection = glm::perspective(glm::radians(60.0f), static_cast<float>(width) / static_cast<float>(height), 0.001f, 256.0f);
ubo_vs.projection = glm::perspective(glm::radians(60.0f), static_cast<float>(width) / static_cast<float>(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);
@@ -391,33 +572,41 @@ void TextureLoading::update_uniform_buffers()
uniform_buffer_vs->convert_and_update(ubo_vs);
}
bool TextureLoading::prepare(const vkb::ApplicationOptions &options)
bool TextureLoading::prepare(const vkb::ApplicationOptions& options)
{
if (!ApiVulkanSample::prepare(options))
{
return false;
}
//load_texture();
// --- 初始化 cam_text 纹理对象 ---
// 注意:这里只是初始化结构体,图像内存等由外部函数分配
// cam_text = {0}; // 已在构造函数或销毁时重置
// --- 加载前景纹理 (示例) ---
int width = 640;
int height = 480;
int rowStride;
auto testImage = generateSimpleTestImage(width, height, &rowStride);
size_t dataSize = testImage.size();
std::cout << "Generated test image: " << width << "x" << height << std::endl;
std::cout << "Row stride: " << rowStride << std::endl;
std::cout << "Data size: " << dataSize << " bytes" << std::endl;
processWithVulkan(testImage.data(), width, height, 1, rowStride, dataSize, texture);
// --- 生成前景几何体 ---
generate_quad();
// --- 准备资源 ---
prepare_uniform_buffers();
setup_descriptor_set_layout();
prepare_pipelines();
setup_descriptor_pool();
setup_descriptor_set();
setup_descriptor_set_layout(); // 前景 DSL
setup_descriptor_set_layout_bg(); // 背景 DSL
prepare_pipelines(); // 前景管线
prepare_pipeline_bg(); // 背景管线
setup_descriptor_pool(); // 描述符池 (已更新大小)
setup_descriptor_set(); // 前景 DS
setup_descriptor_set_bg(); // 背景 DS
build_command_buffers();
prepared = true;
return true;
@@ -430,7 +619,10 @@ void TextureLoading::render(float delta_time)
return;
}
if (texture.width == 0)
// 可以在这里添加逻辑来更新 cam_text 纹理
// 例如,如果 cam_text.image != VK_NULL_HANDLE,调用 updateTexture
if (texture.width == 0) // 检查前景纹理
{
return;
}
@@ -443,7 +635,7 @@ void TextureLoading::view_changed()
update_uniform_buffers();
}
void TextureLoading::on_update_ui_overlay(vkb::Drawer &drawer)
void TextureLoading::on_update_ui_overlay(vkb::Drawer& drawer)
{
if (drawer.header("Settings"))
{
@@ -459,10 +651,18 @@ std::unique_ptr<vkb::Application> create_texture_loading()
return std::make_unique<TextureLoading>();
}
// 外部函数保持不变
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize)
{
TextureLoading::Texture& cam_texture = TextureLoading::Get()->cam_text;
TextureLoading::Get()->processWithVulkan(data, width, height, format, rowStride, dataSize, cam_texture);
if (TextureLoading::Get()) {
TextureLoading::Texture& cam_texture = TextureLoading::Get()->cam_text;
TextureLoading::Get()->processWithVulkan(data, width, height, format, rowStride, dataSize, cam_texture);
// 可能需要重建命令缓冲区或更新描述符集,如果管线已经创建
// 这里简单地重建命令缓冲区
if (TextureLoading::Get()->prepared) {
TextureLoading::Get()->build_command_buffers();
}
}
}
@@ -472,13 +672,20 @@ void TextureLoading::processWithVulkan(uint8_t* data, int width, int height, int
const VkPhysicalDevice& physicalDevice = get_device().get_gpu().get_handle();
if (out_texture.image == VK_NULL_HANDLE) {
createTexture(device, physicalDevice, width, height, format, out_texture);
// 如果纹理是新创建的,并且管线已经准备好,需要更新描述符集
if (prepared && &out_texture == &cam_text) {
setup_descriptor_set_bg(); // 重新设置背景描述符集
}
}
const VkCommandPool& commandPool = get_device().get_command_pool().get_handle();
updateTexture(device, physicalDevice, commandPool, queue, data, width, height,
rowStride, dataSize, out_texture);
// 如果纹理被更新,并且管线已经准备好,可能需要重建命令缓冲区
// 这取决于你的应用逻辑。简单起见,在外部函数中处理。
}
// --- 以下函数保持不变 ---
void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDevice,
int width, int height, int format, Texture& texture) {
@@ -489,7 +696,7 @@ void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDev
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; // 匹配 RGBA_8888
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; // Æ¥Åä RGBA_8888
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
+33 -24
View File
@@ -1,10 +1,10 @@
#pragma once
#pragma once
#include <ktx.h>
#include "api_vulkan_sample.h"
// 顶点结构保持不变,因为背景 quad 可能不需要顶点缓冲区
struct TextureLoadingVertexStructure
{
float pos[3];
@@ -14,7 +14,7 @@ struct TextureLoadingVertexStructure
class TextureLoading : public ApiVulkanSample
{
public:
public:
struct Texture
{
VkSampler sampler;
@@ -26,8 +26,8 @@ class TextureLoading : public ApiVulkanSample
uint32_t mip_levels;
};
Texture texture = {0};
Texture cam_text = {0};
Texture texture = { 0 };
Texture cam_text = { 0 }; // 将由外部函数初始化
std::unique_ptr<vkb::core::BufferC> vertex_buffer;
std::unique_ptr<vkb::core::BufferC> index_buffer;
@@ -45,47 +45,56 @@ class TextureLoading : public ApiVulkanSample
struct
{
VkPipeline solid;
VkPipeline solid; // 原有前景管线
VkPipeline background; // 新增背景管线
} pipelines;
VkPipelineLayout pipeline_layout;
VkDescriptorSet descriptor_set;
VkDescriptorSetLayout descriptor_set_layout;
// 管线布局
VkPipelineLayout pipeline_layout; // 前景管线布局
VkPipelineLayout pipeline_layout_bg; // 背景管线布局
// 描述符集
VkDescriptorSet descriptor_set; // 前景描述符集
VkDescriptorSet descriptor_set_bg; // 背景描述符集
// 描述符集布局
VkDescriptorSetLayout descriptor_set_layout; // 前景描述符集布局
VkDescriptorSetLayout descriptor_set_layout_bg; // 背景描述符集布局 (仅包含 combined image sampler)
static TextureLoading* Get() {
return loadTextIns;
}
static TextureLoading* loadTextIns;
TextureLoading();
~TextureLoading();
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override;
virtual void request_gpu_features(vkb::PhysicalDevice& gpu) override;
void build_command_buffers() override;
void draw();
void generate_quad();
void generate_quad(); // 生成前景 quad
void setup_descriptor_pool();
void setup_descriptor_set_layout();
void setup_descriptor_set_layout_bg(); // 新增:设置背景描述符集布局
void setup_descriptor_set();
void setup_descriptor_set_bg(); // 新增:设置背景描述符集
void prepare_pipelines();
void prepare_pipeline_bg(); // 新增:准备背景管线
void prepare_uniform_buffers();
void update_uniform_buffers();
bool prepare(const vkb::ApplicationOptions &options) override;
bool prepare(const vkb::ApplicationOptions& options) override;
virtual void render(float delta_time) override;
virtual void view_changed() override;
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override;
virtual void on_update_ui_overlay(vkb::Drawer& drawer) override;
void destroy_texture(Texture texture);
public:
// 现有函数保持不变
void processWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize, Texture& out_texture);
void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, int format, Texture& texture);
void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture);
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture);
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
};
std::unique_ptr<vkb::Application> create_texture_loading();