Unity - 伽马空间和线性空间是什么与他们之间的不同?

译自:http://www.kinematicsoup.com/news/2016/6/15/gamma-and-linear-space-what-they-are-how-they-differ

线性空间照明的概念越来越多的被开发人员使用,为了达到下一代真实感使用基于物理的渲染。虽然线性空间和其对应的伽马空间是很简单和重要的概念,下文说明了两种空间是什么,它们的不同,和它们是如何使用的。

线性空间

首先我们需要了解线性颜色空间的概念。简单的说,它意味数值强度与它的感知强度成正比。这意味着可以正确的添加和相乘颜色。一个颜色空间没有属性叫"non-linear"。下面是一个双倍强度值在线性空间和非线性空间的例子。虽然在线性空间中相应数值是正确的,但是在非线性空间中,我们不能简单的通过加法得到结果,相机对于光强的感知是基于线性的,业界的图片都是存储在Gamma空间中,那么相机的到最终的图片就会经历一个编码过程,也就是Gamma编码, Vout = Vin(1/2.2) ;
Unity - 伽马空间和线性空间是什么与他们之间的不同?

伽马空间

需要使用伽马的两种主要情况:首先屏幕对强度是非线性的相应。另一点人眼在暗色的识别比在亮色的识别更好,这意味着图片压缩到存储空间,我们想得到更好的精度对于暗强度,且牺牲了较亮强度。这两个问题都是通过伽马矫正来解决的问题,伽马校正是指将图片中的每个像素强度他通过幂函数进行处理。具体来说,gamma是应用于图像的幂的名称。

Unity - 伽马空间和线性空间是什么与他们之间的不同?

下图显示了gamma值的不同

Unity - 伽马空间和线性空间是什么与他们之间的不同?

颜色空间和渲染管线

当时使用伽马管线渲染,纹理将传给shader,进行gamma修正,下一步进行光照计算。之后图片将输出到屏幕上进行显示并调整显示的伽马值。这种操作是很简单的,没有物理修正。在真正的生活中,光照现象是线性的,这意味着复杂光源对光照表现的贡献是同时添加到正确的强度。这样着色的过程是线性的,这意味着着色的结果不是真正的准确,但是在显示修正后表现的很好,然而随着对真实沉浸感渲染的需求不断增加,这种方法已经不再适用。
PBR的典型实践是使用线性管道。在将输入颜色、纹理传给线性空间之前将伽马修正移除。当着色完成,结果在物理上是正确的因为着色和输入都在同样的空间。之后,后处理也在线性空间中,后处理通常是线性的。最后对图像进行伽马修正以将正确的结果显示出来。

Unity中的颜色空间

Unity可以很方便的切换颜色空间,对于许多项目渲染管线可以无缝工作。通常Unity只在PC、Xbox、PS平台支持线性渲染。对于这些平台:Edit -> Project Settings -> Player -> Other Settings中来切换空间。
这样Shaders将接受无伽马修正的纹理。
当渲染适用HDR的线性颜色空间,Unity全部的后处理将在线性空间中。当只启用线性色彩空间的时候,Unity将是哟个gamma帧缓存,但是当都写得时候,Unity将自动将颜色空间进行转换,这样图片效果还在线性空间中被处理。
虽然Unity在一些平台上不支持线性空间,但是可以通过在shader中实现pow()方法来实现伽马修正,这个方法将有较大的性能消耗。