Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)

一、问题及原因

1.遇到的问题 

前段时间学习shader时发现了一个问题,一张纯红色透明度为128的图片叠加在一张纯绿色的图片上在unity中得出的结果与ps中的结果不一致。网上查找了ps中的透明混合的公式为 

color = A.rgb*A.alpha + B.rgb*(1-A.alpha)。自己计算了一下结果总是不对。 

红色透明度128的图                                          绿色透明度255的图

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第1张图片                               Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第2张图片

 ps中红色在上绿色在下叠加后的结果色

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第3张图片    Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第4张图片

 Unity叠加后的结果色

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第5张图片Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第6张图片

可以明显看出ps混合后的数值要比unity中的数值低。

2.产生的原因 

问题产生原因是unity使用的颜色空间(Color Space)为线性空间数值(Linear),而ps使用的是伽马矫正后的空间数值(gamma)。一般被gamma矫正后的图片会比线性空间的数值要低。所以ps混合后的数值要比unity中的数值低。

二、关于颜色空间描述

1.伽马空间(gamma)。

在查阅资料学习时关于gamma矫正产生的原因基本上围绕着两点

1. CRT 显示器的物理特性

2. 人眼对光强的感知能力并不是线性的

 1.1 伽马矫正之CRT显示器的问题

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第7张图片

在早期我们的电脑显示器基本上是阴极射线管显示器(CRT),就是上面有个后脑勺的显示器。显示器一般是通过电压来控制每个像素的数值从而显示出图片的,但是CRT显示器有一个物理特性是输入的电压会输出为约等于输入电压2.2次幂的亮度。从理论上讲这个值应该是2.5倍,但在当时根据实际统计市面上的产品的特性总结出来的值约是2.2倍。这样就会导致显示器的图比实际图像要暗。图片借用文章

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第8张图片

我们想要让图片最终展示的亮度与原图一致就需要对gamma2.2进行一个矫正,这个矫正值就是gamma1/2.2(2.2次幂的对数0.45) ,看下方的矫正示意图。

 Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第9张图片

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第10张图片

我们为什么要进行gamma1/2.2(0.45)的矫正呢?除了上方需要与gamma2.2进行抵消后显示原图外还有一点就是我们渲染计算的数值要在伽马值为 1 的理想线性空间进行的。

这里举个例子:

矫正图来看假如我们输入一个暗红色的光照RGB颜色为(0.5, 0.0, 0.0)的图, 然后将这个颜色提升一倍变为(1.0, 0.0, 0.0). 但由于显示器的非线性特性, 我们最终调节的颜色实际是从 (0.218, 0.0, 0.0) 变成了 (1.0, 0.0, 0.0)

所以gamma矫正是为了解决CRT的物理特性。但基于人眼的感知特性这个gamma矫正又是怎么实现的呢?我们继续往下看。

1.2 伽马矫正之人眼的感知特性并不是线性的

这是一个黑白渐变图。在rgba数值中是(0,0,0,1)~(1,1,1,1)

1b623707c828454d9fed8aa40fd77e48.png根据上面这个图左侧黑色数值为0,右侧白色数值为1,那么半灰色是不是0~1区间的中间数0.5呢?在数学中0~1的中间值的确应该是0.5。但是人眼在自然界中看到的半灰色实际在上面这张图的3/4的位置即:0.75。来我们看下面这张图:

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第11张图片

我们根据 “物理亮度图” 第0.5的半灰色对比去找 “人类自然界感知亮度图”中对应的颜色应该是在0.75左右。所以“ 人眼对光强的感知能力并不是线性的 ” 的意思就是如此。

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第12张图片

人类的视觉系统在黑暗环境下的辨识能力要强于明亮环境这是进化过程中出现的特性, 这样有助于我们及时发现黑暗中隐藏的危险。而且人眼的这一特性与CRT显示器的gamma2.2相似。

1.3 CRT显示器与人眼特性的关系

网上查的好多资料视频有的说gamma矫正是因为人眼感知特性,有的又说是为了解决CRT显示问题。但其实一开始gamma矫正是为了解决CRT的物理特性巧合的是人眼的感知特性也是如此,而且后面Led等液晶显示器现世后已经可以达到与现实色彩呈线性的数值因为人眼特性和兼容CRT显示器处理的图片才保留了gamma矫正。我感觉这才是正确的。如果有什么不对的也欢迎大家指正。

其他:

  1. gamma本身是人眼对于不同灰阶画面切换时候,一个让眼睛觉得更自然的亮度补充.
  2. 保存在计算机中的图片数据是经过gamma1/2.2(0.45)后的数据。

2. 线性空间(Linear)

这个空间对应的就是物理空间亮度图。半灰色在0~1区间中属于正常的0.5。根据上方伽马空间描述了解到人眼感受的亮度值比实际物理空间的亮度值暗,所以unity中线性空间下的图片亮度会比gamma矫正后的图片要亮。

2.1Texture纹理图片sRGB(Color Texture)属性

Texture纹理图片sRGB(Color Texture)属性只有在线性空间下才管用。勾选是开启gamma矫正,未勾选是不开启gamma矫正。

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第13张图片

在线性空间下勾选了sRGB效果图:

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第14张图片

运算公式 color = (A.rgb^2.2 * A.alpha + B.rgb^2.2 * (1-A.alpha)) ^ (1/2.2)   

未勾选sRGB效果图:

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第15张图片

运算公式 color = (A.rgb * A.alpha + B.rgb*(1-A.alpha)) ^(1/2.2)   

三、解决方法 

1.将unity改为伽马空间(gamma)

修改 File—>Build Settings—>Player Settings—>Other Setting选项卡中的Color Space为gamma即可。

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第16张图片

2.PS修改为Linear 

 “编辑”—>“颜色设置”—>勾选“用灰度系数混合RGB颜色”。

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第17张图片

 修改后ps的最后混合颜色结果 与unity中的一致。

Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第18张图片Unity之透明度混合与ps的透明度混合计算结果不一致(gamma矫正和线性空间)_第19张图片

你可能感兴趣的:(Unity,ASE,数学建模)