通议灵码修改过的。
This commit is contained in:
@@ -1,13 +1,11 @@
|
|||||||
|
#include "texture_loading.h"
|
||||||
|
|
||||||
#include "texture_loading.h"
|
|
||||||
TextureLoading* TextureLoading::loadTextIns = nullptr;
|
TextureLoading* TextureLoading::loadTextIns = nullptr;
|
||||||
|
|
||||||
TextureLoading::TextureLoading()
|
TextureLoading::TextureLoading()
|
||||||
{
|
{
|
||||||
zoom = -2.5f;
|
zoom = -2.5f;
|
||||||
rotation = {0.0f, 15.0f, 0.0f};
|
rotation = { 0.0f, 15.0f, 0.0f };
|
||||||
title = "Texture loading";
|
title = "Texture loading";
|
||||||
loadTextIns = this;
|
loadTextIns = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,9 +17,18 @@ TextureLoading::~TextureLoading()
|
|||||||
// Note : Inherited destructor cleans up resources stored in base class
|
// Note : Inherited destructor cleans up resources stored in base class
|
||||||
|
|
||||||
vkDestroyPipeline(get_device().get_handle(), pipelines.solid, nullptr);
|
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);
|
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);
|
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);
|
destroy_texture(texture);
|
||||||
@@ -32,7 +39,7 @@ TextureLoading::~TextureLoading()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable physical device features required for this example
|
// 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
|
// Enable anisotropic filtering if supported
|
||||||
if (gpu.get_features().samplerAnisotropy)
|
if (gpu.get_features().samplerAnisotropy)
|
||||||
@@ -43,28 +50,32 @@ void TextureLoading::request_gpu_features(vkb::PhysicalDevice &gpu)
|
|||||||
|
|
||||||
void TextureLoading::destroy_texture(Texture texture)
|
void TextureLoading::destroy_texture(Texture texture)
|
||||||
{
|
{
|
||||||
vkDestroyImageView(get_device().get_handle(), texture.view, nullptr);
|
if (texture.view != VK_NULL_HANDLE) vkDestroyImageView(get_device().get_handle(), texture.view, nullptr);
|
||||||
vkDestroyImage(get_device().get_handle(), texture.image, nullptr);
|
if (texture.image != VK_NULL_HANDLE) vkDestroyImage(get_device().get_handle(), texture.image, nullptr);
|
||||||
vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr);
|
if (texture.sampler != VK_NULL_HANDLE) vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr);
|
||||||
vkFreeMemory(get_device().get_handle(), texture.device_memory, 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()
|
void TextureLoading::build_command_buffers()
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();
|
VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();
|
||||||
|
|
||||||
|
// 注意:深度缓冲区清除值改为 1.0f (最远)
|
||||||
VkClearValue clear_values[2];
|
VkClearValue clear_values[2];
|
||||||
clear_values[0].color = default_clear_color;
|
clear_values[0].color = default_clear_color;
|
||||||
clear_values[1].depthStencil = {0.0f, 0};
|
clear_values[1].depthStencil = { 1.0f, 0 }; // 使用 1.0f 作为深度清除值
|
||||||
|
|
||||||
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
|
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
|
||||||
render_pass_begin_info.renderPass = render_pass;
|
render_pass_begin_info.renderPass = render_pass;
|
||||||
render_pass_begin_info.renderArea.offset.x = 0;
|
render_pass_begin_info.renderArea.offset.x = 0;
|
||||||
render_pass_begin_info.renderArea.offset.y = 0;
|
render_pass_begin_info.renderArea.offset.y = 0;
|
||||||
render_pass_begin_info.renderArea.extent.width = width;
|
render_pass_begin_info.renderArea.extent.width = width;
|
||||||
render_pass_begin_info.renderArea.extent.height = height;
|
render_pass_begin_info.renderArea.extent.height = height;
|
||||||
render_pass_begin_info.clearValueCount = 2;
|
render_pass_begin_info.clearValueCount = 2; // 现在清除颜色和深度
|
||||||
render_pass_begin_info.pClearValues = clear_values;
|
render_pass_begin_info.pClearValues = clear_values;
|
||||||
|
|
||||||
for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i)
|
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);
|
VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0);
|
||||||
vkCmdSetScissor(draw_cmd_buffers[i], 0, 1, &scissor);
|
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]);
|
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) {
|
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) {
|
if (outRowStride) {
|
||||||
*outRowStride = rowStride;
|
*outRowStride = rowStride;
|
||||||
}
|
}
|
||||||
@@ -112,27 +138,27 @@ std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowS
|
|||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
int pixelOffset = y * rowStride + x * 4;
|
int pixelOffset = y * rowStride + x * 4;
|
||||||
|
|
||||||
// 简单分成三个区域:红、绿、蓝
|
// 简单分成三个区域:红、绿、蓝
|
||||||
if (x < width / 3) {
|
if (x < width / 3) {
|
||||||
// 红色区域
|
// 红色区域
|
||||||
imageData[pixelOffset] = 255; // R
|
imageData[pixelOffset] = 255; // R
|
||||||
imageData[pixelOffset + 1] = 0; // G
|
imageData[pixelOffset + 1] = 0; // G
|
||||||
imageData[pixelOffset + 2] = 0; // B
|
imageData[pixelOffset + 2] = 0; // B
|
||||||
}
|
}
|
||||||
else if (x < 2 * width / 3) {
|
else if (x < 2 * width / 3) {
|
||||||
// 绿色区域
|
// 绿色区域
|
||||||
imageData[pixelOffset] = 0; // R
|
imageData[pixelOffset] = 0; // R
|
||||||
imageData[pixelOffset + 1] = 255; // G
|
imageData[pixelOffset + 1] = 255; // G
|
||||||
imageData[pixelOffset + 2] = 0; // B
|
imageData[pixelOffset + 2] = 0; // B
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 蓝色区域
|
// 蓝色区域
|
||||||
imageData[pixelOffset] = 0; // R
|
imageData[pixelOffset] = 0; // R
|
||||||
imageData[pixelOffset + 1] = 0; // G
|
imageData[pixelOffset + 1] = 0; // G
|
||||||
imageData[pixelOffset + 2] = 255; // B
|
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
|
// Command buffer to be submitted to the queue
|
||||||
submit_info.commandBufferCount = 1;
|
submit_info.commandBufferCount = 1;
|
||||||
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
|
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
|
||||||
|
|
||||||
// Submit to queue
|
// Submit to queue
|
||||||
VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE));
|
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
|
// Setup vertices for a single uv-mapped quad made from two triangles
|
||||||
std::vector<TextureLoadingVertexStructure> vertices =
|
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}, {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, 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}, {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, 0.0f}, {0.0f, 0.0f, 1.0f}} };
|
||||||
|
|
||||||
// Setup indices
|
// Setup indices
|
||||||
std::vector<uint32_t> indices = {0, 1, 2, 2, 3, 0};
|
std::vector<uint32_t> indices = { 0, 1, 2, 2, 3, 0 };
|
||||||
index_count = static_cast<uint32_t>(indices.size());
|
index_count = static_cast<uint32_t>(indices.size());
|
||||||
|
|
||||||
auto vertex_buffer_size = vkb::to_u32(vertices.size() * sizeof(TextureLoadingVertexStructure));
|
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
|
// Create buffers
|
||||||
// For the sake of simplicity we won't stage the vertex data to the gpu memory
|
// For the sake of simplicity we won't stage the vertex data to the gpu memory
|
||||||
// Vertex buffer
|
// Vertex buffer
|
||||||
vertex_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
|
vertex_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
|
||||||
vertex_buffer_size,
|
vertex_buffer_size,
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||||
vertex_buffer->update(vertices.data(), vertex_buffer_size);
|
vertex_buffer->update(vertices.data(), vertex_buffer_size);
|
||||||
|
|
||||||
index_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
|
index_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
|
||||||
index_buffer_size,
|
index_buffer_size,
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||||
|
|
||||||
index_buffer->update(indices.data(), index_buffer_size);
|
index_buffer->update(indices.data(), index_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLoading::setup_descriptor_pool()
|
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 =
|
std::vector<VkDescriptorPoolSize> pool_sizes =
|
||||||
{
|
{
|
||||||
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
|
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_COMBINED_IMAGE_SAMPLER, 2) // 改为 2
|
||||||
|
};
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo descriptor_pool_create_info =
|
VkDescriptorPoolCreateInfo descriptor_pool_create_info =
|
||||||
vkb::initializers::descriptor_pool_create_info(
|
vkb::initializers::descriptor_pool_create_info(
|
||||||
static_cast<uint32_t>(pool_sizes.size()),
|
static_cast<uint32_t>(pool_sizes.size()),
|
||||||
pool_sizes.data(),
|
pool_sizes.data(),
|
||||||
2);
|
2); // 最大描述符集数量改为 2
|
||||||
|
|
||||||
VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool));
|
VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLoading::setup_descriptor_set_layout()
|
void TextureLoading::setup_descriptor_set_layout()
|
||||||
{
|
{
|
||||||
|
// Foreground descriptor set layout (UBO + Texture)
|
||||||
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings =
|
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings =
|
||||||
{
|
{
|
||||||
// Binding 0 : Vertex shader uniform buffer
|
// Binding 0 : Vertex shader uniform buffer
|
||||||
vkb::initializers::descriptor_set_layout_binding(
|
vkb::initializers::descriptor_set_layout_binding(
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT,
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
0),
|
0),
|
||||||
// Binding 1 : Fragment shader image sampler
|
// Binding 1 : Fragment shader image sampler (foreground texture)
|
||||||
vkb::initializers::descriptor_set_layout_binding(
|
vkb::initializers::descriptor_set_layout_binding(
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
1)};
|
1) };
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo descriptor_layout =
|
VkDescriptorSetLayoutCreateInfo descriptor_layout =
|
||||||
vkb::initializers::descriptor_set_layout_create_info(
|
vkb::initializers::descriptor_set_layout_create_info(
|
||||||
set_layout_bindings.data(),
|
set_layout_bindings.data(),
|
||||||
static_cast<uint32_t>(set_layout_bindings.size()));
|
static_cast<uint32_t>(set_layout_bindings.size()));
|
||||||
|
|
||||||
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout));
|
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout));
|
||||||
|
|
||||||
|
// Foreground pipeline layout
|
||||||
VkPipelineLayoutCreateInfo pipeline_layout_create_info =
|
VkPipelineLayoutCreateInfo pipeline_layout_create_info =
|
||||||
vkb::initializers::pipeline_layout_create_info(
|
vkb::initializers::pipeline_layout_create_info(
|
||||||
&descriptor_set_layout,
|
&descriptor_set_layout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout));
|
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()
|
void TextureLoading::setup_descriptor_set()
|
||||||
{
|
{
|
||||||
|
// Foreground descriptor set
|
||||||
VkDescriptorSetAllocateInfo alloc_info =
|
VkDescriptorSetAllocateInfo alloc_info =
|
||||||
vkb::initializers::descriptor_set_allocate_info(
|
vkb::initializers::descriptor_set_allocate_info(
|
||||||
descriptor_pool,
|
descriptor_pool,
|
||||||
&descriptor_set_layout,
|
&descriptor_set_layout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set));
|
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set));
|
||||||
|
|
||||||
VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*uniform_buffer_vs);
|
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;
|
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.imageView = texture.view;
|
||||||
image_descriptor.sampler = texture.sampler; // The sampler (Telling the pipeline how to sample the texture, including repeat, border, etc.)
|
image_descriptor.sampler = texture.sampler;
|
||||||
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.imageLayout = texture.image_layout;
|
||||||
|
|
||||||
std::vector<VkWriteDescriptorSet> write_descriptor_sets =
|
std::vector<VkWriteDescriptorSet> write_descriptor_sets =
|
||||||
{
|
{
|
||||||
// Binding 0 : Vertex shader uniform buffer
|
// Binding 0 : Vertex shader uniform buffer
|
||||||
vkb::initializers::write_descriptor_set(
|
vkb::initializers::write_descriptor_set(
|
||||||
descriptor_set,
|
descriptor_set,
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
0,
|
0,
|
||||||
&buffer_descriptor),
|
&buffer_descriptor),
|
||||||
// Binding 1 : Fragment shader texture sampler
|
// Binding 1 : Fragment shader texture sampler (foreground)
|
||||||
// Fragment shader: layout (binding = 1) uniform sampler2D samplerColor;
|
vkb::initializers::write_descriptor_set(
|
||||||
vkb::initializers::write_descriptor_set(
|
descriptor_set,
|
||||||
descriptor_set,
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // The descriptor set will use a combined image sampler (sampler and image could be split)
|
1,
|
||||||
1, // Shader binding point 1
|
&image_descriptor)
|
||||||
&image_descriptor) // Pointer to the descriptor image for our texture
|
};
|
||||||
};
|
|
||||||
|
|
||||||
vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
|
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()
|
void TextureLoading::prepare_pipelines()
|
||||||
{
|
{
|
||||||
|
// --- 前景管线 ---
|
||||||
VkPipelineInputAssemblyStateCreateInfo input_assembly_state =
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_state =
|
||||||
vkb::initializers::pipeline_input_assembly_state_create_info(
|
vkb::initializers::pipeline_input_assembly_state_create_info(
|
||||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
0,
|
0,
|
||||||
VK_FALSE);
|
VK_FALSE);
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterization_state =
|
VkPipelineRasterizationStateCreateInfo rasterization_state =
|
||||||
vkb::initializers::pipeline_rasterization_state_create_info(
|
vkb::initializers::pipeline_rasterization_state_create_info(
|
||||||
VK_POLYGON_MODE_FILL,
|
VK_POLYGON_MODE_FILL,
|
||||||
VK_CULL_MODE_NONE,
|
VK_CULL_MODE_NONE, // 保持不变,或根据需要调整
|
||||||
VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState blend_attachment_state =
|
VkPipelineColorBlendAttachmentState blend_attachment_state =
|
||||||
vkb::initializers::pipeline_color_blend_attachment_state(
|
vkb::initializers::pipeline_color_blend_attachment_state(
|
||||||
0xf,
|
0xf,
|
||||||
VK_FALSE);
|
VK_FALSE);
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo color_blend_state =
|
VkPipelineColorBlendStateCreateInfo color_blend_state =
|
||||||
vkb::initializers::pipeline_color_blend_state_create_info(
|
vkb::initializers::pipeline_color_blend_state_create_info(
|
||||||
1,
|
1,
|
||||||
&blend_attachment_state);
|
&blend_attachment_state);
|
||||||
|
|
||||||
// Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept
|
// Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept
|
||||||
|
// 前景管线启用深度测试和写入
|
||||||
VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
|
VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
|
||||||
vkb::initializers::pipeline_depth_stencil_state_create_info(
|
vkb::initializers::pipeline_depth_stencil_state_create_info(
|
||||||
VK_TRUE,
|
VK_TRUE, // depthTestEnable
|
||||||
VK_TRUE,
|
VK_TRUE, // depthWriteEnable
|
||||||
VK_COMPARE_OP_GREATER);
|
VK_COMPARE_OP_GREATER); // Reversed depth buffer
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewport_state =
|
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 =
|
VkPipelineMultisampleStateCreateInfo multisample_state =
|
||||||
vkb::initializers::pipeline_multisample_state_create_info(
|
vkb::initializers::pipeline_multisample_state_create_info(
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
std::vector<VkDynamicState> dynamic_state_enables = {
|
std::vector<VkDynamicState> dynamic_state_enables = {
|
||||||
VK_DYNAMIC_STATE_VIEWPORT,
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
VK_DYNAMIC_STATE_SCISSOR};
|
VK_DYNAMIC_STATE_SCISSOR };
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamic_state =
|
VkPipelineDynamicStateCreateInfo dynamic_state =
|
||||||
vkb::initializers::pipeline_dynamic_state_create_info(
|
vkb::initializers::pipeline_dynamic_state_create_info(
|
||||||
dynamic_state_enables.data(),
|
dynamic_state_enables.data(),
|
||||||
static_cast<uint32_t>(dynamic_state_enables.size()),
|
static_cast<uint32_t>(dynamic_state_enables.size()),
|
||||||
0);
|
0);
|
||||||
|
|
||||||
// Load shaders
|
// Load shaders (确保你有对应的 SPIR-V 文件)
|
||||||
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages;
|
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[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);
|
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 = {
|
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 = {
|
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, 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, 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, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(TextureLoadingVertexStructure, normal)),
|
||||||
};
|
};
|
||||||
VkPipelineVertexInputStateCreateInfo vertex_input_state = vkb::initializers::pipeline_vertex_input_state_create_info();
|
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.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_input_bindings.size());
|
||||||
vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data();
|
vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data();
|
||||||
vertex_input_state.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attributes.size());
|
vertex_input_state.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attributes.size());
|
||||||
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data();
|
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data();
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipeline_create_info =
|
VkGraphicsPipelineCreateInfo pipeline_create_info =
|
||||||
vkb::initializers::pipeline_create_info(
|
vkb::initializers::pipeline_create_info(
|
||||||
pipeline_layout,
|
pipeline_layout, // 前景管线布局
|
||||||
render_pass,
|
render_pass,
|
||||||
0);
|
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.pInputAssemblyState = &input_assembly_state;
|
||||||
pipeline_create_info.pRasterizationState = &rasterization_state;
|
pipeline_create_info.pRasterizationState = &rasterization_state;
|
||||||
pipeline_create_info.pColorBlendState = &color_blend_state;
|
pipeline_create_info.pColorBlendState = &color_blend_state;
|
||||||
pipeline_create_info.pMultisampleState = &multisample_state;
|
pipeline_create_info.pMultisampleState = &multisample_state;
|
||||||
pipeline_create_info.pViewportState = &viewport_state;
|
pipeline_create_info.pViewportState = &viewport_state;
|
||||||
pipeline_create_info.pDepthStencilState = &depth_stencil_state;
|
pipeline_create_info.pDepthStencilState = &depth_stencil_state;
|
||||||
pipeline_create_info.pDynamicState = &dynamic_state;
|
pipeline_create_info.pDynamicState = &dynamic_state;
|
||||||
pipeline_create_info.stageCount = static_cast<uint32_t>(shader_stages.size());
|
pipeline_create_info.stageCount = static_cast<uint32_t>(shader_stages.size());
|
||||||
pipeline_create_info.pStages = shader_stages.data();
|
pipeline_create_info.pStages = shader_stages.data();
|
||||||
|
|
||||||
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &pipelines.solid));
|
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
|
// Prepare and initialize uniform buffer containing shader uniforms
|
||||||
void TextureLoading::prepare_uniform_buffers()
|
void TextureLoading::prepare_uniform_buffers()
|
||||||
{
|
{
|
||||||
// Vertex shader uniform buffer block
|
// Vertex shader uniform buffer block
|
||||||
uniform_buffer_vs = std::make_unique<vkb::core::BufferC>(get_device(),
|
uniform_buffer_vs = std::make_unique<vkb::core::BufferC>(get_device(),
|
||||||
sizeof(ubo_vs),
|
sizeof(ubo_vs),
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||||
|
|
||||||
update_uniform_buffers();
|
update_uniform_buffers();
|
||||||
}
|
}
|
||||||
@@ -378,7 +559,7 @@ void TextureLoading::prepare_uniform_buffers()
|
|||||||
void TextureLoading::update_uniform_buffers()
|
void TextureLoading::update_uniform_buffers()
|
||||||
{
|
{
|
||||||
// Vertex shader
|
// 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));
|
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 = 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);
|
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))
|
if (!ApiVulkanSample::prepare(options))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//load_texture();
|
|
||||||
|
// --- 初始化 cam_text 纹理对象 ---
|
||||||
|
// 注意:这里只是初始化结构体,图像内存等由外部函数分配
|
||||||
|
// cam_text = {0}; // 已在构造函数或销毁时重置
|
||||||
|
|
||||||
|
// --- 加载前景纹理 (示例) ---
|
||||||
int width = 640;
|
int width = 640;
|
||||||
int height = 480;
|
int height = 480;
|
||||||
int rowStride;
|
int rowStride;
|
||||||
|
|
||||||
auto testImage = generateSimpleTestImage(width, height, &rowStride);
|
auto testImage = generateSimpleTestImage(width, height, &rowStride);
|
||||||
size_t dataSize = testImage.size();
|
size_t dataSize = testImage.size();
|
||||||
|
|
||||||
std::cout << "Generated test image: " << width << "x" << height << std::endl;
|
std::cout << "Generated test image: " << width << "x" << height << std::endl;
|
||||||
std::cout << "Row stride: " << rowStride << std::endl;
|
std::cout << "Row stride: " << rowStride << std::endl;
|
||||||
std::cout << "Data size: " << dataSize << " bytes" << std::endl;
|
std::cout << "Data size: " << dataSize << " bytes" << std::endl;
|
||||||
|
|
||||||
processWithVulkan(testImage.data(), width, height, 1, rowStride, dataSize, texture);
|
processWithVulkan(testImage.data(), width, height, 1, rowStride, dataSize, texture);
|
||||||
|
|
||||||
|
// --- 生成前景几何体 ---
|
||||||
generate_quad();
|
generate_quad();
|
||||||
|
|
||||||
|
// --- 准备资源 ---
|
||||||
prepare_uniform_buffers();
|
prepare_uniform_buffers();
|
||||||
setup_descriptor_set_layout();
|
setup_descriptor_set_layout(); // 前景 DSL
|
||||||
prepare_pipelines();
|
setup_descriptor_set_layout_bg(); // 背景 DSL
|
||||||
setup_descriptor_pool();
|
prepare_pipelines(); // 前景管线
|
||||||
setup_descriptor_set();
|
prepare_pipeline_bg(); // 背景管线
|
||||||
|
setup_descriptor_pool(); // 描述符池 (已更新大小)
|
||||||
|
setup_descriptor_set(); // 前景 DS
|
||||||
|
setup_descriptor_set_bg(); // 背景 DS
|
||||||
|
|
||||||
build_command_buffers();
|
build_command_buffers();
|
||||||
prepared = true;
|
prepared = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -430,7 +619,10 @@ void TextureLoading::render(float delta_time)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture.width == 0)
|
// 可以在这里添加逻辑来更新 cam_text 纹理
|
||||||
|
// 例如,如果 cam_text.image != VK_NULL_HANDLE,调用 updateTexture
|
||||||
|
|
||||||
|
if (texture.width == 0) // 检查前景纹理
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -443,7 +635,7 @@ void TextureLoading::view_changed()
|
|||||||
update_uniform_buffers();
|
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"))
|
if (drawer.header("Settings"))
|
||||||
{
|
{
|
||||||
@@ -459,10 +651,18 @@ std::unique_ptr<vkb::Application> create_texture_loading()
|
|||||||
return std::make_unique<TextureLoading>();
|
return std::make_unique<TextureLoading>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 外部函数保持不变
|
||||||
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize)
|
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize)
|
||||||
{
|
{
|
||||||
TextureLoading::Texture& cam_texture = TextureLoading::Get()->cam_text;
|
if (TextureLoading::Get()) {
|
||||||
TextureLoading::Get()->processWithVulkan(data, width, height, format, rowStride, dataSize, cam_texture);
|
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();
|
const VkPhysicalDevice& physicalDevice = get_device().get_gpu().get_handle();
|
||||||
if (out_texture.image == VK_NULL_HANDLE) {
|
if (out_texture.image == VK_NULL_HANDLE) {
|
||||||
createTexture(device, physicalDevice, width, height, format, out_texture);
|
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();
|
const VkCommandPool& commandPool = get_device().get_command_pool().get_handle();
|
||||||
updateTexture(device, physicalDevice, commandPool, queue, data, width, height,
|
updateTexture(device, physicalDevice, commandPool, queue, data, width, height,
|
||||||
rowStride, dataSize, out_texture);
|
rowStride, dataSize, out_texture);
|
||||||
|
// 如果纹理被更新,并且管线已经准备好,可能需要重建命令缓冲区
|
||||||
|
// 这取决于你的应用逻辑。简单起见,在外部函数中处理。
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- 以下函数保持不变 ---
|
||||||
void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||||
int width, int height, int format, Texture& texture) {
|
int width, int height, int format, Texture& texture) {
|
||||||
|
|
||||||
@@ -489,7 +696,7 @@ void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDev
|
|||||||
VkImageCreateInfo imageInfo = {};
|
VkImageCreateInfo imageInfo = {};
|
||||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
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.width = width;
|
||||||
imageInfo.extent.height = height;
|
imageInfo.extent.height = height;
|
||||||
imageInfo.extent.depth = 1;
|
imageInfo.extent.depth = 1;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ktx.h>
|
#include <ktx.h>
|
||||||
|
|
||||||
#include "api_vulkan_sample.h"
|
#include "api_vulkan_sample.h"
|
||||||
|
|
||||||
|
// 顶点结构保持不变,因为背景 quad 可能不需要顶点缓冲区
|
||||||
struct TextureLoadingVertexStructure
|
struct TextureLoadingVertexStructure
|
||||||
{
|
{
|
||||||
float pos[3];
|
float pos[3];
|
||||||
@@ -14,7 +14,7 @@ struct TextureLoadingVertexStructure
|
|||||||
|
|
||||||
class TextureLoading : public ApiVulkanSample
|
class TextureLoading : public ApiVulkanSample
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Texture
|
struct Texture
|
||||||
{
|
{
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
@@ -26,8 +26,8 @@ class TextureLoading : public ApiVulkanSample
|
|||||||
uint32_t mip_levels;
|
uint32_t mip_levels;
|
||||||
};
|
};
|
||||||
|
|
||||||
Texture texture = {0};
|
Texture texture = { 0 };
|
||||||
Texture cam_text = {0};
|
Texture cam_text = { 0 }; // 将由外部函数初始化
|
||||||
|
|
||||||
std::unique_ptr<vkb::core::BufferC> vertex_buffer;
|
std::unique_ptr<vkb::core::BufferC> vertex_buffer;
|
||||||
std::unique_ptr<vkb::core::BufferC> index_buffer;
|
std::unique_ptr<vkb::core::BufferC> index_buffer;
|
||||||
@@ -45,47 +45,56 @@ class TextureLoading : public ApiVulkanSample
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
VkPipeline solid;
|
VkPipeline solid; // 原有前景管线
|
||||||
|
VkPipeline background; // 新增背景管线
|
||||||
} pipelines;
|
} pipelines;
|
||||||
|
|
||||||
VkPipelineLayout pipeline_layout;
|
// 管线布局
|
||||||
VkDescriptorSet descriptor_set;
|
VkPipelineLayout pipeline_layout; // 前景管线布局
|
||||||
VkDescriptorSetLayout descriptor_set_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() {
|
static TextureLoading* Get() {
|
||||||
return loadTextIns;
|
return loadTextIns;
|
||||||
}
|
}
|
||||||
static TextureLoading* loadTextIns;
|
static TextureLoading* loadTextIns;
|
||||||
|
|
||||||
TextureLoading();
|
TextureLoading();
|
||||||
~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 build_command_buffers() override;
|
||||||
void draw();
|
void draw();
|
||||||
void generate_quad();
|
void generate_quad(); // 生成前景 quad
|
||||||
void setup_descriptor_pool();
|
void setup_descriptor_pool();
|
||||||
void setup_descriptor_set_layout();
|
void setup_descriptor_set_layout();
|
||||||
|
void setup_descriptor_set_layout_bg(); // 新增:设置背景描述符集布局
|
||||||
void setup_descriptor_set();
|
void setup_descriptor_set();
|
||||||
|
void setup_descriptor_set_bg(); // 新增:设置背景描述符集
|
||||||
void prepare_pipelines();
|
void prepare_pipelines();
|
||||||
|
void prepare_pipeline_bg(); // 新增:准备背景管线
|
||||||
void prepare_uniform_buffers();
|
void prepare_uniform_buffers();
|
||||||
void update_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 render(float delta_time) override;
|
||||||
virtual void view_changed() 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);
|
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 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 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);
|
||||||
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);
|
||||||
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
|
||||||
VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
|
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
|
||||||
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();
|
std::unique_ptr<vkb::Application> create_texture_loading();
|
||||||
Reference in New Issue
Block a user