Gamma校正
颜色空间
颜色空间也称彩色模型和彩色空间,它的用途是在某些标准下用通常可接受的方式对颜色加以说明,本质上,颜色空间是坐标系统和子空间的阐述,其中每种颜色都由单个点表示。
不同标准下所采用的颜色空间
通用:sRGB
电影:DCI-P3
电视:Rec-709、PAL
印刷:CMYK、Adobe RGB
上图中sRGB和Rec.709表达的色域范围是差不多的,区别在于传递函数的不同。
传递函数是什么?
我们已知一个颜色在颜色空间下三原色的值,但是要把它显示在电子设备上,就需要把它转换成视频信号,这就需要用到一个转换函数,也就是传递函数。一个传递函数包含两个部分,一个是把光信号转换为电信号,比如在拍视频的时候;另一个是把电信号转换为光信号,比如在播放视频的时候。传递函数实际上就是我们所说的Gamma校正函数。
Gamma校正,简单来说就是对线性的三色值和非线性的视频信号之间进行编码和解码的操作。
-
图像经过gamma编码存储在硬盘中,将获取到的物理数据做一个gamma值为0.45的映射,这样的过程叫做gamma编码。由曲线可知,此时图像的像素比实际物理像素要更亮。
-
在显示图像时,需要将每个像素做一个gamma值约为2.2的校正,使最终的结果为正确的物理数据。经过gamma校正之后,图像亮度降低。
为什么要进行Gamma校正?
非线性转换的目的主要是为了优化存储空间和带宽,传递函数能够更好的利用编码空间。
一般用于显示图像的数据都是8bit,基于人眼对暗部变化更敏感,如果要充分利用带宽,那么就需要用更高精度去存储暗部值;而亮部相对来说没有那么敏感,就使用低精度值去存储。
韦伯定律
人眼在应对外界的亮度刺激均匀增长的过程中,会从刚开始的比较敏感,变得越来越不敏感,符合生理学上的韦伯定律。
韦伯定律,即感觉的差别阈限随原来刺激量的变化而变化,而且表现为一定的规律性,用公式来表示,就是△I/I=K(其中,I为原刺激量,△I为此时的差别阈限,K为常数,又称为韦伯率)。
Gamma校正的另一个由来
早期我们使用的图像显示器都是CRT(学名:阴极射线显像管),人们发现这种设备的亮度与电压并不成线性关系,而是gamma值约为2.2类似幂律的关系。刚好会把我们存储的图像文件进行压暗的处理,符合人眼舒适的亮度。
线性工作流
-
在生产的各个环节,正确使用gamma编码以及gamma解码,使得最终得到的颜色数据与最初输入的物理数据一致。
-
如果是使用Gamma空间的贴图,在传给着色器前需要从Gamma空间转到线性空间,以保证渲染计算的正确结果。
如果不在线性空间下进行渲染工作,会产生什么问题?
亮度叠加时:过曝
颜色混合时:边缘显示出黑边
Unity中的颜色空间
通过点击菜单Edit->Project Settings->Player页签->Other Settings下的Rendering部分进行修改,参数Color Space可以选择Gamma或Linear。
-
当选择Gamma时,Unity不会做任何处理。
-
当选择Linear时,引擎的渲染流程在线性空间计算,理想情况下项目使用线性空间的贴图颜色,不需要勾选sRGB;如果勾选了sRGB的贴图,会通过硬件特性在采样时进行线性转换。
硬件支持
线性空间需要图形API的硬件支持,目前支持的平台:
(1)Windows,Mac OS x 和Linux(Standalone)
(2)Xbox One、PS 4
(3)Android (OpenGL ES 3.0)、iOS(Metal)
(4)WebGL
硬件特性支持
主要由两个硬件特性来支持:
(1)sRGB Frame Buffer
-
将Shader的计算结果输出到显示器前做Gamma校正
-
作为纹理读取时会自动把存储的颜色从sRGB空间转换到线性空间
-
调用ReadPixel()、ReadBackImage()时,会直接返回sRGB空间下的颜色
-
sRGB Frame Buffer只支持每通道为8bit的格式,不支持浮点格式
-
HDR开启后会先把渲染结果绘制到浮点格式的FB中,最后绘制到sRGB FB上输出
(2)sRGB Sampler
-
将sRGB的贴图进行线性采样的转换
使用硬件特性完成sRGB贴图的线性采样和对shader计算结果的gamma校正,比起在shader里贴图采样和对计算结果的gamma校正要更快。
资源导出问题
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中一样
Unity中的混合是线性混合,Photoshop的图层和图层之间做混合的时候,每个上层图层都经过了伽马变换,然后才做了混合。在设置中更改,选择“用灰度系数混合RGB颜色”,参数设置为1,这样图层才是直接混合的结果。