Unity3D教程:如何使用NGUI分离RGBA通道

发表于2017-02-13
评论0 2.3k浏览
  如何使用NGUI分离RGBA通道?这就需要借助一些工具脚本来实现,可能有些开发者没有这方面的经验,为了帮助大家,下面就给大家介绍下使用NGUI分离RGBA通道的方法,一起来看看吧。
  
  一、拆分图片通道
  
  下面是代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
public class DuanTools_ETC1SeperateRGBA 
    static string getPath_NGUIAtlas() 
    
        return Application.dataPath + "/Atlas-3"
    
   
    [MenuItem("DuanTools/ETC1分离RGBA/分离NGUI图片通道")] 
    static void SeperateNGUI_TexturesRGBandAlphaChannel() 
    
        Debug.Log("分离Alpha通道 Start.");   
        string[] paths = Directory.GetFiles(getPath_NGUIAtlas(), "*.*", SearchOption.AllDirectories); 
        foreach (string path in paths) 
        
            if (!string.IsNullOrEmpty(path) && !IsIgnorePath(path) && IsTextureFile(path) && !IsTextureConverted(path))   //full name 
            
                //Debug.Log("path:" + path); 
                SeperateRGBAandlphaChannel(path); 
            
        
        AssetDatabase.Refresh(); 
        ReImportAsset(); 
        Debug.Log("分离Alpha通道 Finish.");   
    
   
    [MenuItem("DuanTools/ETC1分离RGBA/改变NGUI材质")] 
    static void ChangeNGUI_MaterialtoETC1() 
    
        //CalculateTexturesAlphaChannelDic(); 
        string[] matpaths = Directory.GetFiles(getPath_NGUIAtlas(), "*.mat", SearchOption.AllDirectories); 
        foreach (string matpath in matpaths) 
        
            string propermatpath = GetRelativeAssetPath(matpath); 
            Material mat = (Material)AssetDatabase.LoadAssetAtPath(propermatpath, typeof(Material)); 
            if (mat != null
            
                ChangMaterial(mat, getPath_NGUIAtlas()); 
                   
                /*string[] alphatexpaths = GetMaterialTexturesHavingAlphaChannel(mat);
                if (alphatexpaths.Length == 0)
                {
                    continue;
                }
                Debug.Log("Material having texture(s) with Alpha channel : " + propermatpath);
                foreach (string alphatexpath in alphatexpaths)
                {
                    Debug.Log(alphatexpath + " in " + propermatpath);
                }*/ 
            
            else 
            
                Debug.LogError("Load material failed : " + matpath); 
            
        
        Debug.Log("材质改变完成 Finish!");   
    
      
  
    #region 分离 RGB & A 
    ///  
    /// 分离图片通道 
    ///  
    ///  
    static void SeperateRGBAandlphaChannel(string _texPath) 
    
        //获得相对路径 
        string assetRelativePath = GetRelativeAssetPath(_texPath); 
        SetTextureReadable(assetRelativePath); 
        Texture2D sourcetex = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(Texture2D)) as Texture2D;  //not just the textures under Resources file 
        if (!sourcetex) 
        
            Debug.Log("读取图片失败 : " + assetRelativePath); 
            return
        
   
        /*进化版本*/ 
        Color[] colors = sourcetex.GetPixels(); 
        Texture2D rgbTex2 = new Texture2D(sourcetex.width, sourcetex.height, TextureFormat.RGB24, false); 
        rgbTex2.SetPixels(colors); 
        rgbTex2.Apply(); 
        string strPath_RGB = GetRGBTexPath(_texPath); 
        File.WriteAllBytes(strPath_RGB, rgbTex2.EncodeToPNG()); 
        ReImport_Addlist(strPath_RGB, rgbTex2.width, rgbTex2.height); 
   
        Texture2D alphaTex2 = new Texture2D(sourcetex.width , sourcetex.height, TextureFormat.RGB24, false); 
        Color[] alphacolors = new Color[colors.Length]; 
        for (int i = 0; i < colors.Length; ++i) 
        
            alphacolors[i].r = colors[i].a; 
            alphacolors[i].g = colors[i].a; 
            alphacolors[i].b = colors[i].a; 
        
        alphaTex2.SetPixels(alphacolors); 
        alphaTex2.Apply(); 
        string strPath_Alpha = GetAlphaTexPath(_texPath); 
        File.WriteAllBytes(strPath_Alpha, alphaTex2.EncodeToPNG()); 
        ReImport_Addlist(strPath_Alpha, alphaTex2.width, alphaTex2.height);  
    
   
    ///  
    /// 设置图片为可读格式 
    ///  
    ///  
    static void SetTextureReadable(string _relativeAssetPath) 
    
        string postfix = GetFilePostfix(_relativeAssetPath); 
        if (postfix == ".dds")    // no need to set .dds file.  Using TextureImporter to .dds file would get casting type error. 
        
            return
        
   
        TextureImporter ti = (TextureImporter)TextureImporter.GetAtPath(_relativeAssetPath); 
        ti.isReadable = true
        AssetDatabase.ImportAsset(_relativeAssetPath); 
    
   
    static Dictionary<string, int[]=""> ReImportList = new Dictionary<string, int[]="">(); 
    static void ReImport_Addlist(string path, int width, int height) 
    
        ReImportList.Add(path, new int[] { width, height }); 
    
   
    ///  
    /// 设置图片格式 
    ///  
    static void ReImportAsset() 
    
        foreach (var item in ReImportList) 
        
            TextureImporter importer = null
            string assetpath = GetRelativeAssetPath(item.Key); 
            try 
            
                importer = (TextureImporter)TextureImporter.GetAtPath(assetpath); 
            
            catch 
            
                Debug.LogError("Load Texture failed: " + assetpath); 
                return
            
   
            if (importer == null
            
                Debug.Log("importer null:" + assetpath); 
                return
            
            importer.textureType = TextureImporterType.Advanced; 
            importer.isReadable = false//increase memory cost if readable is true   
   
            importer.mipmapEnabled = false
   
            importer.wrapMode = TextureWrapMode.Clamp; 
            importer.anisoLevel = 1; 
   
            importer.maxTextureSize = Mathf.Max(item.Value[0], item.Value[1]); 
            importer.textureFormat = TextureImporterFormat.ETC_RGB4; 
            importer.compressionQuality = 50; 
   
            //if (path.Contains("/UI/")) 
            //{ 
            //    importer.textureType = TextureImporterType.GUI; 
            //} 
            AssetDatabase.ImportAsset(item.Key); 
        
    
    #endregion 
  
    #region 材质 
    static void ChangMaterial(Material _mat,string _texPath) 
    
        Shader shader; 
        switch (_mat.shader.name) 
        
            case "Unlit/Transparent Colored"
                
                    shader = Shader.Find("Unlit/Transparent Colored ETC1"); 
                
                break
            default:  
                return
        
   
        string[] mainPath = Directory.GetFiles(_texPath, _mat.mainTexture.name + "_ETC_RGB.png", SearchOption.AllDirectories); 
        Texture mainTex = AssetDatabase.LoadAssetAtPath(GetRelativeAssetPath(mainPath[0]), typeof(Texture)) as Texture; 
        string[] alphaPath = Directory.GetFiles(_texPath, _mat.mainTexture.name + "_ETC_Alpha.png", SearchOption.AllDirectories); 
        Texture alphaTex = AssetDatabase.LoadAssetAtPath(GetRelativeAssetPath(alphaPath[0]), typeof(Texture)) as Texture; 
   
        _mat.shader = shader; 
        _mat.SetTexture("_MainTex", mainTex); 
        _mat.SetTexture("_MainTex_A", alphaTex); 
    
    #endregion  
  
    #region Path or 后缀 
    ///  
    /// 获得相对路径 
    ///  
    ///  
    ///  
    static string GetRelativeAssetPath(string _fullPath) 
    
        _fullPath = GetRightFormatPath(_fullPath); 
        int idx = _fullPath.IndexOf("Assets"); 
        string assetRelativePath = _fullPath.Substring(idx); 
        return assetRelativePath; 
    
   
    ///  
    /// 转换斜杠 
    ///  
    ///  
    ///  
    static string GetRightFormatPath(string _path) 
    
        return _path.Replace("\", "/"); 
    
   
    ///  
    /// 获取文件后缀 
    ///  
    ///  
    ///  
    static string GetFilePostfix(string _filepath)   //including '.' eg ".tga", ".dds" 
    
        string postfix = ""
        int idx = _filepath.LastIndexOf('.'); 
        if (idx > 0 && idx < _filepath.Length) 
            postfix = _filepath.Substring(idx, _filepath.Length - idx); 
        return postfix; 
    
   
    static bool IsIgnorePath(string _path) 
    
        return _path.Contains("\UI\"); 
    
   
    ///  
    /// 是否为图片 
    ///  
    ///  
    ///  
    static bool IsTextureFile(string _path) 
    
        string path = _path.ToLower(); 
        return path.EndsWith(".psd") || path.EndsWith(".tga") || path.EndsWith(".png") || path.EndsWith(".jpg") || path.EndsWith(".dds") || path.EndsWith(".bmp") || path.EndsWith(".tif") || path.EndsWith(".gif"); 
    
   
    ///  
    /// 是否为自动生成的ETC图片 
    ///  
    ///  
    ///  
    static bool IsTextureConverted(string _path) 
    
        return _path.Contains("_ETC_RGB.") || _path.Contains("_ETC_Alpha."); 
    }   
   
    static string GetRGBTexPath(string _texPath) 
    
        return GetTexPath(_texPath, "_ETC_RGB."); 
    
   
    static string GetAlphaTexPath(string _texPath) 
    
        return GetTexPath(_texPath, "_ETC_Alpha."); 
    
   
    static string GetTexPath(string _texPath, string _texRole) 
    
        string result = _texPath.Replace(".", _texRole); 
        string postfix = GetFilePostfix(_texPath); 
        return result.Replace(postfix, ".png"); 
    
    #endregion  
string,>string,>
  
  二、专用的shader
  
  其间夹杂了R通道为0时,自动置灰的shader功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
Shader "Unlit/Transparent Colored ETC1" 
    Properties 
    
        _MainTex ("Base (RGB)", 2D) = "black" {} 
        _MainTex_A ("Alpha (A)", 2D) = "white" {} 
    
       
    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            
            #include "UnityCG.cginc" 
   
            sampler2D _MainTex; 
            sampler2D _MainTex_A; 
            float4 _MainTex_ST; 
       
            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 o; 
   
            v2f vert (appdata_t v) 
            
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 
                o.texcoord = v.texcoord; 
                o.color = v.color; 
                return o; 
            
                   
            fixed4 frag (v2f IN) : COLOR 
            
                fixed4 col; 
   
                col.rgb = tex2D(_MainTex, IN.texcoord).rgb; 
                col.a = tex2D(_MainTex_A, IN.texcoord).b; 
   
                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 
            
        
    
}
  
  另外分别复制Unlit - Transparent Colored 1、2、3,分别创建 Unlit - Transparent Colored  ETC1 1、2、3。并逐一添加A贴图,并读取A贴图的r通道。
  
  UIPanel的拓展
  
  将图集的shader改为ETC1shader后,运行发现,UIPanel选择clipping模式后shader还原了。
  
  解决方案:
  
  UIDrawCall脚本里,找到CreateMaterial()方法修改此处

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