gamma和LWF的分享
前言:最近有时间看了很多各大神的文章@阿拉平平的小屋@[email protected]@ Super的博客@TraceYang的****空间等等还有没来得及留笔的各大神关于gamma与LWF(线性流)之类的文章之后,也一直想弄清这方面的知识点,所以收集整理组合各类知识点,在这里与感兴趣的人做下分享…
gamma问题和线性工作流程问题一直以来都是讨论的热点问题,也是大都数人糊里糊涂的一个地方,其实我接触到的大都数重业者对这些概念都比较混淆,或者是有自己的一个不那么合适的认知。原理性的东西说重要也很重要,说不重要只要大家在公司按项目安排的流程走也不会对自己工作有什么影响,就像骑摩托车,就算不懂发动机工作原理,或各配件是什么以及其作用等等,也一样能骑的飞起来,不影响驾驶,只是车子出问题的时候,自己会一脸萌逼的去修理店。这里对之前阶段的研究作了总结,希望对有兴趣的朋友有点用
Gamma
误区(大都数人一直以为显示器问题是gamma产生的原因。这个观点不太合适,因为显示器不是gamma产生的关键原因)
从头开始撸:显示器的以前的CRT显示器是使用电子显像管,通过控制电流大小来控制显示屏幕上的亮度。然而亮度和电流之间的关系并非是线性的,也就是说电流强度变为原来的一倍时,显示的亮度并非是1倍,而是接近2倍,由公式1决定:
(out=输出 in=输入)
经过测试发现VIN(输入) 和 Vout(输出) 成幂指数关系,这个关系是非线性的
2.2
如:y=0.2 =约0.04…;
2.2
如:y=0.4 =约0.16…;
(2.2是根据当年研究者经过一系列计算反求的一个数值,我们这里只是验证输入与输出的关系,所以直接套用这个值 )
这是大多数人理解的gamma产生的原因,但这是真正的原因吗? …也许不是,其实还有一个真正主要的原因,就是人类眼睛感知亮度和自然物理亮度之间的关系。
01 人眼对自然亮度感知是非线性的(人眼对暗部的细节会更敏感,比如室内开灯例子)。
02 我们用来展示画面的媒介上,动态范围和灰阶预算是有限的。(现在主流色彩空间是8bit的SRGB,有256种颜色呈现)
为了在灰阶预算有限的前提下,协调自然物理亮度和主观感知亮度这二者的映射关系,Gamma的曲线就产生了。
这是Gamma的产生乃至延续至今的主要原因。巧合的是:符合人眼感知的gamma曲线 与 矫正显示器反gamma曲线 相同.
人眼感知的非线性特点:即物理0.2亮度会被人眼感知为0.5左右,所以在SRGB空间有限的8bit条件下 我们只能通过gamma矫正 把亮度更多的bit用来编码更重要的暗部信息
上图为: 人眼感知亮度的曲线
产生原因:人眼感知的非线性
上图为: 实线:显示器gamma曲线 虚线:显示器 gamma矫正曲线(它和人眼感知曲线函数相同)
产生原因:硬件问题造成 输入不等于输出
显示器的反gamma曲线 和 人眼感知亮度的曲线二者相同,所以我们输
入的数据图像或视频,用这样的曲线来预先处理进行Gamma校正一次(函数:y=x1/gamma),这样处理过之后,再经过显示器的(函数:y=xgamma),刚好就是线性的曲线(函数:y=x)了。
人眼感知的非线性特点 会导致gamma矫正会一直存在,这也就是现在的非CRT的显示设备还要特意保留在gamma 2.2左右的原因.
以下摘自一前辈的论述:
凡是说Gamma 来自于老式CRT显示器物理特性的解释,大都是有点误解。这个误解一般会这么讲解Gamma的来龙去脉:当年老式的CRT显示器内置Gamma 2.5左右,解码的时候会把输入信号压暗,所以我们呢,为了保证总Gamma接近1,就要预先在编码的时候把输入文件的信号提亮,而且这样一来呢,刚好顺应了人眼对暗部感兴趣的特点,把暗部的信息多多记录了下来,充分利用了文件的空间,真是美妙的巧合啊。讲起来顺畅,听起来也很美妙,我也曾经这么给别人讲,但是我发现我没法说服我自己,人类就被一个老式硬件的物理特性决定了后世的工业标准?这逻辑不对。
为啥错,比如当年要是没有先发明CRT显示器呢?假设我们先发明了一个物理Gamma为1的显示器。当输入8位图像0.5的数值的时候,它还是要乖乖的把这个0.5映射成白像素的20%输出出来。否则看起来就不是中灰,8位每通道的显示器Gamma必须在2.2左右,跟显示器发展史没关系,完全是视觉效果决定的。一切都因为韦伯定律。
一切的前提必须是:灰阶预算很紧张,只有灰阶有限,我们才需要考虑中灰映射给谁的问题,如果灰阶足足的够用,硬盘不要钱了,网线足够粗,我们主流不再使用8位每通道图片记录亮度信息的话,Gamma是没必要的,我们直接把自然界的0.2记录在文件上,显示器读取到0.2,也直接显示就好了——32位每通道的hdr格式就是这样的。
总之一句话:灰阶有限的前提下,因为人眼对自然的非线性感知特性,我们才需要Gamma校正。
Gamma=2.2怎么来的?是实践中目测调整出来并最终确定的,其实说良心话,只要是0.5中灰对应白色的20%左右,画面看起来都是靠谱的,所以当年的Gamma特别多种多样,在2.2上下浮动(1.8-2.5),1996年微软和惠普在特定的光照条件下测试人观看显示器的感受,他们认为,把8位图像中128号灰(0.5灰)这个抽象的、代表心目中中灰色的数值,对应以白像素21.8%的亮度显示出来,由黑到白的渐变过渡看起来会比较均匀。最终对应的Gamma就是2.2。那么他们定了这个标准,后世的硬件也就都往上面靠了,包括拍照的时候,编码Gamma也就取了1/2.2=0.454。这样能保证整个编码解码系统总Gamma是1,高保真,自然界中的色值能在屏幕上相对完好的再现。
总结:因为我们硬盘太贵,网线太细,所以地球人目前主流使用8位每通道的sRGB色彩描述体系,它灰阶有限,中灰的地位必须在所有灰阶的中间,记录值为128,而不能是其物理值0.218,把物理量0.218换算成0.5灰阶编号的过程,就是编码端的Gamma校正,Gamma值为1/2.2=0.454。屏幕读取到128显示成21.8%的亮度的过程,就是解码端的Gamma校正,Gamma值为2.2。整个系统Gamma为1。若是有朝一日,32位每通道文件成为主流格式,Gamma校正就会消失。自然数据不经校正直接记录为文件数据,再不经校正直接显示。
其实我们常言的gamma矫正就是说的gamma的编码, 如图
Gamma和sRGB gamma
前面俺们聊过,显示器由于硬件制造的输入不等于输出的问题,大部分显示器可以通过Gamma校正获取最好的效果。现在世界上大都显示器用微软和惠普的sRGB色彩空间,sRGB 颜色空间是一个可以直接用来在显示器上显示的非线性颜色空间,其曲线和gamma2.2接近
如上图:线性空间和sRGB的对比产生的曲线 ,和gamma2.2的曲线几乎重合,这样的好处是sRGB可以储存更多低luminance RGB值,更适合人类的视觉(但要注意的是SRGB曲线是分段函数,而gamma2.2曲线则重头到尾都是幂函数曲线,两者接近而并非重合)。综上,对于图片来讲,如果他是sRGB空间的话,那么也就可以说它是gamma校正过的了。
Gamma的种类
图像的Gamma
通常所说的sRGB空间 = gamma 0.45,照相机或其他Raw软件捕捉的图像,通常会转为标准的JPEG或TIFF文件,也就是编码为gamma 1/2.2的图像文件。但Raw是保存在线性空间的
显示的Gamma****
通常的gamma2.2,现在的显示器通常已经把gamma2.2作为标准,所以不用太担心不同gamma值所带来的优缺点,老的苹果显示器可能用的是gamma1.8。
不同显示gamma值和对应曲线的对比,其中,蓝线为图片的gamma校正值(gamma 1/2.22),红线为设置的显示gamma值,紫色则为最终的系统gamma值。
最终系统呈现的 Gamma(gamma=1)
表现的是gamma校正和 显示gamma同时作用在图片上的效果,当系统gamma是线性时,可以保证你的光照计算正确的显示。
**
Lwf(线性工作流)
首先了解下并不是所有的贴图都需要进行gamma矫正。
哪些贴图进入渲染器前的Gamma矫正呢
大家记住一点:能影响到最终效果颜色呈现的颜色贴图都需要矫正,如diffuse_map,color_speaular/refr/refl彩色镜明高光贴图等等
如bump,dis,normal,tansparency,黑白speaualr等贴图无需矫
然后我们聊聊色彩空间,如下图 左侧为三维渲染空间(liners) 右侧为显示器的显示空间(SRGB),大家可以先了解一下
如下图2是我粗燥的手工绘制图 LWF从开始到结束的工作方式,各曲线分别代表:
以上为三维里的工作流程。
如果你问:非线性的图片,如JPG在经过系统SRGB矫正为线性的颜色空间的同时 后台发生了什么?
那一定有人疑惑,为什么我们看到的类似jpg的图不是白灰的呢?原因就是显示器。如下截图
所以,对于图片来讲如果是sRGB空间的话,那它就应该是经过gamma校正过的了
三维渲染时,程序内部使用的是线性的颜色,直到最后渲染结果要输出到显示器上前,我们的srgb色彩空间会自动对渲染结果进行的校正。如照相机等摄像设备所做的那样,这样保证我们渲染的结果能够正确的在显示器上显示。但是,前提是我们加载的纹理中颜色数据是线性空间中的。所以最终
正如前面所说,大部分图像捕捉设备在保存图片时会自动加上伽马校正,也就是说图片中存储的是非线性空间中的颜色,如果我们在渲染时直接使用图片存储的颜色数据,然后最终输出到屏幕时则会导致图像偏灰。 所以读取纹理数据时,若纹理颜色空间是sRGB空间中的,我们需要对其“反伽马”校正,转化到线性空间中来,以保证光照计算的正确。
需要注意的是:一是现代8位的图片格式如jpg,png等保存下来都是已经经过Gamma校正的。二是32位图片能保存非常多的信息,故不需要经过Gamma校正。
下面我们来讨论下
为什么要使用线性流 若不矫正贴图为线性颜色空间,会是什么结果?
在游戏引擎或是3D渲染软件中,灯光都是一个线性量,当灯光与没经过反Gamma校正的非线性纹理数据混合就有二种情况,一是纹理亮度是对的,但是灯光会感觉局部暴光太高,而远处太暗;二是灯光显示正确,但是纹理亮度更亮,亮度细节丢失。为什么这样了,第一种情况,灯光也加入了反Gamma,这样暗的位置更暗,对比之下灯光位置太亮,第二种情况,纹理又进行了一次Gamma,这样更亮,而人眼对0-0.2与0.2-1感觉是一样的颜色差,亮度差更高,但是人看不出来,而暗差变小,会感觉亮度细节丢失明显。
那么只有在与灯光混合计算前,进行一个反Gamma的过程,这样灯光与纹理数据都是线性数据,显示正确。
总结为两点的话,如下
01当在非线性空间下计算渲染的时候会发生的是,在亮度上,他们在各个位置的比率是不一样的,于是实际输出亮度也就不匹配了
02在线性空间下计算,输入端也是线性,那么他们的比率就匹配了,如图所示:
LWF的宗旨:为了确保在渲染所有的灯光,材质,贴图都保持在相同的颜色空间里去进行,使整个流程达到一个统一性,物理性,完整性。
拿渲染器arnold来说,maya2017开始就弃用了使用arnold的gamma correct,官方推荐使用maya的本机color management进行色彩管理,而且现在maya2018是默认开始色彩管理属性的。现在arnold默认的所有控件Gamma设置为1.0,这意味着arnold期望所有的需要进行渲染处理的颜色和图像都是线性的;如果使用贴图纹理,需要将文件加载到maya中之前先对其进行线性化,可以在转换为.tx的过程中手动设置colorconver对其进行线性化,也可以Hyshader手动连接gamma correct材质节点进行校正,但有一点需要注意,不是所有贴图需要去校正,如置换,normal等不涉及影响最终颜色信息的贴图。
如果觉得前期矫正麻烦,可以在做贴图的时候就直接出16bit及以上的贴图,这样贴图信息包含的已经线性的颜色空间了。
测试发现,houdini里通过修改Source color space能达到把8bit的贴图强行线性化的效果,这一点也是刚测试,后面会继续追一下这个结论的肯定性。具体测试结果如下
延伸:
觉得关于色彩空间这方面 一些学者应该了解一下 便于后期的知识延伸,所以额外扩展一下:
SRGB和Adobe RGB
sRGB色域是一个通用的标准色域,是由微软、惠普联合于1997年共同开发的标准色彩空间,也是现在的主流电脑上的色彩体系。
Adobe RGB是Adobe公司(PS的母亲)于1998年提出的实用性色彩空间,它拥有比sRGB宽广的色彩空间和良好的色彩层次表现.它还有一个优点:就是Adobe RGB还包含了sRGB所没有完全覆盖的CMYK色彩空间。这使得Adobe RG8色彩空间在印刷等领域具有更明显的优势。
同上图所示,两张相同的图像与颜色,不同色彩空间,你可以发现其中的差异。以直接的感官感受来看,AdobeRGB相较于sRGB在色彩上看起来似乎比较有活力,而sRGB的色彩表现看起来稍微平淡。
可以看出,100%AdobeRGB相比100%sRGB拥有更广的范围,包含了sRGB所没有完全覆盖的CMYK色彩空间,覆盖了较大的绿色以及青色的区域,能更加真实地还原拍摄对象(如天空草地等),记录更多的颜色细节。AdobeRGB色域在图像处理和编辑方面可以拥有更大的自由度。
虽然AdobeRGB色域覆盖范围更广,但是相比之下,sRGB应用范围更广泛。sRGB(standard Red Green Blue)标准 RGB 色彩空间,平时拍摄照片仅仅网络平台浏览、使用,且很少做色彩管理工作的情况下,就可以直接选择sRGB模式。
我们有时会遇到,将Adobe RGB色域的图片上传到不支持色彩管理的网站后,画面色彩反而变得平淡,这是因为图片上超过浏览器显色范围极限的那部分色彩信息丢失了。
备注:使用的截图来源于网络
后续有时间会继续分享houdini相关的知识小点