一、问题
前段时间学习shader时发现了一个问题,一张纯红色透明度为128的图片叠加在一张纯绿色的图片上得出的结果与ps中的结果不一致。网上查找了ps中的透明混合的公式为
color = A.rgb*A.alpha + B.rgb*(1-A.alpha)。自己使用代码在unity中计算了一下结果总是不对。
红色透明度128的图 绿色图
ps中红色在上绿色在下叠加后的结果色
Unity叠加后的结果色
二、原因及颜色空间描述
其主要原因是,unity使用的颜色空间(Color Space)为线性空间(Linear),而ps使用的是伽马空间(gamma)。下面解释一下这两个空间。
1.伽马空间(gamma)。
网上搜索很多关于Gamma的文章看的最多的一句是人眼对光强的感知能力并不是线性的。这句话的意思是什么呢?下面根据图片解释一下这句话的意思。
这是一个黑白渐变图。在rgba数值中是(0,0,0,0)~(1,1,1,1)
根据上面这个图我们知道了左侧最黑色数值为0,右侧最白色数值为1,那么半灰色是不是0~1区间的中间数0.5呢?在数学中0~1的中间值的确应该是0.5。但是人眼在自然界中看到的半灰色实际在上面这张图的3/4的位置即:0.75。来我们看下面这张图:
我们根据 “物理亮度图” 第0.5的半灰色对比去找 “人类自然界感知亮度图”中对应的颜色应该是在0.75左右。所以“ 人眼对光强的感知能力并不是线性的 ”。的意思就是如此。这句话也表明了通过伽马空间(gamma)计算矫正可以使 “物理亮度图” 和 “人类自然界感知亮度图”中的数值统一对应。
公式:L= 255 * ((R/255)^2.2)
gamma=2.2
红色的虚线是经过Gamma计算后矫正的屏幕亮度曲线,而对角连接的灰色虚线是人类感知亮度。所以说伽马空间就是为了矫正我们屏幕中看到颜色与现实中人类感知颜色保持一致的。
在Unity中伽马空间中透明度混合公式: color = A.rgb*A.alpha + B.rgb*(1-A.alpha)
2. 线性空间(Linear)
这个空间对应的就是物理空间亮度图。半灰色在0~1区间中属于正常的0.5。根据伽马空间我们可以了解到人眼感受的亮度值比物理空间的亮度值暗,所以在unity中的图片亮度会比gamma矫正后的图片要亮。
2.1Texture纹理图片sRGB(Color Texture)属性
Texture纹理图片sRGB(Color Texture)属性只有在线性空间下才管用。勾选是开启gamma矫正,未勾选是不开启gamma矫正。
在线性空间下勾选了sRGB效果图:
其运算公式是 color = (A.rgb^2.2 * A.alpha + B.rgb^2.2 * (1-A.alpha)) ^ (1/2.2)
未勾选sRGB效果图:
其运算公式是 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即可。
2.PS修改为Linear
“编辑”—>“颜色设置”—>勾选“用灰度系数混合RGB颜色”。
修改后ps的最后混合颜色结果
与unity中的一致。
四、结语
以上对于伽马空间和线性空间的描述是网上查找的资料自己理解的,自己也是个小菜菜如果有不对的地方欢迎大家来纠正。