欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > Unity中的伽马(Gamma)空间和线性(Linear)空间

Unity中的伽马(Gamma)空间和线性(Linear)空间

2025/2/27 12:45:11 来源:https://blog.csdn.net/qq_65461674/article/details/139601547  浏览:    关键词:Unity中的伽马(Gamma)空间和线性(Linear)空间

伽马空间定义:通常用于描述图像在存储和显示时的颜色空间。在伽马空间中,图像的保存通常经过伽马转换,使图片看起来更亮。

gamma并不是色彩空间,它其实只是如何对色彩进行采样的一种方式

为什么需要Gamma:

在游戏业界长期以来都忽视一个伽马矫正的问题,这就导致渲染出来的效果要么过曝,要么过暗,总是和真实世界不同。

尽管是使用了同一shader渲染,但选择颜色空间不同和处理gamma矫正时做法不同,就导致结果不同

CRT的亮度和施加电压不成线性

人眼和响应不成线性

unity中可以在此处选择不同的颜色空间,如图

 一、Gamma空间与线性空间

什么是线性颜色空间?

如图,横轴为输入给显卡进行渲染的的颜色,纵轴为显卡渲染后输出到显示器的颜色结果

所有线性空间就是输入等于输出的 ColorOut=ColorIn^{1} 

输入的颜色不进行任何处理 Gamma值为1

但现实世界要做到输入颜色等于输出颜色是很难的

因为显示器的颜色输出不是线性的,不同显示器输出的也是不同的

人眼对光强的感知能力并不是线性的——对暗部颜色变化更敏感,但很难识别亮部的颜色差异。

 RGB=0.5的灰色,但其物理亮度(光子数)却只有纯白(RGB=1)的22%。

这时为什么呢?为何不是线性的呢?

人们之所以不设定RGB值与亮度值线性相关,是因为人眼更善于发现暗部中亮度的细微差别。

人眼对光强的感知能力并不是线性的——对暗部颜色变化更敏感,但很难识别亮部的颜色差异。

 

在某些阴暗的环境下,点亮一盏灯,这时人眼就会觉得非常亮。如果同时点亮1000盏灯,反而觉得只是10倍的亮度,对亮度的认知相当于从0~1再从1~10.

 因为人眼不易识别亮部的颜色差异,这就导致了在亮部,我们不需要那么多的空间去存储亮度值,因为人眼根本就难以区别它们,如果按照线性存储,就会导致亮部空间的浪费。

所以在电子图象存储技术中,人们降低亮部的采样数来节约磁盘空间——或者说,在不增加数据量的前提下,分配更多的采样数给暗部以提高可辨识精度。

相机捕获到现实世界真实的光的信息,经过处理后显示到屏幕上,我们希望物理世界中的真实值能够于显示器中的呈现值相同,那么怎么做呢?

先来看一下这个做法的演变过程

从最简单的模型演变

(1)图片真实值0.2->(亮部浪费)图片存储值0.2->提交值0.2->(pow 2.2)呈现值0.029 (缺点:浪费存储空间、早期计算机无法直接让呈现值等同于提交值)

(这个2.2是历史问题,但后来对我们是有益的,所有就沿用下来并未修复)

改善以上问题:

(2)图片真实值0.2->(pow 0.45)图片存储值0.48->提交值0.48->(pow 2.2)呈现值0.2

游戏业界带来新的问题:

(3)图片真实值0.2->(pow 0.45)图片存储值0.48->光照计算0.48*2->提交值0.96->(pow 2.2)呈现值0.914(严重偏离真实值0.2*2=0.4)

二、伽马矫正

最后我们的具体做法是:相机捕获到现实世界真实的光的信息,然后对这些数据开n次方根(n即gamma值,一般取1.8~2.2),Output=Input^{\frac{1}{gamma}},然后通过采样存储图像。这样存储的图像就是经过Gamma校正的图像。

线性的光信号变成了非线性的电信号。

而在显示器上显示图片时,则需要做一次逆Gamma校正:Output=Input^{gamma}

将非线性的电信号转换成线性的光信号。

总结一下就是: 

想要游戏的效果接近真实世界,那么就需要保证在光照计算之前处于线性空间!

sRGB=Gamma^{\frac{1}{2.2}} = Gamma矫正=Gamma 0.45    提亮

Gamma 2.2 = Gamma 空间

Gamma 1 = 线性空间

Color * Gamma 1/2.2 * Gamma 2.2 = Color * Gamma 1 = Color

假如摄像机不做Gamma矫正,会是什么情况?

三、sRGB

unity在贴图的导入设置面板中有“sRGB(Color Texture)”选项,勾选它,告诉Unity这是一张sRGB贴图,需要对它做sRGB解码才可以获得用于光照计算的数据;不勾选,即表示这是一张线性贴图,这张贴图的RGB数据可直接用于光照计算。

sRGB是一种颜色空间,它的定义包括White Point、Primaries、OETF、EOTF

Color SpaceWhite PointPrimariesOETFEOTF
sRGBD65R(0.640,0.330),
G(0.300,0.600),
B(0.150,0.060)
δ=12.92,
β=0.0031308,
α=1.055,
γ=12/5
2.2
Rec.709同 sRGB同 sRGBδ=4.5,
β=0.004,
α=1.099,
γ=20/9
~2.4

sRGB标准和Rec.709标准所定义的白点、三元色相同,只是传递函数的定义不同;

下图的马蹄形区域表示人眼能够感知到的最大色域,三角形围起来的区域即 sRGB / Rec.709 的色域:

 

1.色域: sRGB首先设定了RGB三个基色的坐标

2.白点: sRGB也规定了白点位置

3.gamma: sRGB的gamma设定为≈2.2也就是说从外而向内切,先切的很细,然后逐渐变粗

sRGB的编码伽马值实际是12/5=1/2.4,但我们常听说的是1/2.2,这是因为完整版本的伽马函数【1.055*x ^(1/2.4)-0.055】在形状上更接近【x ^(1/2.2)】,如下图的黑线更接近红线,而不是绿线,红线【x ^(1/2.2)】就被大家当做是简化版本的伽马矫正啦:

渲染时的图片来源,不论是照片还是DCC软件,还是手绘和渲染,都是在sRGB颜色空间下工作的

Substance Painter导出贴图时,会对提供色彩信息的贴图(比如Albedo和Specular Color)做sRGB编码(目的是为了让贴图看起来更舒服,匹配人眼感知,同时优化数据存储),所以我们应把它们当作sRGB贴图来使用;而对法线贴图/金属度贴图这类用以存储数值信息的贴图,是不做sRGB编码的,所以我们应把它们当作线性贴图来使用。

对sRGB编码的图片是直接使用还是转换使用?

线性空间:直接用(系统替我们转换)

Gamma空间:手动转换

四、Unity线性空间流程图

 关于 Gamma 与线性的混淆

色彩空间为什么那么空?色度系统、色度图、色域、伽马、白点...  

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词