我正在编写一个 Vulkan 图形引擎,我已经将以下 .PNG 渲染到屏幕上
.PNG 的背景是透明的,但这不会出现在我的 Vulkan 应用程序中。
这里是相关代码:
bool vk::Vulkan_Buffers::createTextureBuffer(PhysicalDevice& physicalDevice, Image& image, int index) {
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
size_t imageSize = (sizeof(((Uint32*)image.getSurface()->pixels)[0])) * (image.getSurface()->w * image.getSurface()->h);
createBuffer(physicalDevice, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(physicalDevice.logicalDevice.handle, stagingBufferMemory, 0, imageSize, 0, &data);
memcpy(data, image.getSurface()->pixels, imageSize);
vkUnmapMemory(physicalDevice.logicalDevice.handle, stagingBufferMemory);
//transition to the correct image format
transitionImageLayout(physicalDevice, physicalDevice.logicalDevice.images[index], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyBufferToImage(physicalDevice, stagingBuffer, physicalDevice.logicalDevice.images[index], static_cast<uint32_t>(image.getDimentions().x), static_cast<uint32_t>(image.getDimentions().y));
transitionImageLayout(physicalDevice, physicalDevice.logicalDevice.images[index], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vkDestroyBuffer(physicalDevice.logicalDevice.handle, stagingBuffer, nullptr);
vkFreeMemory(physicalDevice.logicalDevice.handle, stagingBufferMemory, nullptr);
return true;
}
bool vk::Vulkan_Buffers::createImage(PhysicalDevice& physicalDevice, std::vector<Image>& images, int index) {
physicalDevice.logicalDevice.images.resize(physicalDevice.logicalDevice.images.size() + 1);
physicalDevice.logicalDevice.imagesMemory.resize(physicalDevice.logicalDevice.imagesMemory.size() + 1);
VkImageCreateInfo imageCreateInfo{};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.extent.width = static_cast<uint32_t>(images[index].getDimentions().x);
imageCreateInfo.extent.height = static_cast<uint32_t>(images[index].getDimentions().y);
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.flags = 0;
if (vkCreateImage(physicalDevice.logicalDevice.handle, &imageCreateInfo, nullptr, &physicalDevice.logicalDevice.images[index]) == VK_SUCCESS) {
PRINTSUCSESS("VULKAN IMAGE CREATED");
}
else {
PRINTERROR("VULKAN IMAGE FAILED TO BE CREATED");
}
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(physicalDevice.logicalDevice.handle, physicalDevice.logicalDevice.images[index], &memoryRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memoryRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,physicalDevice);
if (vkAllocateMemory(physicalDevice.logicalDevice.handle, &allocInfo, nullptr, &physicalDevice.logicalDevice.imagesMemory[index]) != VK_SUCCESS) {
PRINTERROR("MEMORY FAILED TO BE ALLOCATED");
}
vkBindImageMemory(physicalDevice.logicalDevice.handle, physicalDevice.logicalDevice.images[index], physicalDevice.logicalDevice.imagesMemory[index], 0);
return true;
}
bool vk::Vulkan_Image::createGraphicsImageView(PhysicalDevice& physicalDevice,int index) {
physicalDevice.logicalDevice.graphicImageViews.resize(physicalDevice.logicalDevice.graphicImageViews.size() + 1);
VkImageViewCreateInfo imageViewCreateInfo{};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.image = physicalDevice.logicalDevice.images[index];
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
imageViewCreateInfo.subresourceRange.levelCount = 1;
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 1;
imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
if (vkCreateImageView(physicalDevice.logicalDevice.handle, &imageViewCreateInfo, nullptr, &physicalDevice.logicalDevice.graphicImageViews[index]) == VK_SUCCESS) {
PRINTSUCSESS("CREATED GRAPHICS IMAGE VIEW");
return true;
}
else {
PRINTERROR("FAILED TO CREATE GRAPHICS IMAGE VIEW");
return false;
}
}
bool vk::Vulkan_Image::createSampler(PhysicalDevice& physicalDevice, int index) {
physicalDevice.logicalDevice.samplers.resize(physicalDevice.logicalDevice.samplers.size() + 1);
VkSamplerCreateInfo samplerCreateInfo{};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.anisotropyEnable = VK_TRUE;
samplerCreateInfo.maxAnisotropy = physicalDevice.deviceProperties.limits.maxSamplerAnisotropy;
samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
samplerCreateInfo.compareEnable = VK_FALSE;
samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 0.0f;
if (vkCreateSampler(physicalDevice.logicalDevice.handle, &samplerCreateInfo, nullptr, &physicalDevice.logicalDevice.samplers[index]) == VK_SUCCESS) {
PRINTSUCSESS("SAMPELER CREATED");
return true;
}
else {
PRINTERROR("SAMPELER FAILED TO BE CREATED");
return false;
}
}
这是来自图形管道的颜色混合代码:
//Colour blending
VkPipelineColorBlendAttachmentState colorBlendAttachmentInfo{};
colorBlendAttachmentInfo.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachmentInfo.blendEnable = VK_TRUE;
colorBlendAttachmentInfo.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachmentInfo.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachmentInfo.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachmentInfo.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachmentInfo.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachmentInfo.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlendingInfo{};
colorBlendingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlendingInfo.logicOpEnable = VK_TRUE;
colorBlendingInfo.logicOp = VK_LOGIC_OP_COPY;
colorBlendingInfo.attachmentCount = 1;
colorBlendingInfo.pAttachments = &colorBlendAttachmentInfo;
colorBlendingInfo.blendConstants[0] = 0.0f;
colorBlendingInfo.blendConstants[1] = 0.0f;
colorBlendingInfo.blendConstants[2] = 0.0f;
colorBlendingInfo.blendConstants[3] = 0.0f;
如果您需要更多信息,请告诉我。
可能与
VkPipelineColorBlendStateCreateInfo
配置有关
在
VkPipelineColorBlendStateCreateInfo
结构中,您通过将logicOpEnable
设置为VK_TRUE
和logicOp
设置为VK_LOGIC_OP_COPY
来启用逻辑运算。这可能会干扰您在 VkPipelineColorBlendAttachmentState
中指定的混合操作。要解决此问题,您应该禁用逻辑运算。
更改颜色混合代码中的以下行:
colorBlendingInfo.logicOpEnable = VK_TRUE;
colorBlendingInfo.logicOp = VK_LOGIC_OP_COPY;
到
colorBlendingInfo.logicOpEnable = VK_FALSE;
colorBlendingInfo.logicOp = VK_LOGIC_OP_CLEAR; // This value doesn't matter when logicOpEnable is VK_FALSE
进行此更改后,您的透明背景应该正确显示,因为您在
VkPipelineColorBlendAttachmentState
中的混合操作已经设置为正确的 alpha 混合。