Gamma校正
颜色空间
GAMES101中有详细说明:https://www.bilibili.com/video/BV1X7411F744?p=20
- 通用:sRGB
- 电影:DCI-P3
- 电视:Rec-709、PAL等
- 印刷:CMYK、Adobe RGB
- 其他
图中sRGB和Rec.709的色域是差不多的,三原色的位置是相同的,不同的部分在于:传递函数不同。
传递函数
传递函数:知道了颜色的颜色值之后,想要在电子设备上显示,就需要把它转换为视频信号,传递函数就是用来做转换的。
- OETF:光转电传递函数,负责把场景线性光转到非线性视频信号值
- EOTF:电转光传递函数,负责把非线性视频信号值转换成显示光亮度
伽马校正是什么
数学公式如下:
Gamma 是指对线性三色值和非线性视频信号之间进行编码和解码的操作
- 编码:光信号->视频信号(存储)
- 解码:视频信号->光信号(显示器显示)
示例如下:
- 图像经过gamma编码存储在硬盘中,将获取到的物理数据做一次gamma值约为0.45(1/2.2)的映射,这样的过程叫做 gamma编码(由曲线可知,此时图像的像素比实际物理像素要更亮)
- 在显示图像时,需要将每个像素做一次gamma值约为2.2的矫正,使最终的结果为正确的物理数据(经过显示的gamma校正之后,之前偏亮的图像亮度降低)
为什么要进行伽马校正
- 非线性转换的目的主要是为了优化存储空间和带宽,传递函数能够更好地帮我们利用编码空间
- 由于我们用于显示图像数据都是8bit,且人眼对暗部变化更敏感,如果要充分利用带宽,那么就需要使用更多位置去存储暗部值。也就是说暗部使用更高精度保存,而亮部使用更低精度保存
韦伯定律与CRT
韦伯定律
即感觉的差别阈限随原来刺激量的变化而变化,而且表现为一定的规律性,用公式来表示,就是△Φ/Φ=C,其中Φ为原刺激量,△Φ为此时的差别阈限,C为常数,又称为韦柏率。
简单来说就是,当所受刺激越大时,需要增加的刺激也要足够大才会让人感觉到明显变化,但是只适用于中等强度的刺激。
使用:
- 人眼对暗部变化比亮部更加敏感
- 我们目前所使用的真彩格式RGBA32,每个颜色通道只有8位用于记录信息,为了合理使用带宽和存储空间,需要进行非线性转换。
- 目前我们所普遍使用的sRGB颜色空间标准,他的传递函数gamma值为2.2(2.4)
CRT非线性响应
早期我们使用的图像显示器都是CRT(学名:阴极射线显像管),人们发现这种设备的亮度与电压并不成线性关系,而是gamma值约为2.2类似幂律的关系。
由于CRT的这个物理特性,刚好可以把亮度压暗,也就说,左图变亮的情况下,经过右图显示器的压低亮度校正,结果刚好可以显示正常。
使用的转换函数
- CRT非线性响应的历史原因
- 人眼对暗部颜色变化更加敏感
线性工作流
正常工作流
- 在生产的各个环节,正确使用gamma编码及gamma解码,使得最终得到的颜色数据与最初输入的物理数据一致。
- 如果是使用Gamma空间的贴图,在传给着色器前需要从Gamma空间转到线性空间。
如果不在线性空间下进行渲染工作,可能会产生的问题:
-
亮度叠加时
- 可以看到非线性空间下亮度叠加出现了过曝(亮度>1的)的情况
- 因为Gamma空间经过gamma编码后的亮度值相对之前会变大。
-
颜色混合时
- 如果在混合前没有非线性的颜色进行转换,就会在纯色的边界出现一些黑边。
-
光照计算时
- 在光照渲染结算时,如果我们把非线性空间下(视觉上的)的棕灰色0.5当做实际物理光强为0.5来计算时,就会出现左边这种情况
- 在显示空间下是0.5,但在渲染空间下它的实际物理光强为0.18(如右图)
补充渲染中没有正确使用线性工作流的情况
Unity中的颜色空间
选项开关(一般在player页签)
- 当选择Gamma Space时,Unity不会做任何处理(贴图处理以及颜色输出到显示器时),此时理论上可以手动处理(没有利用到硬件特性会比较慢)。
- 当选择Linear Space时,引擎的渲染流程在线性空间计算,理想情况下项目使用线性空间的贴图颜色,不需要勾选sRGB,如果勾选了sRGB的贴图,会通过硬件特性采样时进行线性转换。
硬件支持
线性空间需要图形API的硬件支持,目前支持的平台
- Windows,Mac OS x 和Linux(Standalone)
- Xbox One
- PS 4
- Android (OpenGL ES 3.0)
- iOS(Metal)
- WebGL
硬件特性支持
主要由两个硬件特性来支持:
-
sRGB Frame Buffer
- 将Shader的计算结果输出到显示器前做Gamma校正
- 作为纹理被读取时会自动把存储的颜色从sRGB空间转换到线性空间
- 调用ReadPixels()、ReadBackImage()时,会直接返回sRGB空间下的颜色
- sRGB Frame Buffer只支持每通道为8bit的格式,不支持浮点格式
- HDR开启后会先把渲染结果绘制到浮点格式的FB中,最后绘制到sRGB FB上输出。
-
sRGB Sampler
- 将sRGB的贴图进行线性采样的转换。
使用硬件特性完成sRGB贴图的线性采样和shader计算结果的gamma校正,比起在shader里对贴图采样和计算结果的校正要快
资源导出问题
Substance Painter
当Substance的贴图导出时,线性的颜色值经过伽马变换,颜色被提亮了,所以需要在Unity中勾选sRGB选项,让它在采样时能还原回线性值。
PhotoShop
正常流程
- 使用线性空间,一般来说Photoshop可以什么都不改,导出的贴图只要勾上sRGB
- 调整PhotoShop的伽玛值为1,导出的贴图在Unity中不需要勾选sRGB
使用Document Color Profile
- PhotoShop对颜色管理特别精确,Unity里看到的颜色要经过显示器的伽玛变换,而PhotoShop不会,PhotoShop会读取显示器的Color Profile,反向补偿回去
- PhotoShop有第二个Color Profile,叫做Document Color Profile。通常它的默认值就是sRGB Color Profile,和显示器的Coor Profile一致,颜色是被这个Color Profile压暗了,所以PhotoShop中看到的结果才和Unity中一样。
PhotoShop中制作的半透明UI在Unity中效果不一样
- Unity中:
- Unity进行半透明混合时,会先将它们转换到一个线性空间下然后再混合
- PS中:
- PS的图层和图层之间做混合时,每个上层的图层都会读取他们的Color Profile(gamma值),然后经过一个gamma变换再做混合,这样做得结果就会偏暗一些。
- 可以在它的工作空间 的设置中进行更改,选择用灰度系数混合RGB颜色,参数设置为一,这样图层才是一个最终直接混合的结果
Gamma校正尝试
使用一个简单的Blinn-Phong光照模型进行尝试
- 默认设置–Gamma空间下
-
在Shader中进行手动Gamma
-
albedo纹理勾选sRGB,法线纹理选Normal选项(法线纹理本身为线性),同时开启Linear颜色空间(局部部分比默认Gamma下亮一丢丢,但与手动Gamma不一致)
-
albedo纹理不勾选sRGB(使用gimp确认原图使用了sRGB),法线纹理选Normal选项(法线纹理本身为线性),同时开启Linear颜色空间,明显过曝了
实验说明
- Unity_ColorSpaceDouble是一个Unity提供的与色彩空间相关的值,这个值在Gamma颜色空间时为2,在Linear Color Space时为4.594(2的2.2次方)。
- 对于这个值可以这样来理解。一般在Gamma颜色空间中将两个Color值相乘后,为了避免颜色变得很暗,会在后面乘以2。
- 也就是说,为了避免颜色变暗,应该扩大两倍,但是这个值在不同空间下不一样,所以要使用Unity_ColorSpaceDouble。
1 | //======================fs着色器部分代码======================== |
UnityCG.cginc
1 | inline float GammaToLinearSpaceExact (float value) |
补充
- 金属度官方PBR实现中,加了[Gamma]标记,会进行Gamma Correction Removed。这和底层的光照计算中考虑能量守恒的部分有关,Metallic代表了物体的“金属度”,如果值越大则反射(高光)越强,漫反射会越弱。在实际的计算中,这个强弱的计算和Color Space有关,所以需要加上[Gamma]项。
- 在计算纹理的Mipmap时也需要注意。如果纹理存储在非线性空间中,那么在计算mipmap时就会在非线性空间里计算。由于mipmap的计算是种线性计算——即降采样的过程,需要对某个方形区域内的像素去平均值,这样就会得到错误的结果。正确的做法是,把非线性的纹理转换到线性空间后再计算Mipmap
- sRGB是Gamma0.45,显示器是2.2(可能更高,需要补偿亮度)
参考资料
- https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
- https://www.bilibili.com/video/BV15t411Y7cf
- https://edu.uwa4d.com/lesson-detail/116/365/0?isPreview=0
- https://blog.csdn.net/candycat1992/article/details/46228771
- https://www.gameres.com/811214.html
- 大佬笔记:
- https://zhuanlan.zhihu.com/p/66558476