前言
之前UI那里碰到一個(gè)問(wèn)題,就是他們發(fā)現(xiàn)UGUI里拼好的界面和PS里的效果圖不一致,主要是半透明混合的區(qū)域會(huì)顯得透明度偏低。不過(guò)幸好UI以前也碰到過(guò)類(lèi)似的問(wèn)題,告知我是色彩空間的問(wèn)題(項(xiàng)目使用的是Linear線(xiàn)性空間),所以這兩天花了些時(shí)間往這個(gè)方向研究了下。
先說(shuō)一下情況:Unity在線(xiàn)性空間下,如果貼圖勾選sRGB,那么Unity可以把貼圖的RGB通道正確的還原到Gamma空間,但是對(duì)于帶Alpha半透明的貼圖,似乎不會(huì)進(jìn)行處理,在混合顏色時(shí)就會(huì)出現(xiàn)錯(cuò)誤。
問(wèn)題驗(yàn)證
首先我用代碼生成了兩張256寬度的貼圖:
- 第一張稱(chēng)它為AlphaRamp。顏色全部為純黑色(0,0,0),其Alpha從左到右為255~0。
- 第二張稱(chēng)它為GreyscaleRamp。顏色從左到右為(0,0,0)到(255,255,255),沒(méi)有Alpha(或者說(shuō)Alpha 都為1)。
理論上,這兩張圖在白底背景上以常規(guī)形式混合,其顯示效果應(yīng)該是相同的。
然后搭建一個(gè)UICanvas,背景鋪上純白底,在其之上疊加上面的貼圖,切換項(xiàng)目顏色空間(Linear和Gamma),調(diào)整貼圖的sRGB選項(xiàng)查看效果。(sRGB選項(xiàng)在Gamma空間中是無(wú)效的)
| AlphaRamp | GreyscaleRamp | |
|---|---|---|
| 項(xiàng)目使用Gamma空間 | 效果正確 | 效果正確 |
| Linear空間+勾選sRGB | 效果錯(cuò)誤 | 效果正確 |
| Linear空間+不勾選sRGB | 效果錯(cuò)誤 | 效果錯(cuò)誤 |
效果正確表示屏幕上輸出的顏色正確還原到了Gamma空間中的效果(也是Photoshop中的效果),如下圖:

效果錯(cuò)誤則表示輸出的色階為線(xiàn)性,視覺(jué)上亮色區(qū)域過(guò)多,如下圖:

此外,這個(gè)混合問(wèn)題不僅存在于UGUI里,任何涉及Alpha混合的地方都會(huì)有。我測(cè)試了兩個(gè)面片使用透明材質(zhì),使用最常規(guī)的混合模式(Blend SrcAlpha OneMinusSrcAlpha)進(jìn)行混合測(cè)試,結(jié)果也和上面的表格相同。
所以可以肯定的就是:Unity線(xiàn)性空間下的sRGB選項(xiàng)不會(huì)對(duì)Alpha進(jìn)行處理!
原因&解決
一開(kāi)始為了解決這個(gè)問(wèn)題,試過(guò)手動(dòng)對(duì)素材的Alpha進(jìn)行預(yù)處理的做法(既然Unity不處理那我們自己處理!),發(fā)現(xiàn)怎么算都得不到正確的結(jié)果——實(shí)際上怎么處理都不可能對(duì)的,因?yàn)楹髞?lái)發(fā)現(xiàn)問(wèn)題出在混合公式上。
Gamma空間下的Alpha混合公式:
Linear空間下的Alpha混合公式:
Linear工作流下,Unity會(huì)對(duì)素材進(jìn)行Gamma校正后(如果素材勾選sRGB選項(xiàng),則會(huì)對(duì)素材進(jìn)行預(yù)處理),再進(jìn)行混合計(jì)算,最后對(duì)結(jié)果進(jìn)行Gamma還原。
有辦法在混合公式上修改嗎?Shader里能對(duì)混合算法進(jìn)行的操作十分有限,只憑借Blend和BlendOp兩個(gè)混合命令似乎無(wú)法達(dá)到修正的效果。
最后項(xiàng)目里采取的做法是——項(xiàng)目里所有UI素材取消勾選sRGB選項(xiàng),以線(xiàn)性的顏色進(jìn)行輸入,此時(shí)Alpha混合公式就變成了:
?
然后只要在最后輸出的顏色上進(jìn)行一次pow(2.2)的處理(在UI相機(jī)上添加后處理實(shí)現(xiàn)),顏色就和Gamma空間下的完全一樣了。