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 了
- 如果屏幕硬件没有 gamma correct,那么我们给这种设备输出数据前,收到给 FB(FrameBuffer),后处理一遍对每个像素 gamme correct 一下
- 如果我们的屏幕设备(如:CRT)对输入数据不可以线性的控制灰度输出,那么我们确保设备是否处理了 gamma,没有的话,同上处理
- 我们屏幕设备(如:LED)对输入数据可以线性的控制灰度输出,那么我们只要确保设备是否会硬件层处理了 gamma correct:
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
- Color space - unity 官方的文档 - 建议先看这个 大智的讲解(相信里面的部分理解也是看过 韩世鳞 老师的视频)
- Gamma校正与线性工作流入门讲解 - 韩世鳞 老师的讲解,太牛逼了
- Gamma校正 - 结合大部分 DCC 的涉及 gamma 校正的处理,很不错
以上是关于Gamma Correction/Gamma校正/灰度校正/亮度校正的主要内容,如果未能解决你的问题,请参考以下文章