using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.IO;
using System.Reflection;
public class MaterialTextureForETC1{
public static float sizeScale =1f; //the size decrease scale for alphaTexture
public static Dictionary<string, bool> texturesAlphaDic = new Dictionary<string, bool>();
[MenuItem("EffortForETC1/Seperate RGB and Alpha Channel for All Textures")]
static void SeperateAllTexturesRGBandAlphaChannel()
{
string[] paths = Directory.GetFiles(Application.dataPath+"/test", "*.*", SearchOption.AllDirectories);
foreach (string path in paths)
{
if (!string.IsNullOrEmpty(path) && IsTextureFile(path)) //full name
{
SeperateRGBAandlphaChannel(path);
}
}
}
[MenuItem("EffortForETC1/Show Materials Having Textures with Alpha Chanel")]
static void ShowMaterialsHavingTextureswithAlphaChanel()
{
CalculateTexturesAlphaChannelDic();
string[] matpaths = Directory.GetFiles(Application.dataPath, "*.mat", SearchOption.AllDirectories);
foreach (string matpath in matpaths)
{
string propermatpath = GetRelativeAssetPath(matpath);
Material mat = (Material)AssetDatabase.LoadAssetAtPath(propermatpath, typeof(Material));
if (mat)
{
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 inspect material
static string[] GetMaterialTexturesHavingAlphaChannel(Material _mat)
{
List<string> alphatexpaths = new List<string>();
string[] texpaths = GetMaterialTexturePaths(_mat);
foreach (string texpath in texpaths)
{
if (texturesAlphaDic[texpath])
{
alphatexpaths.Add(texpath);
}
}
return alphatexpaths.ToArray();
}
static string[] GetMaterialTexturePaths(Material _mat)
{
List<string> results = new List<string>();
Object[] roots = new Object[] { _mat };
Object[] dependObjs = EditorUtility.CollectDependencies(roots);
foreach (Object dependObj in dependObjs)
{
if (dependObj.GetType() == typeof(Texture2D))
{
string texpath = AssetDatabase.GetAssetPath(dependObj.GetInstanceID());
results.Add(texpath);
}
}
return results.ToArray();
}
#endregion
static void CalculateTexturesAlphaChannelDic()
{
string[] paths = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories);
foreach (string path in paths)
{
if (!string.IsNullOrEmpty(path) && IsTextureFile(path)) //full name
{
string assetRelativePath = GetRelativeAssetPath(path);
SetTextureReadable(assetRelativePath);
Texture2D sourcetex = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(Texture2D)) as Texture2D;
if (!sourcetex) //make sure the file is really Texture2D which can be loaded as Texture2D.
{
continue;
}
if (HasAlphaChannel(sourcetex))
{
AddValueToDic(assetRelativePath, true);
}
else
{
AddValueToDic(assetRelativePath, false);
}
}
}
}
static void AddValueToDic(string _key, bool _val)
{
if (texturesAlphaDic.ContainsKey(_key))
{
texturesAlphaDic[_key] = _val;
}
else
{
texturesAlphaDic.Add(_key, _val);
}
}
#region process texture
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("Load Texture Failed : " + assetRelativePath);
return;
}
if (!HasAlphaChannel(sourcetex))
{
Debug.Log("Texture does not have Alpha channel : " + assetRelativePath);
return;
}
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);
}
rgbTex.Apply();
alphaTex.Apply();
byte[] bytes = rgbTex.EncodeToPNG();
File.WriteAllBytes(GetRGBTexPath(_texPath), bytes);
bytes = alphaTex.EncodeToPNG();
File.WriteAllBytes(GetAlphaTexPath(_texPath), bytes);
Debug.Log("Succeed to seperate RGB and Alpha channel for texture : " + assetRelativePath);
}
static bool HasAlphaChannel(Texture2D _tex)
{
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);
ti.isReadable = true;
AssetDatabase.ImportAsset(_relativeAssetPath);
}
#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
}
shader
Shader "Custom/TextureETC" {
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" { }
_AlphaTex("AlphaTex",2D) = "white"{}
}
SubShader
{
Tags
{
"Queue" = "Transparent+80"
}
Pass
{
Lighting Off
ZTest Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _AlphaTex;
float _AlphaFactor;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color :COLOR;
};
half4 _MainTex_ST;
half4 _AlphaTex_ST;
v2f vert (appdata_full v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
o.color = v.color;
return o;
}
half4 frag (v2f i) : COLOR
{
half4 texcol = tex2D (_MainTex, i.uv);
half4 result = texcol;
result.a = tex2D(_AlphaTex,i.uv)*i.color.a ;
return result;
}
ENDCG
}
}
}