Unity3D NGUI分离RGBA通道

原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 Unity3D引擎技术交流QQ群:【119706192本文链接地址: Unity3D NGUI分离RGBA通道


工具脚本

用于拆分图片通道和修改图集shader
借鉴网上多处代码,具体出处已经忘了,反正我也是抄的。
直接上代码:
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
    /// <summary>
    /// 分离图片通道
    /// </summary>
    /// <param name="_texPath"></param>
    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); 
    }

    /// <summary>
    /// 设置图片为可读格式
    /// </summary>
    /// <param name="_relativeAssetPath"></param>
    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 });
    }

    /// <summary>
    /// 设置图片格式
    /// </summary>
    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 后缀
    /// <summary>
    /// 获得相对路径
    /// </summary>
    /// <param name="_fullPath"></param>
    /// <returns></returns>
    static string GetRelativeAssetPath(string _fullPath)
    {
        _fullPath = GetRightFormatPath(_fullPath);
        int idx = _fullPath.IndexOf("Assets");
        string assetRelativePath = _fullPath.Substring(idx);
        return assetRelativePath;
    }

    /// <summary>
    /// 转换斜杠
    /// </summary>
    /// <param name="_path"></param>
    /// <returns></returns>
    static string GetRightFormatPath(string _path)
    {
        return _path.Replace("\\", "/");
    }

    /// <summary>
    /// 获取文件后缀
    /// </summary>
    /// <param name="_filepath"></param>
    /// <returns></returns>
    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\\");
    }

    /// <summary>
    /// 是否为图片
    /// </summary>
    /// <param name="_path"></param>
    /// <returns></returns>
    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");
    }

    /// <summary>
    /// 是否为自动生成的ETC图片
    /// </summary>
    /// <param name="_path"></param>
    /// <returns></returns>
    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 
}

专用的shader

其间夹杂了R通道为0时,自动置灰的shader功能。
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()方法修改此处

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值