看到這個标題,有人估計會質疑,這不蛋疼,好好的png幹嘛要分拆成兩個啊!
倘若你有如此質疑,如此憤青的言論,恭喜你來對地方了,同時也小小鄙視你一下,水準太菜了。哈哈 言歸正傳!
為什麼要這麼做?
1、主要目的為了減小包大小,同時圖檔品質損失小。手遊大家都知道,包越小轉化率越高(可玩性相同的前提下)
實作細節:把一張帶alpha通道的導入ps,在ps裡面建立一張大小跟原圖一樣,格式為位圖(為什麼要位圖,alpha值在标記透明的時候 其實就是非黑及白 也就是 0 1),複制原圖的alpha通道到建立的圖層,儲存為png,儲存原圖為JPG 這樣mask和jpg制作好了(這塊用的bmp原圖遭吐槽了,補充一份png的圖)
前後大小比較:
實作原理:
在渲染過程中,把這兩個重新還原回來,緩沖區的rgb為jpg紋理的rgb,a為mask紋理的r或g或b(為什麼是 r/g/b 儲存的mask時三個值是一樣的 不信你試試 反正我試了 好使)
shader源碼:
Shader "MaskTest" {
Properties {
_MainTex ("Base (RGB)", 2D) = "" {}
_MainMask ("Base (RGB)", 2D) = "" {}
}
SubShader {
Pass
{
Blend SrcAlpha OneMinusSrcAlpha //一定不要忘了這個
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct vert_Input
{
fixed4 vertex : POSITION;
fixed2 texcoord : TEXCOORD0;
};
struct vert_Output
{
fixed4 pos : SV_POSITION;
fixed2 texcoord : TEXCOORD0;
};
uniform sampler2D _MainTex;
uniform sampler2D _MainMask;
vert_Output vert(vert_Input i)
{
vert_Output o;
o.pos = mul(UNITY_MATRIX_MVP,i.vertex);
o.texcoord = i.texcoord;
return o;
}
fixed4 frag(vert_Output o):COLOR
{
fixed4 color1 = tex2D(_MainTex,o.texcoord);
fixed4 mask = tex2D(_MainMask,o.texcoord);
color1.a = mask.r;
return color1;
}
ENDCG
}
}
}
實作效果:
使用紋理:
這樣基本實作了功能,但是有點麻煩 還的每次計算兩個紋理,效率有點低,也不夠高大尚
參考别人的說法,是在加載紋理的時候,實作紋理合并,在記憶體中一次生成一個texture,避免在shader中的運算。實作原理就是jpg的rgb拷貝到texture的rgb,把png的r/b/g拷貝到texture的a中
核心代碼如下:
for(int i = 0; i < len; i++)
{
dest = pngData[srcIndex];//得到第一個
outPic[outIndex] = jpgData[srcIndex];
outPic[outIndex + 1] = jpgData[srcIndex + 1];
outPic[outIndex + 2] = jpgData[srcIndex+2];
outPic[outIndex + 3] = dest;
srcIndex += 3;
outIndex += 4;
}