游戏角色shader,包含的东西比较多,还要做到动态合并,程序那边希望贴图经可能少,而我们美术用了两张图,一张图的RGB是高光、流光、自发光,另外一张图的RGB是不同区域的偏色,其实每个通道的一整张贴图只用了一部分,其他地方都是空的,于是就想到把两张图合并成一张图来使用。合并后的这张贴图的R通道:0到128 为高光 128到255为偏色区域,前提是偏色跟高光不要重合 所以这个偏色区域最好是皮肤类的,无明显高光类的。从美术的角度,让他们直接按照这样的色阶来画,肯定是很困难的,所以他们还是按照两张图来做,做是做到不交叉,然后我们用工具将两张图合并成一张图,将偏色从0到255改成128到255,将高光从0到255改成0到128,这样再把两个颜色合并到一起。其他通道也是如此。
如图:
偏色 高光 合并后
这样就是一个通道的合成,到shader里 ,贴图采样后,将0到128提取出来,变换成0到255当作高光贴图来用,将128到255提取出来,变换成0到255当作偏色来用
工具代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class TextureCombine : EditorWindow { [MenuItem("Tools/角色工具/合并贴图")] static void window() { TextureCombine win = (TextureCombine)EditorWindow.GetWindow(typeof(TextureCombine), false, "合并贴图", false); win.Show(); } Texture2D tex1; Texture2D tex2; Texture2D tex3; //第一张贴图的的像素组 List<Color> color01 = new List<Color>(); //第二张贴图的的像素组 List<Color> color02 = new List<Color> (); //得出第三张贴图得像素组 List<Color> color03 = new List<Color>(); private void OnGUI() { tex1 = EditorGUILayout.ObjectField("偏色贴图", tex1, typeof(Texture), true) as Texture2D; tex2 = EditorGUILayout.ObjectField("高光贴图", tex2, typeof(Texture), true) as Texture2D; tex3 = EditorGUILayout.ObjectField("合并后效果", tex3, typeof(Texture), true) as Texture2D; if (GUI.Button(new Rect(100, 40, 50, 25), "合并")) { if (tex1!=null && tex2 != null) { color01.Clear(); color02.Clear(); color03.Clear(); TextureCombin(); }else this.ShowNotification(new GUIContent("没贴图你点个屁啊!!!")); } } void TextureCombin() { //取出第一张贴图的像素 for (int i = 0; i < tex1.height; i++) { for (int j = 0; j < tex1.width; j++) { Color a = tex1.GetPixel(j, i); //将0到1转换成0.51-1 需要加判断 0值也会被加到0.51 就不是黑底了 if (a.r>0) a.r = a.r * 0.51f + 0.49f; if (a.g > 0) a.g = a.g * 0.51f + 0.49f; if (a.b > 0) a.b = a.b * 0.51f + 0.49f; color01.Add(a); } } //取出第二张贴图的像素 for (int i = 0; i < tex1.height; i++) { for (int j = 0; j < tex1.width; j++) { Color a = tex2.GetPixel(j, i); //将0-1的值 转换为 0-0.49 a.r *= 0.49f; a.g *= 0.49f; a.b *= 0.49f; color02.Add(a); } } //得出第一张加第二张贴图 for (int i = 0; i< color01.Count; i++) { Color color = new Color(); if (color01[i].r != 0 && color02[i].r != 0) { this.ShowNotification(new GUIContent("R通道“偏色”跟“高光”交集哦!!!")); break; } else color.r = color01[i].r + color02[i].r; if (color01[i].r != 0 && color02[i].r != 0) { this.ShowNotification(new GUIContent("G通道“偏色”跟“流光”有交集哦!!!")); break; } else color.g = color01[i].g + color02[i].g; if (color01[i].b != 0 && color02[i].b != 0) { this.ShowNotification(new GUIContent("B通道“偏色”跟“自发光”有交集哦!!!")); break; } else color.b = color01[i].b + color02[i].b; color03.Add(color); } //给第三张图赋值 if (color03.Count == tex1.width * tex1.height) { tex3 = new Texture2D(tex1.width, tex1.height, TextureFormat.RGB24, true); for (int i = 0; i < tex1.height; i++) { for (int j = 0; j < tex1.width; j++) { tex3.SetPixel(j, i, color03[j + tex1.width * i]); } } tex3.Apply(); string a = AssetDatabase.GetAssetPath(tex1);//Assets/aa/F2_D001_Body_C 1.psd string[] sArray = a.Split('.'); //取“.”前面部分 a = sArray[0];//取“.”前面部分 byte[] bytes = tex3.EncodeToPNG(); string filename = a+"_Combin.png";//将合并的贴图储存到第一张贴图的路径下 System.IO.File.WriteAllBytes(filename, bytes); EditorApplication.ExecuteMenuItem("Assets/Refresh"); } } }
将两张贴图拖拽到相应位置,点击“合并”,然后新的贴图将保存到偏色贴图的位置,名称为偏色贴图的名称 + “_Combin”
合并后的贴图为png贴图,本来想存成TGA的,发现Texture2D类没有TGA的接口,没弄成功。记得T4m里的那张通道图好像是TGA的,有空去再去研究下。