NGUI下alpha通道的分离与合并

发表于2018-08-24
评论0 3.3k浏览
U3D发布到iOS平台时,图片压缩格式一般设置成PVRTC,而发布到Android平台时候一般需要设置成ETC1,这样做的目的是为了图片压缩力度更大,降低内存的消耗。但是问题来了,Android下ETC1格式不支持Alpha通道,而且带Alpha通道的图消耗非常大。所以,为了能降低各种贴图的消耗,需要把贴图的RGB与alpha通道拆分出来保存为两张图,一张图只保存RGB信息,另外一张只保存Alpha信息。

1.使用texturepacker制作图集

首先在网上随便找了两张带Alpha通道的图片,导入texturepacker,设置如下图:

publish后生成一张PNG图和一个txt文件如图:

然后导入到Unity3D中,制作图集,具体如何制作NGIU图集可Google(不太喜欢用度娘),做好的图集如图:

好了,到此我们的图集做好了,然后随便弄个按钮或者精灵出来,看看它消耗多大(因为随便找的图,所以比较大,暂时不要惊慌失措,只是为了后面有一个比较),如下图:
到此,原图占用2M。

2、拆分贴图的ALpha通道

具体如何拆分Alpha通道,有很多种办法,比如直接在PS中拆分,也可以在Unity3D中写工具,工具的具体代码可参考博友的文章:http://blog.csdn.NET/u010153703/article/details/45502895。其实核心就这部分:
Texture2D rgbTex = new Texture2D(sourcetex.width, sourcetex.height, TextureFormat.RGB24, true);  
       Texture2D alphaTex = new Texture2D((int)(sourcetex.width * sizeScale), (int)(sourcetex.height * sizeScale), TextureFormat.RGB24, true);  
       for (int i = 0; i < sourcetex.width; ++i)  
           for (int j = 0; j < sourcetex.height; ++j)  
           {  
               Color color = sourcetex.GetPixel(i, j);  
               Color rgbColor = color;  
               Color alphaColor = color;  
               alphaColor.r = color.a;  
               alphaColor.g = color.a;  
               alphaColor.b = color.a;  
               rgbTex.SetPixel(i, j, rgbColor);  
               alphaTex.SetPixel((int)(i * sizeScale), (int)(j * sizeScale), alphaColor);  
           }  
       rgbTex.Apply();  
       alphaTex.Apply();  
       byte[] bytes = rgbTex.EncodeToPNG();  
       File.WriteAllBytes(GetRGBTexPath(_texPath), bytes);  
       bytes = alphaTex.EncodeToPNG();  
       File.WriteAllBytes(GetAlphaTexPath(_texPath), bytes);  

对上图中TP这张图拆分后得到TP_RGB和TP_Alpha两张图:

对于拆分后的两张图怎么合并回去呢,可以通过在Shader中处理,具体代码如下:
Shader "Unlit/Merge RGB And Alpha"  
{  
 Properties  
 {  
 _MainTex ("rgb tex", 2D) = "black" {}  
 _AlphaTex("alpha tex",2D) = "white"{}  
 }  
 SubShader  
 {  
 LOD 100  
 Tags  
 {  
 "Queue" = "Transparent"  
 "IgnoreProjector" = "True"  
 "RenderType" = "Transparent"  
 }  
 Cull Off  
 Lighting Off  
 ZWrite Off  
 Fog { Mode Off }  
 Offset -1, -1  
 Blend SrcAlpha OneMinusSrcAlpha  
 Pass  
 {  
 CGPROGRAM  
 #pragma vertex vert  
 #pragma fragment frag  
 #include "UnityCG.cginc"  
 struct appdata_t  
 {  
 float4 vertex : POSITION;  
 float2 texcoord : TEXCOORD0;  
 fixed4 color : COLOR;  
 };  
 struct v2f  
 {  
 float4 vertex : SV_POSITION;  
 half2 texcoord : TEXCOORD0;  
 fixed4 color : COLOR;  
 };  
 sampler2D _MainTex;  
 float4 _MainTex_ST;  
 sampler2D _AlphaTex;  
 float4 _AlphaTex_ST;  
 v2f vert (appdata_t v)  
 {  
 v2f o;  
 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);  
 o.texcoord = v.texcoord;  
 o.color = v.color;  
 return o;  
 }  
 fixed4 frag (v2f i) : COLOR  
 {  
 //fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;  
 //return col;  
 fixed4 texcol = tex2D(_MainTex, i.texcoord);   
 fixed4 result = texcol;  
 result.a = tex2D(_AlphaTex,i.texcoord).r*i.color.a;  
 //灰度计算  
  if (i.color.r < 0.001)   
    {   
        //float grey  =  dot(result.rgb, float3(0.299, 0.587, 0.114));   
        //整数运算速度更快  
        float gray = (result.r*299 + result.g*587 + result.b*114 + 500) / 1680;  
        result.rgb = float3(gray, gray, gray);   
    }   
 return result;  
 }  
 ENDCG  
 }  
 }  
 SubShader  
 {  
 LOD 100  
 Tags  
 {  
 "Queue" = "Transparent"  
 "IgnoreProjector" = "True"  
 "RenderType" = "Transparent"  
 }  
 Pass  
 {  
 Cull Off  
 Lighting Off  
 ZWrite Off  
 Fog { Mode Off }  
 Offset -1, -1  
 ColorMask RGB  
 AlphaTest Greater .01  
 Blend SrcAlpha OneMinusSrcAlpha  
 ColorMaterial AmbientAndDiffuse  
 SetTexture [_MainTex]  
 {  
 Combine Texture * Primary  
 }  
 }  
 }  
}  

这时候,从新再弄个按钮或者精灵来看看效果如下:

基本上可以很好的还原原图。好了,我们在Profiler比较一下现在这两张图到底占了多少内存,入下图:

拆分后的两张图加起来大概1.25M了。来自:https://blog.csdn.net/ethuangfen/article/details/53764070

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引