微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Vulkan 交换链格式 UNORM 与 SRGB?

如何解决Vulkan 交换链格式 UNORM 与 SRGB?

在 Vulkan 程序中,片段着色器通常将 0.0 到 1.0 范围内的单精度浮点颜色输出到每个红/蓝/绿通道,然后将这些颜色写入(混合到)交换链图像中,然后呈现在屏幕上。浮点值根据交换链图像的格式(在创建交换链时指定)编码为位。

当我将交换链格式从 VK_FORMAT_B8G8R8A8_UnorM 更改为 VK_FORMAT_B8G8R8A8_SRGB 时,我观察到帧的整体亮度大大增加,并且还有一些细微的颜色偏移。

我对 SRGB 格式的理解是,它很像 UnorM 格式,只是具有不同的浮点值到 8 位整数的映射,因此它在某些区域具有更高的颜色分辨率,而在其他区域则更低,但是“预编码”RGB浮点值的实际含义保持不变。

所以我对亮度增加感到有点惊讶。我对 SRGB 编码的理解有误吗?和/或与 UnorM 相比,预期亮度会增加吗?

或者也许我有一个错误并且亮度不会增加

更新:

我观察到,如果我使用 SRGB 交换链图像并且还以 VK_FORMAT_B8G8R8A8_SRGB 格式而不是 VK_FORMAT_B8G8R8A8_UnorM 格式加载我的图像/纹理,那么额外的亮度就会消失。它看起来就像我使用 VK_FORMAT_B8G8R8A8_UnorM 交换链图像并以 VK_FORMAT_B8G8R8A8_UnorM 格式加载我的图像/纹理一样。

此外,如果我将交换链图像放入 VK_FORMAT_B8G8R8A8_UnorM 格式,然后使用 VK_FORMAT_B8G8R8A8_SRGB 加载图像/纹理,则帧看起来特别暗/几乎是黑色。

清楚地了解正在发生的事情会有所帮助。

解决方法

这是色彩空间和显示问题。

假定片段着色器在线性 RGB 颜色空间中写入值。因此,如果您要渲染具有线性 RGB 色彩空间 (UNORM) 的图像,则直接解释 FS 生成的值。当您渲染具有 sRGB 色彩空间的图像时,您将值从一个空间(线性)写入另一个空间 (sRGB)。因此,这些值会自动转换为 sRGB 色彩空间。这与将位置从模型空间转换到世界空间或其他什么没有什么不同。

不同之处在于您一直错误地查看您的场景。看,您的交换链的 VkSurfaceFormat::colorSpace 值为 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR 的可能性非常大。

VkSurfaceFormat::colorspace 告诉您显示引擎将如何解释您呈现的交换链图像中的像素数据。这不是您提供的设置;这是显示引擎告诉您有关将如何解释您发送的值的信息。

我说它是 sRGB“几率非常好”,因为在扩展之外,这是唯一可能的值。无论您喜欢与否,您都在渲染到 sRGB 显示设备。

因此,如果您写入 UNORM 图像,显示设备将读取数据的实际位并将它们解释为就好像它们在 sRGB 色彩空间中一样。仅当您的片段着色器本身写入的数据在 sRGB 色彩空间中时,此操作才有意义。

然而,这通常不是 FS 生成数据的方式。您计算的照明计算仅对线性 RGB 颜色空间中的颜色值有意义。因此,除非您编写 FS 以在计算最终颜色值后故意进行 sRGB 转换,否则所有结果都在线性 RGB 颜色空间中的可能性很大。这就是您一直在写入帧缓冲区的内容。

然后显示引擎破坏它

通过使用 sRGB 图像作为目标,您可以强制将颜色空间从线性 RGB 转换为 sRGB,然后显示引擎会将其解释为 sRGB 值。这意味着您的照明方程最终会产生正确的结果

未能执行 gamma-correct rendering properly (including the source texture images which are almost certainly also in the sRGB colorspace,as this is the default colorspace for most image editors. The exceptions would be for things like gloss-maps,normal maps,or other images that aren't storing "colors".) 导致 linear light attention appears more correct than quadratic attenuation,even though quadratic is how reality works 的情况。

,

这是伽马校正。

将交换链与 VK_FORMAT_B8G8R8A8_SRGB 结合使用,可以利用将伽马校正应用为渲染管道中的最后一步的能力。这会在幕后自动发生。

这是您希望进行伽马校正的唯一地方。确保您的着色器没有应用伽马校正。您可能将其视为:

color = pow(color,vec3(1.0/2.2));

如果您的交换链进行了伽马校正,则无需在着色器中进行。

默认情况下,您加载的所有图像都可以安全地假设它们是 SRGB。作为 SRGB,只需使用 VK_FORMAT_R8G8B8A8_SRGB 格式加载它们。 (请注意,有些图像可能无法保存为 SRGB,但我不知道有任何格式可以保存)

这很好地解释了它: https://docs.rs/vulkano/0.7.1/vulkano/swapchain/enum.ColorSpace.html

特别引用它:

  • 在创建交换链时始终请求SrgbNonLinear色彩空间。
  • 确保所有图像文件都使用sRGB色彩空间(保存方​​式),并将它们加载到 em>格式带有 Srgb 后缀。仅将非 sRGB 图像格式用于中间计算或存储非颜色数据。
  • Swapchain 图像的格式应该带有 Srgb 后缀

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。