前言
之前UI那里碰到一個問題裳食,就是他們發(fā)現(xiàn)UGUI里拼好的界面和PS里的效果圖不一致矛市,主要是半透明混合的區(qū)域會顯得透明度偏低芙沥。不過幸好UI以前也碰到過類似的問題诲祸,告知我是色彩空間的問題(項目使用的是Linear線性空間),所以這兩天花了些時間往這個方向研究了下而昨。
先說一下情況:Unity在線性空間下救氯,如果貼圖勾選sRGB,那么Unity可以把貼圖的RGB通道正確的還原到Gamma空間歌憨,但是對于帶Alpha半透明的貼圖着憨,似乎不會進行處理,在混合顏色時就會出現(xiàn)錯誤务嫡。
問題驗證
首先我用代碼生成了兩張256寬度的貼圖:
- 第一張稱它為AlphaRamp甲抖。顏色全部為純黑色(0,0,0)漆改,其Alpha從左到右為255~0。
- 第二張稱它為GreyscaleRamp准谚。顏色從左到右為(0,0,0)到(255,255,255)挫剑,沒有Alpha(或者說Alpha 都為1)。
理論上柱衔,這兩張圖在白底背景上以常規(guī)形式混合樊破,其顯示效果應該是相同的。
然后搭建一個UICanvas唆铐,背景鋪上純白底哲戚,在其之上疊加上面的貼圖,切換項目顏色空間(Linear和Gamma)艾岂,調(diào)整貼圖的sRGB選項查看效果顺少。(sRGB選項在Gamma空間中是無效的)
AlphaRamp | GreyscaleRamp | |
---|---|---|
項目使用Gamma空間 | 效果正確 | 效果正確 |
Linear空間+勾選sRGB | 效果錯誤 | 效果正確 |
Linear空間+不勾選sRGB | 效果錯誤 | 效果錯誤 |
效果正確表示屏幕上輸出的顏色正確還原到了Gamma空間中的效果(也是Photoshop中的效果),如下圖:
效果錯誤則表示輸出的色階為線性王浴,視覺上亮色區(qū)域過多祈纯,如下圖:
此外,這個混合問題不僅存在于UGUI里叼耙,任何涉及Alpha混合的地方都會有腕窥。我測試了兩個面片使用透明材質(zhì),使用最常規(guī)的混合模式(Blend SrcAlpha OneMinusSrcAlpha)進行混合測試筛婉,結(jié)果也和上面的表格相同簇爆。
所以可以肯定的就是:Unity線性空間下的sRGB選項不會對Alpha進行處理!
原因&解決
一開始為了解決這個問題爽撒,試過手動對素材的Alpha進行預處理的做法(既然Unity不處理那我們自己處理H肭),發(fā)現(xiàn)怎么算都得不到正確的結(jié)果——實際上怎么處理都不可能對的硕勿,因為后來發(fā)現(xiàn)問題出在混合公式上哨毁。
Gamma空間下的Alpha混合公式:
Linear空間下的Alpha混合公式:
Linear工作流下,Unity會對素材進行Gamma校正后(如果素材勾選sRGB選項源武,則會對素材進行預處理)扼褪,再進行混合計算,最后對結(jié)果進行Gamma還原粱栖。
有辦法在混合公式上修改嗎话浇?Shader里能對混合算法進行的操作十分有限,只憑借Blend和BlendOp兩個混合命令似乎無法達到修正的效果闹究。
最后項目里采取的做法是——項目里所有UI素材取消勾選sRGB選項幔崖,以線性的顏色進行輸入,此時Alpha混合公式就變成了:
?
然后只要在最后輸出的顏色上進行一次pow(2.2)的處理(在UI相機上添加后處理實現(xiàn)),顏色就和Gamma空間下的完全一樣了赏寇。