首页 > 解决方案 > 在片段着色器中显示格式为 VK_FORMAT_D24_UNORM_S8_UINT 的图像的深度

问题描述

语境

我目前正在尝试显示使用VK_FORMAT_D24_UNORM_S8_UINT.

如果我正确阅读了文档,这种格式将深度分量存储在 24 位浮点上(值介于0和之间1),并将深度存储在无符号 8 位整数上。


Vulkan 设置

我试图做的是首先使用复制此图像vkCmdCopyImage,并使用以下复制参数“仅提取深度”:

constexpr VkImageAspectFlags source_aspects = VK_IMAGE_ASPECT_DEPTH_BIT
                                              | VK_IMAGE_ASPECT_STENCIL_BIT;

constexpr VkImageAspectFlags destination_aspects = VK_IMAGE_ASPECT_DEPTH_BIT;

const VkImageCopy COPY_INFORMATION =
{
    .srcSubresource =
    {
        .aspectMask     = source_aspects,
        .mipLevel       = 0,
        .baseArrayLayer = 0,
        .layerCount     = 1
    },
    .srcOffset =
    {
        .x = 0,
        .y = 0,
        .z = 0
    },
    .dstSubresource =
    {
        .aspectMask     = destination_aspects,
        .mipLevel       = 0,
        .baseArrayLayer = 0,
        .layerCount     = 1
    },
    .dstOffset =
    {
        .x = 0,
        .y = 0,
        .z = 0
    },
    .extent =
    {
        .width  = WIDTH,
        .height = HEIGHT,
        .depth  = 1
    }
};

GLSL 设置

然后我将它传递给片段着色器,如下所示:

#version 450

layout(set = 0, binding = 0) uniform sampler2D depth_sampler;


layout(location = 0) in vec2 screen_quad_position;


layout(location = 0) out vec4 fragment_colour;



void main()
{

    float depth = texture(depth_sampler , screen_quad_position).r;

    if(depth > 0.9999f)
    {
        discard;
    }

    fragment_colour = vec4(vec3((depth)),1);
}

相应的顶点着色器只是一个全屏三角形(因此实际上是一个全屏四边形),正如 Sacha Willems 先生所描述

#version 450

layout(location = 0) out vec2 screen_quad_position;

out gl_PerVertex{vec4 gl_Position;};

void main()
{
    screen_quad_position = vec2(gl_VertexIndex & 2 , (gl_VertexIndex << 1) & 2);
    gl_Position          = vec4(screen_quad_position * 2.0f - 1.0f, 0.0f, 1.0f);
}

结果

这确实产生了一个与我正在渲染的形状相对应的输出(带有背面剔除的单一立方体,逆时针三角形顺序):

得到的结果

不要介意边框不对称,我懒得正确截屏。

但我宁愿期待这样的事情:

预期结果


对问题原因的猜测

我的猜测是 glslfloat存储在 32 位(如果我没有误解这个页面),但由于深度是 24 位浮点,这完全与显示的值混淆。


最后,问题:

假设我无法更改深度模板图像的格式VK_FORMAT_D24_UNORM_S8_UINT,那么在片段着色器中使用格式显示图像深度的正确方法是什么?

以更一般的方式,显示此​​类图像的正确方法是什么(“选择VK_FORMAT_D32_SFLOAT”的解决方案当然是微不足道的)。

如果我忘记输入任何相关信息,请告诉我。

标签: cglslvulkan

解决方案


推荐阅读