通议灵码修改过的。
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user