原理就是将一张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 = ;
foreach (var s in msPath)
{
var ms = new Material[s.Count];
for (int j=; j<s.Count; j++)
{
ms[j] = AssetDatabase.LoadAssetAtPath(s[j], typeof(Material)) as Material;
} ProcessUIMaterial(ms); EditorUtility.DisplayProgressBar("OptimizeAtlasMaterialTextureTool", msPath[i][], 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<=)
{
return;
} var s = Shader.Find(TransparentColoredShaderName);
var sg = Shader.Find(TransparentGreyedShaderName); var m = ms[];
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 = ; i < sourcetex.width; ++i)
for (int j = ; 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();
var count = texPixels.Length; for (int i = ; 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 = ;
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 = )
{
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 > && 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 Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
} Pass
{
Cull Off
Lighting Off
ZWrite Off
Offset -, -
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 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
}
}
}
}

Unity3D 优化NGUI纹理的更多相关文章

  1. Cocos2d-x优化中纹理优化

    转自 http://blog.csdn.net/tonny_guan/article/details/41016241 Cocos2d-x优化中纹理优化 1.纹理像素格式纹理优化工作的另一重要的指标是 ...

  2. Unity3D ShaderLab 模拟纹理运动

    Unity3D ShaderLab 模拟纹理运动 这一篇,我们要说到着色器上的uv贴图的滚动效果,这样的场景可以用在河流,瀑布,熔岩等效果.算是创建纹理动画的基础技术之一. 所以 准备一个新的着色器文 ...

  3. unity3d优化总结篇

    转自http://www.unitymanual.com/thread-21597-1-1.html 此总结由自己经验及网上收集整理优化内容 包括:1.代码方面:2.函数使用方面:3.ngui注意方面 ...

  4. Unity3d优化总结1

    优化内容 包括: 1.代码方面: 2.函数使用方面: 3.ngui注意方面: 4.数学运算方面: 5.内存方面: 6.垃圾回收方面 等等... 1. 尽量避免每帧处理,可以每隔几帧处理一次 比如:   ...

  5. Unity3d优化

    检测方式: 一,Unity3D 渲染统计窗口 Game视窗的Stats去查看渲染统计的信息: 1.FPS fps其实就是 frames per second,也就是每一秒游戏执行的帧数,这个数值越小, ...

  6. unity3d优化总结篇(二)

    1. 尽量避免每帧处理,可以每隔几帧处理一次 比如: [C#] 纯文本查看 复制代码     function Update() { DoSomeThing(); } 可改为每5帧处理一次: [C#] ...

  7. Unity3d优化总结2

    优化: 1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种, 每家的GPU支持不同的压缩格式,但他们都兼容ETC格式, 2. 对于透明贴图,我们只能选择RG ...

  8. 【转载】总结使用Unity3D优化游戏运行性能的经验

    流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏<Shadow Blade>已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标. 以下是我们在紧凑的优化过程中 ...

  9. Unity3D 优化

    用UNITY开发手机游戏,背景图片和UI图片显示的比PC机上模糊非常多,怎么解决??在unity里选中资源 1.TextureType 改成 Advanced2.NonPower of 2 改成 no ...

随机推荐

  1. app v2界面

             相比v1要流畅了很多

  2. 奇怪吸引子---GenesioTesi

    奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...

  3. wcstombs_s 宽字节转多字节

    // crt_wcstombs_s.c // This example converts a wide character // string to a multibyte character str ...

  4. [Nginx] Configuration for SPA

    server { listen ; listen [::]:; default_type application/octet-stream; gzip on; gzip_comp_level ; gz ...

  5. js 创建Date对象5种方式

    new Date("month dd,yyyy hh:mm:ss"); new Date("month dd,yyyy"); new Date(yyyy,mth ...

  6. 【Little Demo】左右按钮tab选项卡双切换

    通过前一篇文章 从简单的Tab标签到Tab图片切换 的说明,相关效果也就可以实现了. 1.左右按钮tab选项卡双切换 很明显,左右两个按钮是 absolute 布局,另外就是内容部分和Tab标签部分. ...

  7. ELK菜鸟手记 (二) - 高级配置之多应用索引过滤

    我们在实际的场景中,经常是多个网站或者服务端在一台服务器上,但是如果这些应用全部 记录到一台logstash服务器,大家日志都混在一起不好区分. 有人说,我可以在日志中打项目名,但是这样并不方便. 其 ...

  8. 3728 联合权值[NOIP 2014 Day1 T2]

    来源:NOIP2014 Day1 T2 OJ链接: http://codevs.cn/problem/3728/ https://www.luogu.org/problemnew/show/P1351 ...

  9. 如何制作initrd.img文件

    2008-11-12 16:02:37    initrd.img文件是redhat,mandrake等linux发布使用的内存镜像文件.镜像中是一个微型系统.在安装系统时,将initrd.img展开 ...

  10. 内核编译之vmlinuz vmlinux system.map initrd

    一.vmlinuz  vmlinuz是可引导的.压缩的内核.“vm”代表“Virtual Memory”.Linux 支持虚拟内存,不像老的操作系统比如DOS有640KB内存的限制.Linux能够使用 ...