【改进版】Unity工程里图片的RGB和Alpha通道的分离

http://blog.csdn.net/u010153703/article/details/39477887

“这篇文章里有两个明显的问题:

1. 处理Alpha贴图时是一个像素一个像素地处理,用Texture.SetPixel()函数。推荐批量处理,用Texture.SetPixels()函数。推荐批量处理,用Texture.SetPixels()函数。”

改进之:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.IO;
using System.Reflection;  

public class MaterialTextureForETC1{

    private static string defaultWhiteTexPath_relative = "Assets/Default_Alpha.png";
    private static Texture2D defaultWhiteTex = null;

    [MenuItem("EffortForETC1/Depart RGB and Alpha Channel")]
    static void SeperateAllTexturesRGBandAlphaChannel()
    {
        Debug.Log("Start Departing.");
        if (!GetDefaultWhiteTexture())
        {
            return;
        }
        string[] paths = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories);
        foreach (string path in paths)
        {
            if (!string.IsNullOrEmpty(path) && IsTextureFile(path) && !IsTextureConverted(path))   //full name
            {
                SeperateRGBAandlphaChannel(path);
            }
        }
        AssetDatabase.Refresh();    //Refresh to ensure new generated RBA and Alpha textures shown in Unity as well as the meta file
        Debug.Log("Finish Departing.");
    }

    #region process texture

    static void SeperateRGBAandlphaChannel(string _texPath)
    {
        string assetRelativePath = GetRelativeAssetPath(_texPath);
        SetTextureReadableEx(assetRelativePath);    //set readable flag and set textureFormat TrueColor
        Texture2D sourcetex = Resources.LoadAssetAtPath(assetRelativePath, typeof(Texture2D)) as Texture2D;  //not just the textures under Resources file
        if (!sourcetex)
        {
            Debug.LogError("Load Texture Failed : " + assetRelativePath);
            return;
        }

        TextureImporter ti = null;
        try
        {
            ti = (TextureImporter)TextureImporter.GetAtPath(assetRelativePath);
        }
        catch
        {
            Debug.LogError("Load Texture failed: " + assetRelativePath);
            return;
        }
        if (ti == null)
        {
            return;
        }
        bool bGenerateMipMap = ti.mipmapEnabled;    //same with the texture import setting      

        Texture2D rgbTex = new Texture2D(sourcetex.width, sourcetex.height, TextureFormat.RGB24, bGenerateMipMap);
        rgbTex.SetPixels(sourcetex.GetPixels());

        Texture2D mipMapTex = new Texture2D(sourcetex.width, sourcetex.height, TextureFormat.RGBA32, true);  //Alpha Channel needed here
        mipMapTex.SetPixels(sourcetex.GetPixels());
        mipMapTex.Apply();
        Color[] colors2rdLevel = mipMapTex.GetPixels(1);   //Second level of Mipmap
        Color[] colorsAlpha = new Color[colors2rdLevel.Length];
        if (colors2rdLevel.Length != (mipMapTex.width+1) / 2 * (mipMapTex.height+1) / 2)
        {
            Debug.LogError("Size Error.");
            return;
        }
        bool bAlphaExist = false;
        for (int i = 0; i < colors2rdLevel.Length; ++i)
        {
            colorsAlpha[i].r = colors2rdLevel[i].a;
            colorsAlpha[i].g = colors2rdLevel[i].a;
            colorsAlpha[i].b = colors2rdLevel[i].a;

            if (!Mathf.Approximately(colors2rdLevel[i].a, 1.0f))
            {
                bAlphaExist = true;
            }
        }
        Texture2D alphaTex = null;
        if (bAlphaExist)
        {
            alphaTex = new Texture2D((sourcetex.width+1) / 2, (sourcetex.height+1) / 2, TextureFormat.RGB24, bGenerateMipMap);
        }
        else
        {
            alphaTex = new Texture2D(defaultWhiteTex.width, defaultWhiteTex.height, TextureFormat.RGB24, false);
        }

        alphaTex.SetPixels(colorsAlpha);

        rgbTex.Apply();
        alphaTex.Apply();

        byte[] bytes = rgbTex.EncodeToPNG();
        File.WriteAllBytes(assetRelativePath, bytes);
        byte[] alphabytes = alphaTex.EncodeToPNG();
        string alphaTexRelativePath = GetAlphaTexPath(_texPath);
        File.WriteAllBytes(alphaTexRelativePath, alphabytes);

        ReImportAsset(assetRelativePath, rgbTex.width, rgbTex.height);
        ReImportAsset(alphaTexRelativePath, alphaTex.width, alphaTex.height);
        Debug.Log("Succeed Departing : " + assetRelativePath);
    }

    static void ReImportAsset(string path, int width, int height)
    {
        try
        {
            AssetDatabase.ImportAsset(path);
        }
        catch
        {
            Debug.LogError("Import Texture failed: " + path);
            return;
        }

        TextureImporter importer = null;
        try
        {
            importer = (TextureImporter)TextureImporter.GetAtPath(path);
        }
        catch
        {
            Debug.LogError("Load Texture failed: " + path);
            return;
        }
        if (importer == null)
        {
            return;
        }
        importer.maxTextureSize = Mathf.Max(width, height);
        importer.anisoLevel = 0;
        importer.isReadable = false;  //increase memory cost if readable is true
        importer.textureFormat = TextureImporterFormat.AutomaticCompressed;
        importer.textureType = TextureImporterType.Image;
        if (path.Contains("/UI/"))
        {
            importer.textureType = TextureImporterType.GUI;
        }
        AssetDatabase.ImportAsset(path);
    }

    static void SetTextureReadableEx(string _relativeAssetPath)    //set readable flag and set textureFormat TrueColor
    {
        TextureImporter ti = null;
        try
        {
            ti = (TextureImporter)TextureImporter.GetAtPath(_relativeAssetPath);
        }
        catch
        {
            Debug.LogError("Load Texture failed: " + _relativeAssetPath);
            return;
        }
        if (ti == null)
        {
            return;
        }
        ti.isReadable = true;
        ti.textureFormat = TextureImporterFormat.AutomaticTruecolor;      //this is essential for departing Textures for ETC1. No compression format for following operation.
        AssetDatabase.ImportAsset(_relativeAssetPath);
    }

    static bool GetDefaultWhiteTexture()
    {
        defaultWhiteTex = Resources.LoadAssetAtPath(defaultWhiteTexPath_relative, typeof(Texture2D)) as Texture2D;  //not just the textures under Resources file
        if (!defaultWhiteTex)
        {
            Debug.LogError("Load Texture Failed : " + defaultWhiteTexPath_relative);
            return false;
        }
        return true;
    }

    #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(".bmp") || path.EndsWith(".tif") || path.EndsWith(".gif");
    }

    static bool IsTextureConverted(string _path)
    {
        return _path.Contains("_RGB.") || _path.Contains("_Alpha.");
    }

    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 dir = System.IO.Path.GetDirectoryName(_texPath);
        string filename = System.IO.Path.GetFileNameWithoutExtension(_texPath);
        string result = dir + "/" + filename + _texRole + "png";
        return result;
    }  

    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("\\", "/");
    }  

    #endregion
}  
时间: 2024-10-10 00:13:56

