伽马 (Direct3D 9)

纹理内容通常以 sRGB 格式存储。 传统上,像素管道假定颜色是线性的,因此在线性空间中执行混合操作。 但是,由于 sRGB 内容经过伽玛校正,因此线性空间中的混合操作将产生不正确的结果。 视频卡现在可以通过在读取 sRGB 内容时撤消伽玛校正来修复此问题,并在写出像素时将像素数据转换回 sRGB 格式。 此时,像素管道中的所有操作就都是在线性空间中执行的了。

灰度校正

Direct3D 9 可以:

  • 指示纹理是否经过了伽马 2.2 校正(sRGB 或其他格式)。 驱动程序将转换为线性伽马,以便在 SetTexture 时执行混合操作,或者采样器将在查找时将数据转换为线性数据。
  • 指示在向呈现器目标写出像素时,像素管道是否应伽马校正回 sRGB 空间。

所有其他颜色(透明颜色、材质颜色、顶点颜色等)都假定在线性空间中。 应用程序可以使用像素着色器指令对写入帧缓冲区的颜色进行伽玛校正。 线性化应仅应用于 RGB 通道,而非 alpha 通道。

并非所有图面格式都可以线性化。 只有 CheckDeviceFormat 传回 D3DUSAGE_QUERY_SRGBREAD 的格式才能线性化。 其余格式将忽略采样器状态D3DSAMP_SRGBTEXTURE。 只有无符号纹理格式才支持这种转换。 无符号纹理格式仅包括 R、G、B 和 L 组件。 如果存在 alpha 通道,则会忽略它。 如果混合格式支持 sRGB 线性化,则仅会影响无符号通道。 理想情况下,硬件应在筛选之前执行线性化,但在 Direct3D 9 中,硬件可以在筛选后执行线性化。

并非所有图面格式都可以在 sRGB 空间写入。 只有 CheckDeviceFormat 传回使用标志 D3DUSAGE_QUERY_SRGBWRITE 的格式才能线性化。 其余格式将忽略呈现器状态D3DRS_SRGBWRITEENABLE。 每个通道的 8 位 RGB 无符号格式应支持此功能。

理想情况下,硬件应在线性空间中执行帧缓冲区混合操作,但允许硬件在像素着色器之后但在帧缓冲区混合器之前执行此操作。 这意味着在 sRGB 空间中发生的帧缓冲区混合操作将产生不正确的结果。 在清除呈现器目标时,会处理 D3DRS_SRGBWRITEENABLE。 对于支持多呈现器目标 (Direct3D 9)多元素纹理 (Direct3D 9) 的硬件,仅会写入第一个呈现器目标或元素。

API 更改

// New sampler state (DWORD)
// If this is nonzero, the texture is linearized on lookup.
D3DSAMP_SRGBTEXTURE       // Default FALSE

// New render state (DWORD)
D3DRS_SRGBWRITEENABLE     // Default FALSE

// New usage flags
D3DUSAGE_QUERY_SRGBWRITE
D3DUSAGE_QUERY_SRGBREAD

窗口化交换链

为了实现正确的混合操作,应用程序在线性空间中保留交换链的后台缓冲区是很有价值的。 由于桌面通常并不在线性空间中,因此在呈现后台缓冲区的内容之前需要进行伽玛校正。 应用程序可以通过分配其他缓冲区并执行从线性缓冲区到后台缓冲区的校正复制来影响这种校正。 此法还需要额外进行复制,而如果驱动程序在表示位块中执行伽玛校正,则可以避免这种复制。

在 Direct3D 9 中,为表示提供了一个新标志 D3DPRESENT_LINEAR_CONTENT,这样表示即可从线性空间隐式转换为 sRGB/伽马 2.2。 如果后台缓冲区格式为 16 位浮点,则应用程序应指定此标志,以便将窗口模式表示与全屏伽玛行为相匹配,前提是为通过 GetDeviceCaps 检索的设备功能返回 D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION。

帧缓冲区