原创文章如需转载请注明:转载自 脱莫柔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()方法修改此处