Background: The error message returned when the etc1 image format is invalid. The alpha channel is not supported. As a result, programmers waste some effort on alpha channel processing. In order to use etc1, and some transparency effects must have alpha channels, the general processing method is to separate RGB and alpha into two images for storage. Only images with Alpha channels and RGB Images are the alpha values to be stored. Because the entropy is small, the image size can be reduced accordingly.
The work to be done:
1. Save the image with alpha channel as two images, one storing only RGB information and the other storing only alpha information. We recommend that you keep the original directory of the image with the suffix "_ RGB" and "_ Alpha ".
2. For images with Alpha channels, the shader must be updated to the shader that supports reading RGB and Alpha information from two different images. This function, because the shader of the material cannot be very different, so you do not need to use a program to specify it. However, the program should at least give a prompt about which material uses images with Alpha channels in the project.
Let's get started with the code.
using UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEditor;using System.IO;using System.Reflection;public class MaterialTextureForETC1{ public static float sizeScale = 0.5f; //the size decrease scale for alphaTexture public static Dictionary<string, bool> texturesAlphaDic = new Dictionary<string, bool>(); [MenuItem("EffortForETC1/Seperate RGB and Alpha Channel for All Textures")] static void SeperateAllTexturesRGBandAlphaChannel() { string[] paths = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories); foreach (string path in paths) { if (!string.IsNullOrEmpty(path) && IsTextureFile(path)) //full name { SeperateRGBAandlphaChannel(path); } } } [MenuItem("EffortForETC1/Show Materials Having Textures with Alpha Chanel")] static void ShowMaterialsHavingTextureswithAlphaChanel() { CalculateTexturesAlphaChannelDic(); string[] matpaths = Directory.GetFiles(Application.dataPath, "*.mat", SearchOption.AllDirectories); foreach (string matpath in matpaths) { string propermatpath = GetRelativeAssetPath(matpath); Material mat = (Material)Resources.LoadAssetAtPath(propermatpath, typeof(Material)); if (mat) { 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 inspect material static string[] GetMaterialTexturesHavingAlphaChannel(Material _mat) { List<string> alphatexpaths = new List<string>(); string[] texpaths = GetMaterialTexturePaths(_mat); foreach (string texpath in texpaths) { if (texturesAlphaDic[texpath]) { alphatexpaths.Add(texpath); } } return alphatexpaths.ToArray(); } static string[] GetMaterialTexturePaths(Material _mat) { List<string> results = new List<string>(); Object[] roots = new Object[] { _mat }; Object[] dependObjs = EditorUtility.CollectDependencies(roots); foreach (Object dependObj in dependObjs) { if (dependObj.GetType() == typeof(Texture2D)) { string texpath = AssetDatabase.GetAssetPath(dependObj.GetInstanceID()); results.Add(texpath); } } return results.ToArray(); } #endregion static void CalculateTexturesAlphaChannelDic() { string[] paths = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories); foreach (string path in paths) { if (!string.IsNullOrEmpty(path) && IsTextureFile(path)) //full name { string assetRelativePath = GetRelativeAssetPath(path); SetTextureReadable(assetRelativePath); Texture2D sourcetex = Resources.LoadAssetAtPath(assetRelativePath, typeof(Texture2D)) as Texture2D; if (!sourcetex) //make sure the file is really Texture2D which can be loaded as Texture2D. { continue; } if (HasAlphaChannel(sourcetex)) { AddValueToDic(assetRelativePath, true); } else { AddValueToDic(assetRelativePath, false); } } } } static void AddValueToDic(string _key, bool _val) { if (texturesAlphaDic.ContainsKey(_key)) { texturesAlphaDic[_key] = _val; } else { texturesAlphaDic.Add(_key, _val); } } #region process texture static void SeperateRGBAandlphaChannel(string _texPath) { string assetRelativePath = GetRelativeAssetPath(_texPath); SetTextureReadable(assetRelativePath); Texture2D sourcetex = Resources.LoadAssetAtPath(assetRelativePath, typeof(Texture2D)) as Texture2D; //not just the textures under Resources file if (!sourcetex) { Debug.Log("Load Texture Failed : " + assetRelativePath); return; } if (!HasAlphaChannel(sourcetex)) { Debug.Log("Texture does not have Alpha channel : " + assetRelativePath); return; } 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); Debug.Log("Succeed to seperate RGB and Alpha channel for texture : " + assetRelativePath); } static bool HasAlphaChannel(Texture2D _tex) { for (int i = 0; i < _tex.width; ++i) for (int j = 0; j < _tex.height; ++j) { Color color = _tex.GetPixel(i, j); float alpha = color.a; if (alpha < 1.0f - 0.001f) { return true; } } return false; } 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); } #endregion #region string or path helper 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"); } static string GetRGBTexPath(string _texPath) { return GetTexPath(_texPath, "_RGB."); } static string GetAlphaTexPath(string _texPath) { return GetTexPath(_texPath, "_Alpha."); } static string GetTexPath(string _texPath, string _texRole) { string result = _texPath.Replace(".", _texRole); string postfix = GetFilePostfix(_texPath); return result.Replace(postfix, ".png"); } 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; } #endregion }
Region format. In fact, you can import system. Drawing. dll of C # Into the project and use the bitmap class of C # To process images.
The processing of. Dds format images is special. When texture2d. getpixel () and other functions are used to process texture2d, you need to set readable in the import attribute of texture, but the. Dds format does not need to be processed. At the same time, Unity only supports DDs in int format, while. DDS in float32 format does not.
The separation of RGB and Alpha channels of images in the Unity project, and display all material with alpha channel textures