【改进版】Unity工程里图片的RGB和Alpha通道的分离的相关文章

Unity工程里图片的RGB和Alpha通道的分离,以及显示所有带有Alpha通道贴图的Material

背景:ETC1图片格式的罪孽,不支持Alpha通道.于是程序员们将一些气力浪费在Alpha通道的处理上. 为了能使用ETC1,同时某些透明效果必须有Alpha通道,一般的处理方式是将RGB和Alpha分为两张图片分别储存. 只存Alpha通道的图片及RGB都为要存的Alpha值,因为熵比较小,图片尺寸也可以相应减小一些. 要做的工作: 1. 将带有Alpha通道的图片,另存为两张图片,一张只存RGB信息,另一张只存Alpha信息.建议保持为图片原目录,名称加后缀"_RGB", &quo

移除Unity工程里所有图片的Alpha通道

为测试Untiy工程里Texture的Alpha对性能的压力,需要临时移除Unity工程里所有图片的Alpha通道,做测试对比. 这里有一个基本的技巧,当图片不存在Alpha通道时,就不需要处理,如何判断图片是否存在Alpha通道呢,Unity不存在直接的接口.但可以这么干: 1. ti.textureFormat = TextureImporterFormat.AutomaticTruecolor; AssetDatabase.ImportAsset(_relativeAssetPath);

