转换颜色空间的数据

要撰写到屏幕或执行浮点操作,你需要在正确的颜色空间中工作。 我们建议在线性颜色空间中执行浮点操作。 然后,要将图像呈现到屏幕,请将数据转换为标准 RGB 数据(sRGB、gamma 2.2 矫正)颜色空间。 在 sRGB 颜色空间中呈现到屏幕对于颜色准确度非常重要。 如果图像未经过 gamma 2.2 矫正,则会分配过多位或太多带宽到用户无法区分的高光,而对于人们敏感的阴影值则会分配太少的位或带宽,因此需要更多位或带宽来保持相同的视觉质量。 因此,为了确保最佳颜色准确度,请向屏幕呈现经 gamma 2.2 矫正的图像。

严格地说,实际的 sRGB 传输函数是一个分片公式(线性段 + 2.4 功率),这与原始 2.2 功率 gamma 略有不同。 但为了简单起见,我们将互换使用这些术语。

颜色精度

为了进行呈现,整数值显示格式(如 DXGI_FORMAT_B8G8R8A8_UNORM_SRGBDXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM 等)始终包含 sRGB gamma 矫正的数据。 浮值显示格式(目前仅为 DXGI_FORMAT_R16G16B16A16_FLOAT)包含线性值数据。

_SRGB 格式修饰符向操作系统指示,帮助应用在屏幕上放置 sRGB 数据。 即使数据的格式名称中没有此格式修饰符,应用也必须始终将 sRGB 数据放置到具有整数值格式的后台缓冲区中,才能将 sRGB 数据呈现到屏幕。 有关显示扫描输出格式的完整列表:

使用绑定到管道的 _SRGB 格式修饰符将像素着色器中的浮点输出值写入呈现目标视图 (RenderTargetViews) 时,可将它们转换为经 gamma 2.2 矫正的颜色空间。 同样,当具有 _SRGB 格式修饰符的着色器资源视图 (ShaderResourceViews) 绑定到管道时,从 ShaderResourceViews 读取这些值时,可以将值从经 gamma 2.2 矫正的颜色空间转换为线性颜色空间。 然后,着色器可以对它们执行操作。

例如,使用类似于下面的代码将着色器中的浮点输出值写入 RenderTargetView 格式:

struct PSOut
{
    float4 color : SV_Target;
};

PSOut S( PSIn input )
{
    PSOut output;
    output.color = float4( 1.0, 0.0, 0.0, 1.0 );
    return output;
}

当“S”例程返回时,浮点 (1, 0, 0, 1) 值将转换为 RenderTargetView 格式。 然后,如果将 _SRGB 格式修饰符分配给 RenderTargetView,则会发生 gamma 转换。

以下是要遵循的步骤,用于确保屏幕上显示的内容具有最佳的颜色准确度。

要确保管道中的颜色准确度

  1. 如果纹理包含 sRGB 内容,请确保 ShaderResourceView 具有 _SRGB 格式修饰符,因此从 ShaderResourceView 读取到着色器时,可以将纹理内容从 gamma 2.2 矫正的颜色空间转换为线性颜色空间。
  2. 确保 RenderTargetView 还具有 _SRGB 格式修饰符,以便着色器输出值经过 gamma 转换。

如果执行上述步骤,则调用 IDXGISwapChain1::Present1 方法时,屏幕上显示的内容具有最佳颜色准确度。

可以使用 ID3D11Device::CreateRenderTargetView 方法从仅使用 DXGI_FORMAT_*_UNORM 格式创建的交换链的后台缓冲区上创建 DXGI_FORMAT_*_SRGB 视图。 对于创建呈现目标视图的规则来说,这是一个特殊例外,即,仅当创建想要使用 DXGI_FORMAT_*_TYPELESS 查看的资源时,才能将不同的格式用于 ID3D11Device::CreateRenderTargetView

有关数据转换规则的详细信息,请参阅数据转换规则

有关如何同时读取和写入纹理的信息,请参阅解压缩和打包 DXGI_FORMAT 以进行就地图像编辑

使用翻转模型、脏矩形和滚动区域增强呈现