zoukankan      html  css  js  c++  java
  • Unity3D 优化NGUI纹理

    原理就是将一张rgba 32的分成两张纹理:一张平台压缩不带alpha和一张为原图1/4大小的压缩图存储alpha信息(用r分量当alpha值),然后修改原材质的Shader传入这两张纹理。

    代码如下(这个是比较针对我们项目的,你可以自己手动改下)

    注意:NGUI的UIPannel裁剪是需要自己手动写不同裁剪层级的Shader,这个不要忘记写

    using System;
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEditor;
    using System.IO;
    
    public class OptimizeAtlasMaterialTextureTool
    {
        public static float sizeScale = 0.5f;
        public static string TransparentColoredShaderName = "Unlit/Transparent Colored(RGBA)";
        public static string TransparentGreyedShaderName = "Unlit/Transparent Grey(RGBA)";
        public static readonly List<string>[] NeedProcessMaterialPath =
            {
                //new List<string>{"Assets/ArtAsset/UI/Login/Loading.mat"},
                 
                   //new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools.mat","Assets/ArtAsset/UI/zhangjing/NewToolsGrey.mat"},
                   new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools2.mat","Assets/ArtAsset/UI/zhangjing/NewTools2Grey.mat"},
                   new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools3.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools4.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools5.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools6.mat","Assets/ArtAsset/UI/zhangjing/NewTools6Grey.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools7.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools8.mat"},
    
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools9.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools10.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools12.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/NewTools13.mat"},
    
                new List<string>{"Assets/ArtAsset/UI/zhangjing/Fuben.mat","Assets/ArtAsset/UI/zhangjing/FubenGrey.mat"},
                new List<string>{"Assets/ArtAsset/UI/cml_maya/MieShi.mat"},
                new List<string>{"Assets/ArtAsset/UI/zhangjing/Huodong.mat","Assets/ArtAsset/UI/zhangjing/HuodongGrey.mat"},
                
                //new List<string>{"Assets/ArtAsset/UI/SkillIcon/SkillIcon.mat","Assets/ArtAsset/UI/SkillIcon/SkillIconGrey.mat"},
    
            };
    
        public static void OptimizeAtlasMaterial(List<string>[] msPath)
        {
            try
            {
                int i = 0;
                foreach (var s in msPath)
                {
                    var ms = new Material[s.Count];
                    for (int j=0; j<s.Count; j++)
                    {
                        ms[j] = AssetDatabase.LoadAssetAtPath(s[j], typeof(Material)) as Material;
                    }
        
                    ProcessUIMaterial(ms);
                    
                    EditorUtility.DisplayProgressBar("OptimizeAtlasMaterialTextureTool", msPath[i][0], i * 1.0f / msPath.Length);
                    i++;
                }
    
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                        
            }
        }
    
        [MenuItem("Assets/Seperate Material's Texture RGB and Alpha")]
        static void OptimizeAtlasMaterialTexture()
        {
    
            var os = Selection.objects;
            foreach (var o in os)
            {
                var m = o as Material;
                if (null != m)
                {
                    ProcessUIMaterial(new []{m});
                }
            }
        }
    
        [MenuItem("Tools/Atlas Tool/Seperate Material's Texture RGB and Alpha")]
        public static void ToolOptimizeAtlasMaterialTexture()
        {
            OptimizeAtlasMaterial(NeedProcessMaterialPath);
        }
    
        public static void ProcessUIMaterial(Material[] ms)
        {
            if (null == ms || ms.Length<=0)
            {
                return;
            }
    
            var s = Shader.Find(TransparentColoredShaderName);
            var sg = Shader.Find(TransparentGreyedShaderName);
    
            var m = ms[0];
            if (null == m || null == m.mainTexture)
            {
                return;
            }
    
            var str = AssetDatabase.GetAssetPath(m.mainTexture.GetInstanceID());
            string rgbPath = "";
            string aPath = "";
            if (!SeperateRGBAandlphaChannel(str, out rgbPath, out aPath))
            {
                return;
            }
    
    
            Texture2D t = AssetDatabase.LoadAssetAtPath(rgbPath, typeof(Texture2D)) as Texture2D;
            Texture2D t2 = AssetDatabase.LoadAssetAtPath(aPath, typeof(Texture2D)) as Texture2D;
    
            foreach (var material in ms)
            {
                if (null == material)
                {
                    continue;
                }
                if (material.name.ToLower().Contains("grey"))
                {
                    material.shader = sg;
                }
                else
                {
                    material.shader = s;
                }
                material.SetTexture("_MainTex", t);
                material.SetTexture("_AlphaTex", t2);
            }
    
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
    
            Debug.Log("process " + str);
        }
    
        #region process texture
    
        static bool SeperateRGBAandlphaChannel(string _texPath,out string rgbPath,out string aPath)
        {
            rgbPath = "";
            aPath = "";
            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("Load Texture Failed : " + assetRelativePath);
                return false;
            }
    //         if (!HasAlphaChannel(sourcetex))
    //         {
    //             Debug.Log("Texture does not have Alpha channel : " + assetRelativePath);
    //             return false;
    //         }
    
            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);
                 }
    
    //         { 
    //             var sourcetexPixels = sourcetex.GetPixels();
    //             var rgbColors = new Color[sourcetexPixels.Length];
    //             var alphaColors = new Color[sourcetexPixels.Length];
    //             for (int i = 0; i < sourcetexPixels.Length; i++)
    //             {
    //                 var color = sourcetexPixels[i];
    //                 rgbColors[i] = color;
    //                 //alphaColors[(int)(i * sizeScale)].r = color.a;
    //                 alphaColors[(int)(i * sizeScale)].r = color.a;
    //                 alphaColors[(int)(i * sizeScale)].g = color.a;
    //                 alphaColors[(int)(i * sizeScale)].b = color.a;
    //                 alphaColors[(int)(i * sizeScale)].a = color.a;
    //             }
    //             rgbTex.SetPixels(rgbColors);
    //             alphaTex.SetPixels(alphaColors);
    //         }
    
            rgbTex.Apply();
            alphaTex.Apply();
    
            rgbPath = GetRGBTexPath(_texPath);
            aPath = GetAlphaTexPath(_texPath);
    
            byte[] bytes = rgbTex.EncodeToPNG();
            File.WriteAllBytes(rgbPath, bytes);
            bytes = alphaTex.EncodeToPNG();
            File.WriteAllBytes(aPath, bytes);
            Debug.Log("Succeed to seperate RGB and Alpha channel for texture : " + assetRelativePath);
            AssetDatabase.Refresh();
    
            TexturePostProcess(rgbPath, Math.Max(sourcetex.width, sourcetex.height));
            TexturePostProcess(aPath, (int)(Math.Max(sourcetex.width, sourcetex.height)*sizeScale));
    
            AssetDatabase.Refresh();
    
            return true;
        }
    
        static bool HasAlphaChannel(Texture2D _tex)
        {
            var texPixels = _tex.GetPixels32(0);
            var count = texPixels.Length;
    
            for (int i = 0; i < count; i++)
            {
                if (texPixels[i].a < 1.0f -0.001f)
                {
                    return true;
                }
            }
    
            return false;
    
    //         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);
    
            bool change = false;
    
            if (ti.isReadable != true)
            {
                ti.isReadable = true;
                change = true;
            }
            
            var platform = "";
    #if UNITY_STANDALONE
            platform = "Standalone";
    #elif UNITY_ANDROID
            platform = "Android";
    #elif UNITY_IPHONE|| UNITY_IOS
            platform = "iPhone";
    #endif
            var size = 0;
            TextureImporterFormat tf;
            ti.GetPlatformTextureSettings(platform, out size, out tf);
            if (TextureImporterFormat.AutomaticTruecolor!=tf  && 
                tf != TextureImporterFormat.RGBA32 &&
                tf != TextureImporterFormat.ARGB32)
            {
                ti.SetPlatformTextureSettings(platform, size, TextureImporterFormat.RGBA32);
                change = true;
            }
    
            if (change)
            {
                AssetDatabase.ImportAsset(_relativeAssetPath);    
            }
            
        }
    
        static void TexturePostProcess(string _relativeAssetPath,int maxsize = 2048)
        {
            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.textureType = TextureImporterType.Advanced;
            ti.isReadable = false;
            ti.mipmapEnabled = false;
    
    
            ti.SetPlatformTextureSettings("Standalone", maxsize, TextureImporterFormat.RGB24);
            ti.SetPlatformTextureSettings("Android", maxsize, TextureImporterFormat.ETC_RGB4);
            ti.SetPlatformTextureSettings("iPhone", maxsize, TextureImporterFormat.PVRTC_RGB4);
    
            AssetDatabase.ImportAsset(_relativeAssetPath, ImportAssetOptions.ForceUpdate);
        }
        #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
    }

    拿一个普通的Sprite用的Shader举例

    Shader "Hidden/Unlit/Transparent Colored(RGBA) 1"
    {
        Properties
        {
            _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
            _AlphaTex ("Alpha (A)", 2D) = "black" {}
        }
    
        SubShader
        {
            LOD 200
    
            Tags
            {
                "Queue" = "Transparent"
                "IgnoreProjector" = "True"
                "RenderType" = "Transparent"
            }
            
            Pass
            {
                Cull Off
                Lighting Off
                ZWrite Off
                Offset -1, -1
                Fog { Mode Off }
                ColorMask RGB
                Blend SrcAlpha OneMinusSrcAlpha
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                sampler2D _MainTex;
                sampler2D _AlphaTex;
                float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);
                float2 _ClipArgs0 = float2(1000.0, 1000.0);
    
                struct appdata_t
                {
                    float4 vertex : POSITION;
                    half4 color : COLOR;
                    float2 texcoord : TEXCOORD0;
                };
    
                struct v2f
                {
                    float4 vertex : POSITION;
                    half4 color : COLOR;
                    float2 texcoord : TEXCOORD0;
                    float2 worldPos : TEXCOORD1;
                };
    
                v2f o;
    
                v2f vert (appdata_t v)
                {
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.color = v.color;
                    o.texcoord = v.texcoord;
                    o.worldPos = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;
                    return o;
                }
    
                half4 frag (v2f IN) : COLOR
                {
                    // Softness factor
                    float2 factor = (float2(1.0, 1.0) - abs(IN.worldPos)) * _ClipArgs0;
                
                    // Sample the texture
                    half4 col = half4(tex2D(_MainTex, IN.texcoord).rgb,tex2D(_AlphaTex, IN.texcoord).r) * IN.color;
                    
                    col.a *= clamp( min(factor.x, factor.y), 0.0, 1.0);
                    return col;
                }
                ENDCG
            }
        }
        
        SubShader
        {
            LOD 100
    
            Tags
            {
                "Queue" = "Transparent"
                "IgnoreProjector" = "True"
                "RenderType" = "Transparent"
            }
            
            Pass
            {
                Cull Off
                Lighting Off
                ZWrite Off
                Fog { Mode Off }
                ColorMask RGB
                Blend SrcAlpha OneMinusSrcAlpha
                ColorMaterial AmbientAndDiffuse
                
                SetTexture [_MainTex]
                {
                    Combine Texture * Primary
                }
            }
        }
    }
  • 相关阅读:
    得不到的都能释怀
    个人读后感
    面向对象程序设计
    关于QQ的NABCD模型
    团队成员及分工
    软件工程结对项目--实用计算器的设计和制作
    实践作业2 个人项目作业
    github地址
    github心得体会
    人,绩效和职业道德
  • 原文地址:https://www.cnblogs.com/mrblue/p/7827146.html
Copyright © 2011-2022 走看看