干货:Unity游戏开发图片纹理压缩方案

原文:http://www.jianshu.com/p/f7c3741f22af Unity3D引擎对纹理的处理是智能的:不论你放入的是PNG,PSD还是TGA,它们都会被自动转换成Unity自己的Texture2D格式. 在Texture2D的设置选项中,你可以针对不同的平台,设置不同的压缩格式,如IOS设置成PVRTC4,Android平台设置成RGBA16等. 嗯,非常的智能. 但是,在一些进阶的使用中,一些情况是难以满足的. 比如,我们NGUI的图集纹理,在Android平台,使用ETC

清理iOS工程里无用的图片,可瘦身ipa

工程在经过多人后,往往会出现较多的垃圾,导致打包出来的ipa文件偏大,有时候我们会通过清理代码来给程序瘦身,而瘦身ipa效果明显的,主要通过清理程序里的无用图片. 推荐一个清理图片的应用 https://github.com/tinymind/LSUnusedResources 直接打开运行,点击Browse..选择工程目录,再点击Search 搜索出该搜索工具认为工程里没有用到的图片,当然那些没搜出来的就都是有使用的图片了,不用理会 注意:这里所说没有用到的图片不是真的没有用到,因为这个工具他

Unity工程资源破解

    Unity工程资源提取其实还是很方便的,网上也有很多相关介绍,比如雨凇就专门写了一遍关于破解Unity资源的文章(http://www.xuanyusong.com/archives/3618),当然即使有傻瓜式教程,也难免会踩一些坑,下面记录一下这两天破解Unity资源的工程.     一.disunity     disunity是一款开源项目,java语言写的,轻量级,传言简单易用,然而并不好用,     1.disunity5.x版本命令如何尝试都不成功,总是报出如下问题:   

unity 3D里有两种动态加载机制

unity 3D里有两种动态加载机制: 一是Resources.Load: 一是通过AssetBundle: 其实两者本质上没有什么区别.Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的.其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了. 1.    AssetBundles是什么? 在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等

VS工程里的文件都是啥?如何打包? 2015-03-04

打完补充:以下内容全部是我一家之言,只是愿意分享,内容如有不妥还请见谅. ====================================================== 刚才接收了一份代码,庞大的sdf文件也传过来了.如果咱们想分享一份代码的话,其实只需要很少的文件即可.我把我对VS工程里各种文件的认识分享出来,如有错误还请指正,我也是一知半解,欢迎探讨. 我以自己的C语课设为例,大家打开文件夹后,有这些: 第一个文件夹里就是源代码.理论上,“ball_moving”是“项目”的名

使用SVN管理unity工程

 我们的项目使用SVN管理,这几天遇到了几个问题,解决了一下,顺便做了一个总结. 1.关于使用SVN管理unity项目的一些设置和说明 首先在unity中进行两部操作:Edit->ProjectSettings->Editor菜单,选择Verion Control Mode 为VisivaleMeta File,选择Asset SeriaLization Mode 为ForceText.第一步选择外部版本控制可见Meta文件,这样子会为Asset文件夹下面每个资源创建一个.Meta文本文件

Unity工程中 .Meta 文件

在项目提交的时候,尤其是导入了很多资源的情况下会有很多的.meta文件,那么这些文件是否一定要上传? --------------------- 在游戏开发过程中不可避免的要用到版本控制工具,如SVN,git,也因此需要理解Meta文件的作用. 在游戏场景中引用一个游戏资源,Unity并不直接按照文件路径和名称,而是使用一个独一无二的GUID来指向工程里的该资源文件. GUID储存在Unity工程为每个资源和文件夹生成的Meta文件里. 使用GUID的好处就是,即使你移动.重命名或者修改资源的内