x20134799u 发表于 2024-7-15 18:17

Unity中 Gamma 与 Linear 颜色空间的区别?

网上的关于这部门的内容很多,下面我不筹算复制粘贴,只想用本身的白话分享下

一、什么是Gamma矫正?


Gamma 也叫灰度系数,Gamma矫正顾名思义就是对系数的一个矫正。

为什么要矫正呢,这就和显示器有关,我们之所以能在屏幕上看见颜色是因为屏幕上有RGB三原色的射线管,那给射线管施加电压后屏幕就会亮,那这里有个问题在于输入电压和输出电压并不是线性的,意思就是输入电压为1,输出电压可能是2.2 ,也可能是2.5 或者 其他值。那此刻这个值一般统一为2.2,这个值就是Gamma值,输出电压和输入电压的关系为
out = in^{gamma}

1、那矫正是怎么回事呢?


因为我们在shader计算的时候都是在线性空间下计算,就比如你要计算 1 + 1 = 2,但是给你的值不是1 ,而是 0.5 ,那么你后面所有的计算就都是不合错误的。所以需要进行矫正。

2、那为什么输入值会不合错误呢?

这是因为存储的原因,美术导出的有些图是sRGB尺度的。也就是存储长短线性的,那为什么要存非线性的呢,直接存储线性的颜色不香吗,还不用校正了,多好。Why?
其实非线性转换的目的主要是为了优化存储空间和带宽。由于人眼对暗部的变化更敏感,如果要充实操作带宽,那么就需要更多位置去存储暗部。也就是说暗部使用更高精度保留,而亮部使用更低精度保留。


上图中的红色虚线就是图像的 Gamma 矫正曲线,一般都是2.2的倒数,0.454545..。不雅察看矫正以后的曲线,本来0到0.5的区间被扩展到了0到~0.73,相应的大于0.5的区间被压缩到只有本来的一半摆布。这样通过一次简单的计算,我们达到了不增加数据量的前提下提高可辨识精度的目的。可能从来没有人告诉过你,存储在你硬盘上的图像,都是矫正过的,如下图,中间阿谁。




当然有人可能会问,矫正以后岂不是丧掉了很多亮部的细节,也不合算呀。这个问题取决于存储的数据格式,一般的格式都有足够多的冗余精度,足有保留矫正前后的所有细节,但是对于某些特定的压缩格式,比方说游戏遍及使用的 DXT 压缩格式,精度只有6Bit,也就是64阶,Gamma矫正后很多细节永久丧掉了(当然压缩算法也会丢掉很多)。


二、Unity 中 Gamma颜色空间 和 Linear 颜色空间的区别?


在 Unity 的 设置的存在着两种颜色空间选择,Editor -> Project Settings -> Player -> Other Settings -> Rendering -> Color Space,分歧的颜色空间得到的显示效果就纷歧样。




此刻的主流游戏都采用Linear 效果进行开发,保证显示效果是基于物理正确的。

Gamma颜色空间适用于无光照的2d游戏中,而且对性能没有影响。这也是在cocos2dx 引擎中并没有看到关于Gamma矫正的原因,衬着模型都是经验模型或是简单的光照,并没有基于物理的光照的计算,所以大部门情况纹理在Gamma空间采样即可。

下面列出具体适合的游戏类型,对个简单的对比:

Gamma空间适合:
1、兼容opengl es 2.0的硬件设备
2、2d游戏
3、不追求真实的物理光照效果和后期效果
4、手绘风格、画面饱和度高

线性空间适合:
1、方针机型在市场上的中高端机型
2、3d次时代风格
3、需要接近真实的基于物理的衬着和物理光照,使用PBR制作流程
4、需要HDR、Bloom、ToneMapping等后期效果

如果要在gamma空间中进行线性计算就需要在shader中额外措置,Unity 提过了如下接口:
LinearToGammaSpace (half3 linRGB)
GammaToLinearSpace (half3 sRGB)

线性和伽马混合

当混入帧缓冲区时,混合发生在帧缓冲区的颜色空间中。
使用伽马空间衬着时,非线性颜色会混合在一起。这种混合颜色的方式在数学上不正确,并可能得出不符合期望的成果,但这种方式是在某些图形硬件长进行混合的独一方式。
使用线性空间衬着时,混合发生在线性颜色空间中:这在数学上是正确的,并提供精确的成果。
下图显示了分歧类型的混合:



上:线性颜色空间中的混合发生预期的混合成果   下:伽马颜色空间中的混合导致过度饱和以及过亮的混合

三、我们应该怎么设置才能保证最后的效果是对的?


设置也很简单,其实很多工作Unity已经帮我们做了,我们需要做的就是需要确认美术提供的纹理到底是不是sRGB的。
下面给出三种资源规范:

1、场景感觉的Abedo(Base Color)贴图、特效贴图、UI贴图勾选sRGB
2、通道贴图、Alpha贴图不勾选sRGB。
3、法线贴图、光照贴图、环境贴图不需要存眷是否勾选sRGB。

也许你还是有疑问,Gamma矫正到底是哪里进行的啊?

其实这借助了图形API的硬件撑持,在移动设备开发,安卓需要撑持opengl3.0, IOS设备需要撑持Metal特性。只要由两个硬件特性来撑持:
1、sRGB Frame Buffer
sRGB Frame Buffer 将shader的计算成果输出到显示器前做gamma矫正。
2、sRGB Sampler
sRGB Sampler 将 sRGB贴图进行线性采样的转换。如果我们在线性空间中使用Gamma空间制作的贴图,勾选了sRGB选项,硬件会认为图片是Gamma空间的sRGB尺度图像,在采样时sRGB Sample会将sRGB转到线性数据。

使用硬件特性完成sRGB贴图的线性采样和shader计算成果的gamma校正,比起在shader里对贴图采样和计算成果的校正要快。

四、美术导出的资源图

Substance Painter:
当Substance贴图导出时,线性的颜色颠末gamma变换颜色被提亮了,所以需要在Unity中勾选sRGB。

Photo Shop:
如果使用线性空间,一般来说PS可以什么都不改,导出的贴图只要勾上sRGB就可以了。
如果调整PS的gamma值为1,导出的贴图在Unity中也不需要勾选sRGB了。
Unity中的混合是线性混合,ps的图层和图层之间做混合时每个上层图层都颠末了gamma变换,然后做混合,所以效果有点纷歧样。在设置中更改选择“用灰度系数混合RGB颜色”,参数设置为1,这样图层才是直接混合的成果。

参考链接:
Unity Gamma空间和线性空间
https://learnopengl-cn.github.io/05%20Advanced%20Lighting/02%20Gamma%20Correction/#gamma
UWA学堂 | Unity和Unreal游戏引擎的从业者学习交流平台
色彩校正中的 gamma 值是什么?
https://1024114.xyz/posts/465804e3/百人打算-图形-2.6 伽马校正https://1024114.xyz/posts/465804e3/
页: [1]
查看完整版本: Unity中 Gamma 与 Linear 颜色空间的区别?