Vulkan之DepthBuffer

深度缓冲

显示中的场景都是3d的,但是我们的图像只能展示2d的,这就必然会导致一些图元被另一些图元所盖住。而我们在渲染时是按照图元来渲染的,这就会导致一个问题,后渲染的图元会覆盖前面渲染的图元,但是有可能后渲染的图元在现实世界中是被前面图元覆盖的,这样就导致了渲染的错误,因此深度缓冲就是解决这个问题而存在的。

现实世界中的物体是3d的,因此它的世界坐标也是3d的。因此它的z坐标就可以表示物体的深度。

在vulkan中添加深度缓冲一般有如下的步骤

  • 1、创建深度图像资源
  • 2、将深度图像视图添加到FrameBuffer中
  • 3、创建深度attachment
  • 4、在pipeline里面启动深度测试

剩下的事情,vulkan会自己处理。

1)生成深度图像资源:

深度附件是基于图像的,就像颜色附件。所不同的是交换链不会自动创建深度图像。我们仅需要一个深度图像,因为每次只有一个绘制操作。跟之前一样,在vulkan中创建图像的三件套:图像,内存和图像视图。

1
2
3
VkImage depthImage;
VkDeviceMemory depthImageMemory;
VkImageView depthImageView;

1
2
3
4
5
6
void createDepthResources() {
VkFormat depthFormat = findDepthFormat();

createImage(swapChainExtent.width, swapChainExtent.height, 1, msaaSamples, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
}

2)将深度图像视图作为附件添加到FrameBuffer中

1
2
3
4
std::array<VkImageView, 3> attachments = {
depthImageView,
swapChainImageViews[i]
};

3)在renderpass添加depthAttachment的引用

1
2
3
VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 0;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1
2
3
4
5
6
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
subpass.pResolveAttachments = &colorAttachmentResolveRef;

4)pipeline中开启深度测试:

1
2
3
4
5
6
7
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;

5)资源销毁

1
2
3
vkDestroyImageView(device, depthImageView, nullptr);
vkDestroyImage(device, depthImage, nullptr);
vkFreeMemory(device, depthImageMemory, nullptr);
显示 Gitment 评论