使用伽玛更正

伽马更正或伽马(简称)是非线性操作的名称,系统用于对图像中的像素值进行编码和解码。

伽马是什么,它是什么?

在图形管道的末尾,图像离开计算机以沿着监视器电缆进行其旅程,有一小块硬件可以动态转换像素值。 此硬件通常使用查阅表格来转换像素。 此硬件使用从表面显示的红色、绿色和蓝色值来查找表中的伽玛更正值,然后将更正的值发送到监视器,而不是实际表面值。 因此,此查阅表格是将任何颜色替换为任何其他颜色的机会。 虽然表具有该级别的功率,但典型的用法是巧妙地调整图像,以补偿监视器响应的差异。 监视器的响应是将像素的数值与该像素的显示亮度相关的红色、绿色和蓝色组件的函数。

这就是这个表格的目的,但游戏开发者发现创造性地使用它,比如闪烁整个屏幕红色以心理效果。 在现代游戏应用中,作为每个帧帖子处理的一部分,我们通常提供其他方法来执行此类操作。 事实上,我们建议单独离开伽玛表,因为它可能用于校准监视器的响应,对伽马坡的批发更改将破坏这种仔细的校准。

确定伽马修正的科学很复杂,除了照亮“伽玛”名称来自何处之外,这里没有展示。 CRT (,即旧式玻璃) 监视器的响应是一个复杂的功能,但这些监视器的物理特性意味着它们表现出一个可由此电源函数粗略表示的响应:

亮度 (输入) = inputgamma

gamma 值通常接近 2.0 的值。 液晶显示器和所有其他较新的技术专门设计为表现出类似的响应,因此,我们所有的软件和图像都不必为这些新技术重新调整。 sRGB 标准声明此伽马值正好为 2.2,此值已成为广泛实现的标准。

人眼还有一个响应函数,它大约反转了 CRT 电源函数。 这意味着,像素的感知亮度与该像素中的 RGB 值大致呈线性上升。

由于 2.2 的伽马值已成为事实标准,因此我们通常不需要担心此表中编码的伽马曲线,并且可以将其保留为线性的一对一映射。 当然,适当的颜色匹配确实需要对此功能进行精致的护理,但讨论超出了本主题的范围。 Windows包含一个工具,允许用户将显示器校准为 gamma 2.2,此工具使用查阅表格硬件为其计算机派生精心选择的细微调整。 用户可以通过搜索“校准颜色”来运行此工具。 对于自动执行此过程的特定监视器,还有定义完善的颜色配置文件。 “校准颜色”工具可以检测这些较新的监视器,并通知用户校准已到位。

将权力法编码为颜色值的概念在图形管道中的其他位置也很有用,尤其是在纹理中。 对于纹理,由于我们刚才谈论的对数人眼反应,你希望更精确的深色颜色。 在管道的这一部分仔细处理 gamma 非常重要。 有关详细信息,请参阅 转换颜色空间的数据

本主题的其余部分仅重点介绍管道最后一部分的伽马更正(帧缓冲区数据和监视器)。 如果要编写校准向导或在全屏应用中创建特殊效果,其中帖子处理步骤不实用,下面是所需的信息。

Windows上伽玛的背景

Windows计算机通常具有一个伽玛表,该表是一个查找表,该表采用三重字节并输出三重字节。 这些三重组是 768 (256 x 3) 字节 RAM。 当显示格式包含 RGB BYTE 值的三倍,但不足以描述显示格式具有大于 [0,1] 范围的转换(如浮点值)时,这很好。 随着显示格式变得更加复杂,控制伽马Windows中的 API 已随着显示格式的演变而变化。

提供 gamma 控制的第一个Windows API 是Windows图形设备接口 (GDI) 的 SetDeviceGammaRampGetDeviceGammaRamp。 这些 API 使用三个 256 项 WORD 数组,每个 WORD 编码最多为 1,由 WORD 值 0 和 65535 表示。 WORD 的额外精度通常在实际的硬件查找表中不可用,但这些 API 旨在灵活。 与本部分后面所述的其他 API 相反,仅允许与标识函数稍有偏差。 事实上,渐变中的任何条目都必须在标识值的 32768 以内。 此限制意味着,任何应用都不能将显示器完全变为黑色或其他不可读颜色。

下一个 API 是 Microsoft Direct3D 9 的 SetGammaRamp,它遵循与 SetDeviceGammaRamp 相同的模式和数据格式。 Direct3D 9 gamma 渐变的默认值并不特别有用:它是初始化为 0-255,而不是 0-65535 的 WORD 的渐变,即使 API 在 0-65535 中定义也是如此。

最新的 API 是 IDXGIOutput::SetGammaControl。 此 API 具有更灵活的方案来表达 gamma 控件,因为适合 DXGI 增加的一组显示格式,包括每通道十个整数位、16 位浮点格式和XR_BIAS扩展范围格式。

所有这些 API 都在同一硬件上运行,并更改相同的值。 Direct3D 9 和 DXGI API 仅“写入”。 无法读取硬件的值,对其进行修改,然后设置它。 只能设置坡道。 此外,只能在应用全屏时设置 gamma。 此限制是保证桌面始终可读的另一种方法。 也就是说,应用可以干扰其自身的显示,但当应用失去全屏 ((例如,通过 alt-tab 或 ctrl-alt-del) )时,Windows将还原以前的伽马坡道。

显示硬件的演变

