原理就是将一张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. I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2

    问题: 安装TensorFlow(CPU版本),使用pip install tensorflow安装,安装一切顺利,但是在跑一个简单的程序时,遇到如下情况: 大概意思是:你的CPU支持AVX扩展,但是 ...

  2. Android Studio下加入百度地图的使用(二)——定位服务

    上一章(http://www.cnblogs.com/jerehedu/p/4891216.html)中我们已经完成了环境的搭建,这一章我们来研究一下如何使用. 第一步:在xml文件中加入以下权限 & ...

  3. 微软BI 之SSIS 系列 - 通过 ROW_NUMBER 或 Script Component 为数据流输出添加行号的方法

    开篇介绍 上午在天善回答看到这个问题 - SSIS 导出数据文件,能否在第一列增加一个行号,很快就帮助解决了,方法就是在 SQL 查询的时候加一个 ROW_NUMBER() 就可以了. 后来想起在两年 ...

  4. Spring导出可以运行的jar包

    最近需要解决Maven项目导入可执行的jar包的问题,如果项目不包含Spring,那么使用mvn assembly:assembly即可,详情可以参考:http://www.cnblogs.com/l ...

  5. iOS关于沙盒文件拷贝manager.copyItem的一个坑

    记录一下: 沙盒文件操作,当需要拷贝文件时,我们可以使用如下类似方式: // 文件拷贝 func copyFile(from:String,to:String)->Bool{ if !manag ...

  6. Hardware Monitor for Mac(硬件运行状态监测工具)破解版安装

    1.软件简介    Hardware Monitor 是 macOS 系统上一款 mac 硬件检测软件,同时还可以示硬盘.显卡温度以及电池电压等等监控信息.Hardware Monitor for M ...

  7. ASP.NET中TimeSpan的用法

    一.TimeSpan常量.字段 TimeSpan.MaxValue; // 10675199.02:48:05.4775807TimeSpan.MinValue; //-10675199.02:48: ...

  8. SNF快速开发平台MVC-名片管理(实际名片样式)

    名片管理实际的做的意义在于演示应用,在这里使用的技术有排序控件,查询条件.自由样式瀑布流式分页等技术. 下面是自由样式效果图: 下面表格样式效果图: 具体操作: 新增名片 在新增时可以上传图像进行裁剪 ...

  9. [Android源码]Android源码之高仿飞鸽传书WIFI热点搜索与创建(一)

    (本文详情来源:android源码 http://www.eoeandroid.com/thread-296427-1-1.html   转载请注明出处!)  [Android源码分享]飞鸽传书的An ...

  10. 2. RabbitMQ 服务器 之下载安装

    RabbitMQ服务器如何安装? RabbitMQ是一个AMQP(Advanced Message Queue,即高级消息队列协议)服务器 . 下载地址: RabbitMQ下载 安装说明:各平台下Ra ...