为什么 vulkan 交换链更喜欢非 SRGB 格式?

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

在Vulkan立方体示例中,选择表面格式的方法是:

vk::SurfaceFormatKHR Demo::pick_surface_format(const std::vector<vk::SurfaceFormatKHR> &surface_formats) {
// Prefer non-SRGB formats...
for (const auto &surface_format : surface_formats) {
    const vk::Format format = surface_format.format;

    if (format == vk::Format::eR8G8B8A8Unorm || format == vk::Format::eB8G8R8A8Unorm ||
        format == vk::Format::eA2B10G10R10UnormPack32 || format == vk::Format::eA2R10G10B10UnormPack32 ||
        format == vk::Format::eR16G16B16A16Sfloat) {
        return surface_format;
    }
}

printf("Can't find our preferred formats... Falling back to first exposed format. Rendering may be incorrect.\n");

assert(surface_formats.size() >= 1);
return surface_formats[0];

}

为什么我们更喜欢非 SRGB 格式,大多数屏幕不都期待 SRGB 格式吗?

graphics vulkan
1个回答
4
投票

您问题的答案是:您通常更喜欢交换链图像的非 sRGB 格式。 您的怀疑是完全有道理的:有问题的代码可以说没有显示最佳实践方法。考虑图 1,它显示了捕获图像、以低动态范围 (LDR) 格式存储图像并通过计算机显示器显示图像时所涉及的基本转换阶段。

图 1: 显然,物理辐射处于线性空间(最左边的阶段)。当我们捕获图像时,我们通常希望将其存储为 LDR 格式(例如,每个颜色通道 8 位甚至更少),以充分利用存储空间(“LDR 图像”阶段)。无论显示器输出什么亮度,都必须再次处于线性空间中,否则我们就会扭曲颜色值(最右边的阶段)。由于大多数(全部?)显示器仅支持 LDR 帧缓冲区格式,因此它们会在发出相应的辐射(显示器阶段)之前对帧缓冲区颜色值应用伽玛校正。

即,您的显示器需要伽玛空间作为输入。
所以,是的,正确的方法是将 sRGB 格式发送到您的显示器。

事实上,检查 gpuinfo.org 并按

COLOR_ATTACHMENT
支持对列表进行排序,可以发现 sRGB 格式是最常支持的格式。以下是支持的前四种格式:

  • B8G8R8A8_SRGB
    :99.88%
  • A8B8G8R8_SRGB_PACK32
    :99.72%
  • R8G8B8A8_SRGB
    :99.48%
  • B8G8R8A8_UNORM
    :99.44%

所以,我想说,默认为 sRGB 格式!

P.S.:如果您想知道为什么使用 LDR 图像格式有意义,请查看 图 2 获取解释!

图 2: 顶行显示均匀分布的条形图。物理光强度。这意味着,每个相邻条之间发射的光子量增加相同的量。底行显示均匀分布的条形图。感知光强度——物理光强度的增加对应图1所示的伽玛曲线。换句话说,我们只需要在较暗的区域添加一些光子即可使感知的光强度发生巨大变化。对于较亮的区域,我们必须添加大量光子以获得相同的感知光强度相对差异。因此,存储图像时,为较暗的颜色分配相对较多的位,为较亮的颜色分配较少的位,以便最佳地使用可用位是有意义的。人类视觉系统。

© www.soinside.com 2019 - 2024. All rights reserved.