2020-12-4 9:19
颜色空间
参考文章:https://www.cnblogs.com/zblade/p/10769202.html
颜色空间的存在是为了能够基本重现自然界的颜色
- 人眼对光强度的感知为非线性,对高亮部分的感知能力弱,暗部的感知能力强。
- 自然界的光强度范围极其大,而实际存储空间有限,主流对颜色亮度的表示使用8bit(即十进制范围:0-255)
- 根据上述两点得出的存储思路:将自然光以接近人眼感知能力曲线的函数进行压缩到8bit图像中。
gamma颜色空间:
- 压缩函数使用Vout=Vin^Gamma
- (Gamma通常取2.2,可以在256个灰度阶的范围内更多的保留暗部的细节——人眼对暗部的感知能力强,需要更完美的展示暗部)
线性颜色空间:
- 相机对于光强的感知是线性的,两个光子投射到相机上,得到的光强就是两倍光子光强。
- 不同于人眼,人眼对于光强的感知是非线性的,得到的不是2倍光强。
- 由于业界图片都是在Gamma空间中存储的,相机到最终图片需要进行一个编码——Gamma编码:Vout=Vin^(1/2.2)
Gamma补偿/校正:
- 相机拍摄的照片通过Gamma编码最终以Gamma空间的格式存储——sRGB。
- 显示器上显示的照片通过Gamma补偿(Vout=Vin^2.2)对Gamma空间下被压缩的图片重新转换以得到更接近自然界的图像——这一步为显示器默认执行。
三个颜色:
- 自然界颜色/相机未编码图片——线性空间
- 相机Gamma编码图片/业界图片——Gamma空间——sRGB
- 显示器默认经过Gamma校正后显示的图片——线性空间——以得到更接近自然界的图像
unity:
- shader的光学计算基于线性空间下的公式,自定义的颜色rgb也是线性空间下的。
- unity选择gamma空间后:shader计算时直接对图像(gamma空间下的数据)采样,得到的color存入colorbuff中,然后提交到显示器进行一次gamma补偿。
- unity选择linear空间后:默认图片数据是线性存储的,若图片是sRGB需要勾选该标志——shader计算时先进行一次gamma补偿得到线性存储的值,这样shader计算的都是线性空间下的数据,得到的color需要再进行gamma空间,然后提交到显示器进行一次gamma补偿。
- 无论选择哪个空间,决定的是shader计算过程中使用哪个空间下的数据,最终提交给显示器前都需要是gamma空间下的数据,然后经过gamma补偿得到真实效果。
unity具体流程:
unity中的图片在载入后可以选择是否是sRGB,默认勾选:
这样图片数据就可能存在线性空间下的数据和gamma空间下的数据。
在project settings中player的color space选择代表选择以哪种格式的数据进行shader计算,若图片数据不符合对应的选择则进行相应的转换。
例如color space选择了linear,图片选择了sRGB,那么图片数据在shader计算前会进行一次gamma校正,以获得线性空间下的数据在shader中计算。
无论选择哪种color space ,shader得到的最终结果都会被变成gamma空间下的数据,以提交给显示器时进行gamma校正。