简述Unity线性空间和伽马空间

为什么我会想起来写这篇博客呢?缘起于项目中做PBR时,美术来问出贴图是要出线性空间贴图还是伽马空间贴图,经过一番纠结与查证后,项目终于切到了线性空间,而贴图则是能出线性空间优先出线性空间,出不了的出伽马空间也行。至于为什么也行,就是本篇博客所要讲述的内容。

首先要来解决第一个问题,什么是伽马空间,什么是线性空间?线性空间好理解,颜色按照线性渐变的空间即是线性空间,我在网上看到一个举例很有趣,想象一个纯黑墨水的池子,往里面滴一滴白色颜料,随着白色颜料不断的滴入,墨池会越来越白直至变成白色,而记录每次滴入颜料后墨池的颜色变化,即是一个从黑到白的颜色线性渐变过程。既然有线性渐变,那么肯定就有非线性渐变,而伽马空间正是这样一个颜色非线性渐变的空间。为什么会发生这样的事呢?

一个流传甚广的版本表示,这是由CRT显示器引起的。由于CRT显示器对于输入的电压和显示的亮度并不呈线性关系,而是一个类似幂律曲线的关系,一般来说,这个曲线的指数部分称作伽马值,为2.5。显示器有这样的特性后,一个正常颜色输入进去显示出来会变暗,我自己拉了个图来说明下

这是个y=x^{2.5}的幂律曲线,如果颜色输入值为0.5,那么输出值大概为0.176左右,更接近黑色。所以输入的颜色在输出时会变暗。为了解决这个问题,图片在被采集时会做一个逆向操作,如果颜色为0.5的话先逆向0.5^{1/2.5} \approx 0.757然后0.757^{2.5} 就会回到0.5了。这里我们用到了两个伽马值,1/2.52.5,他们分别称为encoding gamma和display gamma,通过下图展示他们的用处。

encoding gamma通常在图片生成时(比如说拍照拍出来的照片,PS新建的图片等)就已经存在,而display gamma又是显示器自带的特性(当然现在的显示器不再是CRT,所以display gamma可能不是2.5,不过为了兼容性厂商还是会把以前的2.5伽马值加入),他俩相乘称作end-to-end gamma,如果是1的话那么真实场景被捕捉的亮度和显示的亮度是成比例的。然而,Real Time Rendering一书指出了乘积为1的问题。一是我们人眼看到的真实场景的亮度与显示器所能显示的亮度差了好几个数量级,说白了显示器所能显示的颜色精度根本达不到真实场景的精度;二是周围环境影响,我们的视野在看真实场景时是由真实场景所填充的,而在看显示器时视野除了被虚拟场景包围,还会被真实场景包围。这样两个差别导致了end-to-end gamma是1的话并不能保证显示的亮度和原始场景的亮度是一致的。书中推荐,电影院那种漆黑的环境为1.5,在明亮的室内为1.125。

我们通常用的sRGB标准的encoding gamma大概为0.45(1/2.2),这是为了配合2.5的display gamma,因为0.45 * 2.5 = 1.125。当然,显示器的display gamma大部分值还是设为2.2(这里有个网站,可以看在不同的伽马值下图片所表现的不同准确的伽玛 2.2 及预设 5 种伽玛值设定),这样1/2.2*2.2 = 1。

当然冯乐乐前辈还提出了来自其他领域对于伽马的解释,以此来论证伽马值存在的必然,不管如何,伽马空间中的颜色并非线性渐变,而是呈一条曲线变化。

那么我们在做PBR时,为什么要纠结到底用伽马空间还是线性空间呢?PBR全称为Physically Based Rendering,既然是基于物理的渲染,那么我们做渲染时对于贴图采样出来的值必定要是和真实环境下相同的值才行,而采用了伽马空间的话贴图中颜色会被encoding gamma所改变,shader中采样出来的颜色值和真实环境下的值是不一样的,这样怎么能称为基于物理的渲染呢?

我们以人的皮肤渲染来举例子,皮肤贴图的r通道的值通常会高于其余两个通道的值,那么在伽马校正后(即对原始值做一个伽马次方的操作),这种差异会被进一步的放大,再做光照计算,你会发现r通道的值提升的异常的高。

上图左边是线性正确值,右边是渲染时带着伽马值,那么提升光的亮度会迅速的曝光。

而当这种差异被拉大后,你会发现在眼皮轮廓的地方会出现蓝黑色的痕迹,如下图

所以在做PBR渲染时,使用线性空间是非常有必要的。

而我们纠结的点在于,把Unity引擎切到线性空间的话,之前所有美术的资源都是在伽马空间下制作的,会不会有问题?实际上是有问题的。

当我们把Unity从伽马空间切换到线性空间时,引擎里面我们需要勾选一个东西,这样伽马空间的资源也能使用了。

勾选了图中的sRGB后,其实引擎为我们做了一个工作,在采样这张图片的时候会调用OpenGL ES3.0里的sRGB Sampler接口,将贴图中被encoding gamma所改变的值还原,这样我们在shader中做的任何计算就是基于物体在真实场景中的颜色了。算完以后当我们要把颜色输出到显示器时,显示器因为自带display gamma,我们无法抹去这个东西,所以引擎又为我们做了一件事,调用OpenGL ES3.0里的sRGB Frame Buffer接口,将计算得出的最终结果用encoding gamma算好,用以抵消display gamma的影响。

那么在线性空间底下使用伽马空间资源会有什么问题呢?透明混合会出问题。我们知道透明混合的时候dst color在frame buffer中,而颜色在线性空间下进入了frame buffer引擎会调用sRGB Frame Buffer接口做一个pow0.45的操作,而透明混合时明显需要线性空间的颜色,因为src color还没进frame buffer,没做过pow4.5的操作。所以这里在把dst color从frame buffer拿出来时,会做一个pow2.2的操作回到线性空间,然后做透明混合,得出结果后再做一遍pow0.45。

假设src color的某个分量为1,alpha为0.5;dst color某个分量为0,那么根据正常的计算为:

res = src * alpha + dst * (1-alpha) = 0.5

而有了sRGB Sampler和sRGB Frame Buffer后:

res = (src ^{2.2} * alpha + dst ^ {2.2} * (1-alpha)) ^ {0.45} = 0.5 ^ {0.45} \approx 0.732

差异在此产生,并且随着混合次数的增多,差异会越来越大。

理论上最好的解决方案是美术直接在线性空间下制作资源,如官方说的在PhotoShop设置中选择“用灰度系数混合RGB颜色”,参数设置为1。

或者参考网上的解决方案【Unity补完计划】Unity线性空间(Linear)下Alpha的混合问题Unity手机线性空间下的透明混合(上),但他们都有额外的消耗,对于性能不是那么富裕的项目就显得无能为力了。

参考
Unite 2018 | 浅谈伽玛和线性颜色空间
聊聊Unity的Gamma校正以及线性工作流
【图形学】我理解的伽马校正(Gamma Correction)
Chapter 24. The Importance of Being Linear

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342