Unity3d之剥离alpha通道

unity中, 将图集的 alpha 通道剥离出来可减少包体大小和内存使用大小。

方法是将原来的一张 rgba 图分成一张 rgb 和一张 alpha 图,android上rgb和alpha图均采用etc压缩格式,ios上采用pvrtc格式。其中alpha通道信息可以存在r中。

 

分享 alpha 通道工具的源代码如下: 

  1 using System;
  2 using System.IO;
  3 using UnityEditor;
  4 using UnityEngine;
  5 
  6 public static class TextureAlphaSpliter
  7 {
  8     const string
  9         RGBEndName = "(rgb)",
 10         AlphaEndName = "(a)";
 11 
 12     public static bool WhetherSplit = true;
 13     public static bool AlphaHalfSize;
 14 
 15     static Texture s_rgba;
 16 
 17     public static void SplitAlpha(Texture src, bool alphaHalfSize, out Texture rgb, out Texture alpha)
 18     {
 19         if (src == null)
 20             throw new ArgumentNullException("src");
 21 
 22         // make it readable
 23         string srcAssetPath = AssetDatabase.GetAssetPath(src);
 24         var importer = (TextureImporter)AssetImporter.GetAtPath(srcAssetPath);
 25         {
 26             importer.isReadable = true;
 27             importer.SetPlatformTextureSettings("Standalone", 4096, TextureImporterFormat.ARGB32, 100, true);
 28             importer.SetPlatformTextureSettings("Android", 4096, TextureImporterFormat.ARGB32, 100, true);
 29             importer.SetPlatformTextureSettings("iPhone", 4096, TextureImporterFormat.ARGB32, 100, true);
 30         }
 31         AssetDatabase.ImportAsset(srcAssetPath);
 32 
 33         alpha = CreateAlphaTexture((Texture2D)src, alphaHalfSize);
 34         rgb = CreateRGBTexture(src);
 35     }
 36 
 37     static Texture CreateRGBTexture(Texture src)
 38     {
 39         if (src == null)
 40             throw new ArgumentNullException("src");
 41 
 42         string srcPath = AssetDatabase.GetAssetPath(src);
 43         string rgbPath = GetPath(src, RGBEndName);
 44         int size = Mathf.Max(src.width, src.height, 32);
 45 
 46         AssetDatabase.DeleteAsset(rgbPath);
 47         AssetDatabase.CopyAsset(srcPath, rgbPath);
 48         AssetDatabase.ImportAsset(rgbPath);
 49 
 50         SetSettings(rgbPath, size, TextureImporterFormat.ETC_RGB4, TextureImporterFormat.PVRTC_RGB4);
 51 
 52         return (Texture)AssetDatabase.LoadAssetAtPath(rgbPath, typeof(Texture));
 53     }
 54 
 55     static Texture CreateAlphaTexture(Texture2D src, bool alphaHalfSize)
 56     {
 57         if (src == null)
 58             throw new ArgumentNullException("src");
 59 
 60         // create texture
 61         var srcPixels = src.GetPixels();
 62         var tarPixels = new Color[srcPixels.Length];
 63         for (int i = 0; i < srcPixels.Length; i++)
 64         {
 65             float r = srcPixels[i].a;
 66             tarPixels[i] = new Color(r, r, r);
 67         }
 68 
 69         Texture2D alphaTex = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false);
 70         alphaTex.SetPixels(tarPixels);
 71         alphaTex.Apply();
 72 
 73         // save
 74         string saveAssetPath = GetPath(src, AlphaEndName);
 75         string fullPath = BuildingAssetBundle.GetFullPath(saveAssetPath);
 76         var bytes = alphaTex.EncodeToPNG();
 77         File.WriteAllBytes(fullPath, bytes);
 78 
 79         AssetDatabase.SaveAssets();
 80         AssetDatabase.Refresh();
 81 
 82         // setting
 83         int size = alphaHalfSize ? Mathf.Max(src.width / 2, src.height / 2, 32) : Mathf.Max(src.width, src.height, 32);
 84         SetSettings(saveAssetPath, size, TextureImporterFormat.ETC_RGB4, TextureImporterFormat.PVRTC_RGB4);
 85 
 86         return (Texture)AssetDatabase.LoadAssetAtPath(saveAssetPath, typeof(Texture));
 87     }
 88 
 89     static void SetSettings(string assetPath, int maxSize, TextureImporterFormat androidFormat, TextureImporterFormat iosFormat)
 90     {
 91         var importer = (TextureImporter)AssetImporter.GetAtPath(assetPath);
 92         {
 93             importer.npotScale = TextureImporterNPOTScale.ToNearest;
 94             importer.isReadable = false;
 95             importer.mipmapEnabled = false;
 96             importer.alphaIsTransparency = false;
 97             importer.wrapMode = TextureWrapMode.Clamp;
 98             importer.filterMode = FilterMode.Bilinear;
 99             importer.anisoLevel = 4;
100             importer.SetPlatformTextureSettings("Android", maxSize, androidFormat, 100, true);
101             importer.SetPlatformTextureSettings("iPhone", maxSize, iosFormat, 100, true);
102             importer.SetPlatformTextureSettings("Standalone", maxSize, TextureImporterFormat.ARGB32, 100, true);
103         }
104         AssetDatabase.ImportAsset(assetPath);
105     }
106 
107     static string GetPath(Texture src, string endName)
108     {
109         if (src == null)
110             throw new ArgumentNullException("src");
111 
112         string srcAssetPath = AssetDatabase.GetAssetPath(src);
113         if (string.IsNullOrEmpty(srcAssetPath))
114             return null;
115 
116         string dirPath = Path.GetDirectoryName(srcAssetPath);
117         string ext = Path.GetExtension(srcAssetPath);
118         string fileName = Path.GetFileNameWithoutExtension(srcAssetPath);
119 
120         if (fileName.EndsWith(RGBEndName))
121             fileName = fileName.Substring(0, fileName.Length - RGBEndName.Length);
122 
123         if (fileName.EndsWith(AlphaEndName))
124             fileName = fileName.Substring(0, fileName.Length - AlphaEndName.Length);
125 
126         return string.Format("{0}/{1}{2}{3}", dirPath, fileName, endName ?? "", ext);
127     }
128 
129     public static Texture GetRGBA(Texture src)
130     {
131         if (src != null && (s_rgba == null || s_rgba.name != src.name))
132         {
133             string path = GetPath(src, "");
134             if (!string.IsNullOrEmpty(path))
135                 s_rgba = AssetDatabase.LoadAssetAtPath(path, typeof(Texture)) as Texture;
136         }
137 
138         return s_rgba;
139     }
140 }
SplitAlpha

 

