问题描述:如果项目切到过线性空间,或者一开始就在线性空间,而美术制作ui的时候没有做设置,那么很快你就能发现这个问题了。美术会发现他们制作的ui效果和在unity里摆出来的不一样,特别是设计到透明度混合等问题
问题的根源:
比如AB两个图层,A在上层,B在下层,A的alpha不为1
PS中默认的工作空间是Gamma空间,半透明图层使用的混合公式如下:
color = A.rgb*A.alpha + B.rgb*(1-A.alpha) (公式1)
如果unity是Gamma空间,那么同样UI层级的混合公式:
color = A.rgb * A.alpha + B.rgb *(1-A.alpha) (公式2)
如果unity是线性空间,如果图勾选了sRGB,则图被认为是存于gamma空间,则首先转到线性空间,然后进行混合:
color = (A.rgb^2.2 * A.alpha + B.rgb^2.2 * (1-A.alpha)) ^ (1/2.2) (公式3)
线转到线性空间内进行混合,然后最后将整个颜色进行gamma编码到gamma空间,因为最后显示器显示的时候会进行gamma矫正
如果没有勾选sRGB,则
color = (A.rgb * A.alpha + B.rgb*(1-A.alpha)) ^(1/2.2) (公式4)
根据以上的公式来看,如果unity是gamma空间,则很好,ps和unity的效果是一致的。如果unity不在gamma空间,则这里必然会出问题。
最容易想到的解决问题的办法,就是给ps调整到线性空间,也就是调整(公式1),将其变为(公式3),这个方法可以使用:编辑-》颜色设置
这个使用灰度系数混个RGB来达成,这样在PS里虽然还是在gamma空间下制作,但是显示以及alpha混合的时候,已经转为线性空间了,这样美术在PS里看到的效果和unity里的最终效果就相同了, 改了这个之后,可以看到画布上的混合会变化。但是工作空间还是在gamma空间哦,这里千万不要理解错。
还有一种办法是将PS里的公式从(公式1)调整为(公式4),也就是在ps里直接就在线性空间下工作,设置方法如下:编辑-》颜色设置:
工作空间:rgb这里,改为自定义 ,然后
灰度系数由2.2,改为1.0.
这样就不需要再勾选那个用灰度系数混合RGB了,因为现在灰度系数原本就是1.0.
这样在ps下看的结果和unity里也会是一样的,所以也可以达到目的。
但是这个工作虽然是在线性空间下制作的,但是unity导出里会有设置导出成sRGB,也就是你存图的时候,又存成了sRGB,不过这个也无所谓,因为你如果导出设置里选的是sRGB,那么unity导入设置里也勾选就行了。
如果想真正导出线性空间的图,那么可以这样设置:
文件-》导出-》导出首选项:
把这里的转为sRGB勾选调,那么你导出的图就是在线性空间了。但是unity里记得也要给对应的勾勾选掉。不然会被认为是sRGB的图,直接给你来一次gamma编码,导致颜色变深。
但是转为线性空间工作,对美术也有一些小影响:
看下以下两个拾色器:
线性空间
可以看到,gamma空间的颜色看起来比线性的好像有更多选择,这是因为人眼对灰度的识别问题,暗的部分我们的眼睛更容易分辨出颜色的色差。
这个只能靠美术克服一下了。
其它解决办法:
1、UI使用单独的相机渲染,整个渲染在gamma空间下进行,渲染完毕之后和场景相机blend。大概步骤应该如下:
1、申请一个线性空间的rt,r8g8b8a8_unorm的rendertexture作为ui相机的RT
2、将所有导出的sRGB的图都不要勾选导入的sRGB,这样就会读取原值,而不用转换
3、进行正常的ui渲染及混合,也就是使用公式2
4、等全部ui渲染完毕,将这个rt先 rt.rgb ^ 2.2转化到线性空间,然后和主场景进行blend,这个结果会写到主场景相机的r8g8b8ab_srgb的图里,最后写进CameraTarget,这个会自动进行gamma编码 也就是结果sceneRT^(1/2.2),最后获得和ui设计一样的ui结果。
我认为较好的解决办法:
个人感觉线性空间下制作会比较好,效率也不错,而且不用单独搞一套相机渲染,还有就是如果模型和ui混合摆放的话,使用单独的ui相机也会比较麻烦。