您好,登錄后才能下訂單哦!
這篇文章主要介紹“Spine的紋理壓縮和半透顯示的實現方法”,在日常操作中,相信很多人在Spine的紋理壓縮和半透顯示的實現方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spine的紋理壓縮和半透顯示的實現方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
如果使用Spine的默認輸出格式,是這樣的
但是輸出紋理的格式必須是未壓縮的RGBA,如果你將圖片格式改為ETC2或者ASTC,就會變成這樣:
而這是絕對不能容忍的畫面瑕疵。
ETC2的壓縮質量絕不至于這樣差,之所以會變成這樣,在于Spine的默認輸出格式是勾選了“預乘(premultiplied alpha)”參數的,這種做法會將圖片原始的RGB通道預先乘以透明度保存成文件,顯示時再用特殊的Shader乘回去。而ETC2的壓縮算法并沒有考慮過這種情況,由此導致了壓縮質量降低。
而之所以Spine要使用預乘(premultiplied alpha),目的是為了解決透明圖片的采樣問題。
如圖,左邊的像素點是純透明,右邊的像素點是白色點,如果在紅點處采樣,獲得的顏色值就是(0.5,0.5,0.5,0.5)
而正確的顏色值應該是(1,1,1,0.5),因為變化的只應該是透明度,不能因為達到邊緣,連圖像本身的亮度都降低。
預乘是能完美的解決這個問題的,它生成的像素點是(0x0,0x0,0x0,0),(1x1,1x1,1x1,1),采樣后的顏色是0.5,0.5,0.5,0.5,但還原的時候還要再除以透明度,所以結果是(0.5/0.5,0.5/0.5,0.5/0.5,0.5)=(1,1,1,0.5),能夠得到正確的值。
而除了預乘以外,還有另一個方法,就是讓透明度為0的區域也填充有顏色。雖然有顏色,但因為透明度是0,看上去依然是透明,如圖:
這種操作叫做出血(bleeding)。排除掉透明通道,可以看到出血后圖片會復制邊緣的像素到臨近的透明區域。
雖然在某些特殊的采樣角度下會有錯誤,但大部分情況沒問題,而這種方法可以正常支持壓縮紋理。
Bleeding可以在Spine的輸出窗體設置,也可以勾選Unity圖片的Alpha Is Transparency激活。
所以,我們應該取消Spine的premultiplied alpha選項,并勾選Bleeding選項來生成普通的圖片(SpineEditorUtilities.cs有自動導入腳本,需要修改,否則圖片參數會被它重新設置回去)。
Shader內,直接用最普通的方式繪制就好了。
瑕疵依然存在,但是回到了普通不透明圖片的壓縮質量水準。(具體質量要看使用的壓縮格式,比如ASTC肯定要比ETC2更好)
——但是,Spine并不能直接用普通的Alpha Blend方式繪制貼圖。
Spine的整個Shader都是基于Blend One OneMinusSrcAlpha,也就是預乘混合模式。它要求frag輸出的顏色通道必須是預乘過Alpha通道的,所以,如果輸入的圖片是未預乘的,就要在采樣后乘上透明度,再輸出。
col = tex2D(_MainTex,xxxxx);
col.rgb *= col.a;
倒也簡單,但為什么不直接將混合模式直接改成普通的Blend SrcAlpha OneMinusSrcAlpha呢?這就是下個話題的內容——
Alpha Blend 對應的是 Blend SrcAlpha OneMinusSrcAlpha,
相當于lerp(x.rgb,y.rgb,x.a),也就是result = (x.r, x.g, x.b) * x.a + (y.r, y.g, y.b) * (1 - x.a)
Additive則是result = (x.r, x.g, x.b) *x.a + (y.r, y.g, y.b)
而預乘混合Blend One OneMinusSrcAlpha是result = (x.r, x.g, x.b) + (y.r, y.g, y.b) * (1 - x.a),由于我們的紋理并不是預乘過的,而是在shader內相乘,所以是za = x.a,result = (x.r, x.g, x.b) * za + (y.r, y.g, y.b) * (1 - x.a),結果上和Alpha Blend相同。
但這里,za和x.a其實是不同的參數,我們可以讓它是不同的值。如果za和x.a始終相等,就是AlphaBlend,如果讓za=x.a,同時把x.a賦值為0,那么結果就是result = (x.r, x.g, x.b) *x.a + (y.r, y.g, y.b) * (1 - 0)。
和Additive是相同的。
Spine就是用這種方式同時顯示AlphaBlend和Additive的圖片的,它的頂點色是預乘過的,比如白色50%透明度就是(0.5,0.5,0.5,0.5),而如果是Additive的部分,白色50%透明度就是(0.5,0.5,0.5,0),因為透明度為0,所以輸出的x.a永遠都是0,效果就和Additive相同。
這樣直接乘在顏色值上,然后用Blend One OneMinusSrcAlpha輸出就可以了。
如果并不是將透明度重置為0,而是取一個中間值,還可以得到Alpha Blend和Additive中間的一個結果,在Alpha Blend太暗,Additive太亮的時候可以考慮(一般特效美術會選擇用兩個不同材質的紋理疊加,其實沒必要)
GrabPass是不可取的,因為存在透明物體的半透疊加。所以唯一的方法就是繪制到RT上再顯示。
這時候就會遇到同時繪制Alpha Blend和Additive的問題。需要將攝像機的ClearColor設置成0,0,0,0(而不是0,0,0,1),Alpha的物體不能有ColorMask,Additive的物體需要ColorMask RGB(或者Alpha值為0)。
而顯示RT時,必須用Blend One OneMinusSrcAlpha才能正確,否則Addtive的部分會沒效果。
在這種情況下,設置為半透不能只修改alpha值,而且是要同時修改全部通道。
Blend One OneMinusSrcAlpha的物體只修改Color的Alpha值,相當于在AlphaBlend和Additive的顯示效果之間調整,其實還挺便利的。這個中間的部分其實很適合用來模擬科幻場景的空氣投影屏幕,因為AlphaBlend太實,Additive又太像光。
而真正的空氣投影屏幕誰也沒見過,畢竟都沒誕生。
很多人對Mipmap有誤解,認為這是一個優化手段,而且是在處理遠近物體的時候用的。
Mipmap最初的目的其實是為了處理紋理走樣問題,優化只是一個副產品。
比較著名的示例是這個,又稱為摩爾紋。
在立繪的情況下是這個,也算是紋理鋸齒的一種。
至于出現的原因?紋理過濾時,圖像的放大其實和PS里是類似的,也就是普通的2次線性插值,但是縮小時則完全不同。PS將圖像縮小一倍,目標像素是對應的4個像素的平均值,但是在紋理過濾的時候,只會取的最近的1個像素的值。
很顯然,這是為了效率考慮。
mipMap則將這4個像素的平均值預先儲存了一份,這種情況下就可以直接取值了。其實效率是差不多的,但只有mipMap的才是正確的。
但在兩個mipMap層級中間的時候,即使使用三向過濾或者多重采樣過濾,會從兩個mipMap層級之間插值,依然還是不正確的。因為采樣了低分辨率的圖像,還會導致圖像產生模糊。
也就是在信號學所說的“在不提高分辨率的情況下,我們只能把信號中無法還原的高頻部分拋棄掉,避免出現劇烈的變化,來實現所謂的反走樣”,即是,想要反走樣,就必須承擔一定程度的模糊。想要反走樣又不想模糊,只有一個辦法,提升分辨率。
出現走樣并不需要3D,只要你的圖片存在兩個像素被并進一個像素顯示的情況(這通過縮放也可以達成),如果你的圖片分辨率高于屏幕分辯率就更是如此。
不過,大部分走樣效果并不明顯,因為人眼會自己修正。但是,如果你的物體是運動的,走樣就會產生另一種效果“閃爍”,這就非常明顯了。上面的鋸齒其實也算是一種線段的時隱時現。
如果你的圖片是靜態的,用一點點走樣換取圖片的“清晰”其實更合算。但是動態立繪,請不要。
當然,如果你的分辨率極高,高到人眼無法分辨,走樣確實也無所謂了。
但這樣的話,模糊也同樣無所謂。
而且別忘了,Mipmap確實在很多情況下可以提高性能。
到此,關于“Spine的紋理壓縮和半透顯示的實現方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。