Unity颜色空间初探

367 阅读2分钟

最近复习了一下颜色空间的定义,记录一下。

Gamma空间

使用数学模型描述光照强度变化是线性的,但是我们人眼的感知却不是线性的。

gamma.png

通过科学研究分析,人眼对光亮度的变化感知能力接近于n = 1/ 2.2的幂函数,即对于偏暗的变化尤其敏感,对于高亮度的变化就稍迟钝。

加上存储空间限制,为了性能优化和让图像存储更加丰富的暗部信息(更容易让人眼感知的信息),就有了gamma压缩存储的方式。 gamma2.png

通过上图可以看出取Gamma=2.2这个值函数变化很符合人眼。

有的文章描述说是因为老式CRT屏幕的物理特性导致Gamma压缩的方式遗留下来,但是实际上这种说法是不准确的。人眼的感知能力才是Gamma校正的起因,CRT屏幕的物理特性使得老屏幕自带接近Gamma校正的特性不过是一个巧合。

因为早期为了方便使用Gamma空间进行计算和存储,即先将自然光通过Gamma压缩然后存储到硬件(图片)中,输出时就需要进行Gamma校正获取正确的自然光值。所以电脑屏幕都自带Gamma校正,业界标准为sRGB,即颜色最后输出到屏幕会自动经过硬件的一个转换:Colorout=Colorin2.2Color_{out} = Color_{in}^{2.2}

但是游戏引擎的Shader中计算一般是使用线性空间,这样对于数学模型的计算更为准确方便,但是因为主流应用和图形存储都还是按照Gamma空间(为了向下兼容?),所以从图片提取数据时需要先转换成线性空间再进行计算,结果也需要再通过Gamma压缩后输出。

Unity编码

回到Unity的光照贴图(Lightmap)编码来,编码过程中,就会遇到有线性空间的编/解码和伽马空间的编/解码,其中使用过程就要注意保持一致。 官方手册上面显示了Unity的光照贴图(Lightmap)基本使用两种编码方式: docs.unity3d.com/2020.3/Docu…

RGBM

RGBM主要是使用M系数压缩精度更高的RGB。 Unity官方Lihgtmap使用exr的格式来存储Lightmap,即openEXR。

dLDR

dLDR一般用于移动设备应用,用于节省空间,将[0,2]压缩到[0,1]。

通过官方文档可以看出来,两种格式在编/解码的时候,会因为颜色空间不同而采用不同的系数,方法一样的。这个在编写shader的时候要注意。