一些较新的监视器可以显示广泛的强度。 但是,当显示格式只能表示介于零和一之间的值时,显示必须将零映射到最暗的值,一个映射到最亮的值。 这种最亮的值可能太亮了,无法舒适地查看在白色背景上带有黑色文本的网页,但对于超亮的特殊效果非常出色,例如查看阳光从湖上闪闪发光或闪电照耀天空。 因此,我们需要一种方法来表达这些更广泛的范围。 DXGI 1.1 及更高版本包含显示格式值,允许 1.0 表示舒适的白色值,并为超亮的特殊效果保留更广泛的显示格式值。 DXGI 1.1 支持两种可表达这些更宽值的显示格式:DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM和 16 位浮点。 有关这些格式的完整讨论,请参阅 扩展格式的详细信息。 接下来,我们看看 DXGI 的 IDXGIOutput::SetGammaControl gamma API 需要大于 1.0 的像素值的原因。

DXGI 中的 Gamma 控制功能

DXGI 允许显示驱动程序将其 gamma 控件表示为一个分步线性函数。 此阶梯线性函数由此函数的控制点定义,函数可以转换为的值范围,以及可在转换后应用的附加可选刻度和偏移运算。 应用可以调用 IDXGIOutput::GetGammaControlCapabilities 方法,以检索 DXGI_GAMMA_CONTROL_CAPABILITIES 结构中的所有控制功能。

此图显示了一个仅包含四个控制点的线性函数。

gamma correction linear function

DXGI 按沿图面颜色轴的位置定义控制点。 在上图中,控制点的位置为 0、0.5、0.75 和 1.0。 这些控制点指示硬件可以转换范围 0 到 1.0 中的值。 DXGI 在 controlPointPositions 数组成员 中列出DXGI_GAMMA_CONTROL_CAPABILITIES 的这些控制点,并且始终按递增顺序声明这些控制点。 DXGI 仅填充 ControlPointPositions 数组的第一个元素,并指示具有 DXGI_GAMMA_CONTROL_CAPABILITIESNumGammaControlPoints 成员的元素数。 如果 NumGammaControlPoints 小于 1025,则 DXGI 将保留未定义的 ControlPointPositions 元素的其余部分。

此图表示的硬件可以将值转换为 0 到 1.25 的范围。 因此,DXGI 分别将 MinConvertedValueMaxConvertedValue 成员设置为 0.0f 和 1.25f。

DXGI 设置 DXGI_GAMMA_CONTROL_CAPABILITIESScaleAndOffsetSupported 成员,以指示硬件是否支持缩放和偏移功能。 如果硬件支持缩放和偏移,它会保留简单的一对一查找表,但随后调整表的输出,将输出拉伸到大于 [0,1] 的范围。 硬件首先缩放查找表格中出现的值,然后将其偏移。

注意

连接到同一台计算机的不同监视器可能具有不同的伽玛控制功能。 此外,伽玛控件功能实际上可能会根据输出的显示模式而变化。 因此,我们建议在应用进入全屏模式后始终调用 IDXGIOutput::GetGammaControlCapabilities 来查询 gamma 控制功能。

 

可以使用这些 gamma 控件功能值来派生控件值,然后可以使用 IDXGIOutput::SetGammaControl API 设置这些值。

使用 DXGI 设置 gamma 控件

若要设置 gamma 控件,在调用 IDXGIOutput::SetGammaControl API 时,将指针传递给DXGI_GAMMA_CONTROL结构。

设置DXGI_GAMMA_CONTROLScaleOffset 成员,以指定希望硬件应用于从查找表中获取的值的刻度和偏移值。 可以安全地将 Scale 设置为 1, 偏移量 设置为零 (即,如果不想使用缩放和偏移功能,或者硬件没有该功能,则零的偏移量没有效果) 。

DXGI_GAMMA_CONTROLGammaCurve 数组成员设置为伽马曲线上点的DXGI_RGB结构列表。 每个 DXGI_RGB 元素指定表示该点的红色、绿色和蓝色组件的浮点值。 gamma 曲线不使用 alpha 值。 使用从 DXGI_GAMMA_CONTROL_CAPABILITIESNumGammaControlPoints 获取的数字填充 GammaCurve 数组中的元素数。 放置在 GammaCurve 数组中的每个元素都是每个控制点的高度。

请注意,在上图中,你现在可以控制每个控制点的垂直放置,并且你对红色、绿色和蓝色具有单独的控件。 例如,可以将所有绿色和蓝色值设置为零,并将红色值设置为从零升到 1 的升序楼梯。 在此方案中,显示的图像仅显示其红色部分,蓝色和绿色显示为黑色。 你还可以为所有颜色设置降序楼梯,这会导致倒排显示。 放置在 GammaCurve 数组中的任何值都必须包含在从 DXGI_GAMMA_CONTROL_CAPABILITIES 的 MinConvertedValue 和 MaxConvertedValue 成员获取的值中。

伽玛控件的实用性

只要应用全屏,DXGI 的 gamma 控件才适用。 Windows在应用退出或返回到窗口模式时还原显示器的上一状态。 但是,如果应用重新进入全屏模式,Windows不会还原应用的伽马状态。 当应用重新进入全屏模式时,你的应用必须显式还原其 gamma 状态。

并非所有适配器都支持 gamma 控制。 如果适配器不支持 gamma 控制,它将忽略设置伽马渐变的调用。

在远程桌面下运行的应用根本无法控制 gamma。

如果鼠标光标在硬件 (中实现,因为大多数) ,则通常不会响应 gamma 设置。

DXGI 编程指南