Gamma Correction/Gamma校正/灰度校正/亮度校正

Posted Jave.Lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gamma Correction/Gamma校正/灰度校正/亮度校正相关的知识,希望对你有一定的参考价值。


我们一般说的 gamma correction 简称 gamma,而 gamme correction 就是对 pow(inputVal, 1.0 / 2.2) 也就是提亮颜色的处理,而 gamme correction 的逆运算可以简称:de-gamma,就是 pow(inputVal, 2.2) 也就是压低亮度的处理

因为我们人眼在看到真实世界中的亮度值时,在眼球编码生物神经电信号给大脑中的灰度感知并非线性的(人眼会将 pow(inputVal, 2.2) 处理,会将原来的线性颜色表现出来的亮度整体偏暗,这种视觉效果感觉很差

所以我们为了提高视觉效果更好,才会在颜色输出给人眼看到之前,先将其提亮颜色,也就是A=pow(inputVal, 1.0/2.2),这样将提亮过的结果,给到人眼时呈现的是 pow(A, 2.2) 颜色亮度,但是刚刚说过,给人眼看前提亮,人眼编码在大脑压低亮度,这一升一降,刚刚好变成线性的,所以这是在人脑中的灰度信号是线性的,那么视觉上自然就会舒服很多,但是实际上真正的物理亮度是被提亮过的

如果有些设备,如:CRT,也是会降低亮度的输出,那么就在 CRT 输出前 2 次 gamme 校正,这样,CRT 降低1次,人眼再降低1次,刚刚好看起来就像是在 线性变化的感觉(注意这时人眼看到的输出结果都是被提亮过的,不提亮就会偏暗,人眼对灰度的感知编码不是线性的)

下面用 GGB 来显示对应的操作:

  • GC⇒ Gamma Correct(因为 CRT、人眼 设备等,会降低亮度的编码方式,所以需要 gamma 校正)
  • L⇒ Linear(如果我们传入人眼的是 GC 过得,脑子呈现的灰度将会是 Linear 的变化)
  • DGC⇒ De-Gamma Correct (人眼将数据 Linear 后的数据压低亮度就变成这条曲线的亮度)

所以如果你在 shader,或是其他一些代码中可能会看到 pow(val, 0.4545) 的其实就是 pow(val, 1.0 / 2.2) 的一个 gamma correct 操作

因为 1.1/2.2 == 0.4545454545 无尽小数部分


Unity 中的 gamma、linear 工作流

在 Unity 中,涉及到 gamma correct 等颜色空间的有:

  • Edit/Project Settings…/Player/Other Settings/Color Space: Gamma 或是 Linear
  • 每个纹理资源只要是颜色类型的纹理(不是 AO, Normal, Height 贴图),那么 sRGB 的勾选需要在对应的 Color Space 下选择是否勾选:
    • 在 Color Space 为 Gamma 时,勾上(Unity 默认情况下时会勾上的)
    • 在 Color Space 为 Linear 时,不要勾上
    • 因为 Unity 的纹理的 sRGB 属性意思是:是否对已有颜色数据进行 Gamma Correct 处理,也就是上面 GGB 函数中对应的 GC 函数处理,GC(x) = pow(x, 1.0 / 2.2),这个纹理里面的数据,给到外部访问、使用时,是否需要先提亮一下的 gamma correct 处理
    • 那么线性空间中,我们需要确保我们输入给 shader 计算的都是 linear 值才行,这样运算结果才能正确,最终输出给屏幕,而输出给屏幕设备有分情况:
      • 我们屏幕设备(如:LED)对输入数据可以线性的控制灰度输出,那么我们只要确保设备是否会硬件层处理了 gamma correct:
        • 如果屏幕硬件没有 gamma correct,那么我们给这种设备输出数据前,收到给 FB(FrameBuffer),后处理一遍对每个像素 gamme correct 一下 return half4(pow(tex2D(_MainTex, uv).rgb, 1.0/2.2), alpha);
        • 如果有屏幕硬件有集成处理 gamma correct,那么我们就不要再处理任何的 gamma correct 了
      • 如果我们的屏幕设备(如:CRT)对输入数据不可以线性的控制灰度输出,那么我们确保设备是否处理了 gamma,没有的话,同上处理

Unity 中的 Linear 工作流简单的总结:

  • Color Space : Linear
  • 只要和直接表述灰度值有关的纹理信息,如:albedo,那么都要确保 sRGB 不要勾上
  • 其他数据纹理(AO, NORMAL, HEIGHT )贴图,也不需要 sRGB,一般你选择了类似类型后,也不会有 sRGB 勾选项的显示,即:不需要的意思
  • 然后我们在 shader 中确保有在 last frame buffer 的写入后,给设备数据前,要 gamma 一次就可以了(目前发现,如果在 Color Space : Linear 下,UNITY 会在最后一个 dc 的后处理 gamma 提亮处理)

Linear 工作流

下面流程图是暂时的编辑结果,还有 gamma 工作流的,后续再增加处理吧


References

以上是关于Gamma Correction/Gamma校正/灰度校正/亮度校正的主要内容,如果未能解决你的问题,请参考以下文章

ISP基础(10)-Gamma校正及其实现

色彩校正中的 gamma 值是什么

gamma校正

将枕头图像转换为灰度的 Gamma 校正

MATLAB 中的 Gamma 校正实现

OpenGL学习脚印:伽马校正(Gamma Correction)