【基础】伽马矫正与线性空间渲染

参考
Unity文档
知乎文章
深入理解线性空间与HDR

伽马矫正
因为人眼对暗部的感知要远敏感于亮部,所以在有限的位数限制下,用线性的方式储存颜色值有些浪费(过多的颜色值被用于储存亮部)。因此为了充分利用储存空间,我们将线性空间下的颜色做pow0.45处理(0.45幂次,按照sRGB标准),如下图左所示。这样能够使得更多的颜色值被用于储存暗部信息,这就是编码伽马(gamma encoding)。
在显示时,为了显示出正确的颜色,需要对图片进行解码,这就是显示伽马/解码伽马(gamma decoding)。sRGB标准使用pow2.2(即约1/0.45)来做解码,如下图右所示。
在视觉表现上,由于颜色值分布在[0,1],编码伽马会使图片变亮,解码伽马会使图片变暗。

sRGB颜色空间标准
由微软提出,使用pow0.45编码,使用pow2.2解码。我们平时保存的图片默认都是以sRGB标准来存储的,显示器的解码伽马系数也采用这一标准。

为什么要在线性空间下进行渲染计算
所有的光照和颜色计算都应该是在线性空间进行的。如果在伽马空间进行计算,会产生许多问题。比如在伽马空间混合两个颜色时,混合结果会倾向于更暗的颜色;在伽马空间中将颜色乘以倍数(比如*2),会得到远大于该倍数的亮度,从而产生过曝。具体的问题情景可以参考Unity文档

注意:alpha通道不参与所有的伽马矫正过程

Unity Color Space
Unity支持在伽马空间或是线性空间下进行渲染计算。在Edit -> Project Settings -> Player -> Other Settings->Color Space处设置,可以选择Linear或Gamma,分别表示在线性空间/伽马空间下进行渲染。以下介绍两种设置下的工作流。

Linear

自动GD
线性空间下运算
自动GE
显示器GD
sRGB图片
线性空间颜色
线性空间结果
缓冲区--伽马空间结果
屏幕--线性空间结果

(GD表示gamma decoding,解码伽马,pow2.2,GE表示gamma encoding,编码伽马,pow0.45)
在线性空间下进行渲染计算,能够保证结果的正确性。sRGB编码的纹理(即在Inspector中勾选了sRGB选框的纹理)在采样时会自动对图片储存的颜色值进行pow2.2的解码操作,转化为线性空间的颜色后再返回。normal map等不是表示sRGB颜色的贴图只要选择正确的type则不会被处理。如果需要使用的颜色贴图不是以sRGB编码存储的,而是以线性空间存储,在inspector面板上取消sRGB选框即可避免在采样时被自动解码(bypass sRGB)。同时,shader自定义的类型为Color的Properties也会被进行解码处理,非Color类型不会,除非加上[Gamma]关键词修饰。
虽然我们在线性空间下进行了所有的渲染运算,但最后的结果在存入缓冲区之前仍需要被编码转换为伽马空间,这是因为我们绕不开显示器的显示伽马(解码),只有在缓冲区内储存伽马空间的颜色值才能在屏幕上显示出正确的色彩。这个编码在Linear模式下也是自动进行的,在fragment shader中我们只需要返回线性空间颜色,系统会自动将改颜色编码后再写入缓冲。
既然在缓冲区中存储的都是伽马空间颜色,那么对于Blend这种需要读取缓冲区值的过程,我们读到的是什么呢?事实上,我们读到的仍然是线性空间中的颜色。这是因为在读缓冲区时,系统自动将读出的伽马空间颜色解码为线性空间后才返回。总之,在Linear模式下,对缓冲区的读写都自带编/解码,在读时自动解码,在写时自动编码,以保证读出的值在线性空间中,写入缓冲的值在伽马空间中。
不过当开启了HDR时,由于缓冲区有足够的位数来存储颜色,并不需要在缓冲区中存储伽马空间颜色,这时系统会直接将线性空间颜色存入缓冲,在读写时也不再进行编/解码;当然为了抵消显示伽马的影响,在所有计算完成后还需要对缓冲区中的颜色统一进行一次编码。

Gamma

伽马空间下运算
显示器GD
sRGB图片
伽马空间颜色
伽马空间结果
缓冲区--伽马空间结果
屏幕--线性空间结果

(GD表示gamma decoding,解码伽马,pow2.2,GE表示gamma encoding,编码伽马,pow0.45)
新建项目时的默认值。在伽马空间下进行计算。和线性空间的关键差异在于,在shader输入方面,所有的纹理在采样时都不会进行解码,而是直接将图片存储的颜色返回。如果图片是sRGB编码的,那么采样得到的就是伽马空间的颜色值。
在输出方面,fragment shader输出的颜色也不会被做任何处理即直接写入缓冲区,对缓冲区的读写
均不会有自动的编/解码。Gamma模式可以被看作“放任”模式,即没有任何自动的伽马处理,除非在shader中手动进行编解码,否则所有的运算都将在伽马空间下进行,得到并不十分正确的结果(但有时也是能接受的)。

纹理的sRGB勾选框
线性空间下,勾选sRGB选项,则代表图片是在Gamma空间存储的。在采样这些图片的时候会自动解码到线性空间再返回。如果一张图片在线性空间中储存,则不要勾选 sRGB选项。
Gamma空间下,引擎不会对图片做Gamma校正,是否勾选sRGB选项无影响。

线性空间渲染的平台支持性

这部分需要注意的是,在移动平台上,至少OpenGL ES 3.0才能够支持在线性空间下进行渲染。如果当前平台不支持线性空间渲染,当你选择Linear Color Space时,会产生上图提示。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值