The separation of RGB and Alpha channels of images in the Unity project, and display all material with alpha channel textures

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.