Vulkan 为图像添加透明度

问题描述 投票:0回答:1

我正在编写一个 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;

如果您需要更多信息,请告诉我。

c++ graphics rendering transparency vulkan
1个回答
0
投票

可能与

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 混合。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.