然后改造一下 shader,以ngui的shader为例。

原来要用一张 rgba 图的地方,现在改成用两张图,一张 rgb 和一张 alpha,改造为下:

Shader "Custom/Alpha Splited Colored"
{
    Properties
    {
        _MainTex ("RGB", 2D) = "black" {}
        _AlphaTex ("Alpha", 2D) = "black" {}
    }
    
    SubShader
    {
        LOD 200

        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }
        
        Pass
        {
            Cull Off
            Lighting Off
            ZWrite Off
            Fog { Mode Off }
            Offset -1, -1
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag            

            sampler2D _MainTex;
            sampler2D _AlphaTex;
    
            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                fixed4 color : COLOR;
            };
    
            struct v2f
            {
                float4 vertex : SV_POSITION;
                half2 texcoord : TEXCOORD0;
                fixed4 color : COLOR;
            };
    
            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 IN) : COLOR
            {
                // [dev]
                fixed4 col;
                col.rgb = tex2D(_MainTex, IN.texcoord).rgb;
                col.a = tex2D(_AlphaTex, IN.texcoord).r;

                if (IN.color.r < 0.001 && IN.color.g < 0.001 && IN.color.b < 0.001)  
                {  
                    float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));  
                    col.rgb = float3(grey, grey, grey);  
                }  
                else  
                    col = col * IN.color;
                
                return col;  
            }
            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
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMaterial AmbientAndDiffuse
            
            SetTexture [_MainTex]
            {
                Combine Texture * Primary
            }

            SetTexture [_AlphaTex] 
            {
                Combine previous, texture * primary 
            }
        }
    }
}
shader 

 

转载请注明出处:http://www.cnblogs.com/jietian331/p/5167422.html

posted @ 2016-01-28 20:34  孤独の巡礼  阅读(5172)  评论(0编辑  收藏  举报