最近研究了一下Texture2D.PackTextures方法。它可以在运行时或者编辑时对贴图进行合并。运行时它不支持任意贴图格式的合并,比如现在主流的ASTC,它会合并成RGBA32格式。而且无法指定贴图合并到大图具体某个位置上。
动态合并贴图的方法可以参考我之前的文章,这篇主要考虑静态合并,也就是编辑模式下合并
Unity3D研究院之运行时合并ETC1、ETC2、ASTC、DXT1、DXT5、PVRTC贴图
既然是编辑模式下合并,我们肯定不希望每张小贴图也需要标记read/write enable 那样就太麻烦了。如下代码所示,提供需要合并的小图,以及小图所在大图的偏移即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using System; using System.IO; using UnityEditor; using UnityEngine;
public class TextureCombine { [MenuItem("Tools/TextureCombine")] static void Combine() { Texture2D tex512 = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/512.jpg"); Texture2D tex128 = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/128.jpg"); Texture2D @out = Combine( new[] { tex512, tex128 }, //贴图 new[] { (0, 0), (600, 600) } //偏移 ,1024);//最终贴图大小
File.WriteAllBytes("Assets/out.jpg", @out.EncodeToJPG()); AssetDatabase.Refresh(); }
static Texture2D Combine(Texture2D []texs, ValueTuple<int,int>[]offests,int size) { Texture2D @out = new Texture2D(size, size, TextureFormat.RGBA32, true); for (int i = 0; i < texs.Length; i++) { var tex = texs[i]; var offest = offests[i]; var width = tex.width; var height = tex.height; RenderTexture tmp = RenderTexture.GetTemporary(width,height,0,RenderTextureFormat.Default,RenderTextureReadWrite.Linear); Graphics.Blit(tex, tmp); RenderTexture previous = RenderTexture.active; RenderTexture.active = tmp; Texture2D @new = new Texture2D(width, height); @new.ReadPixels(new Rect(0, 0, width, height), 0, 0); @new.Apply(); @out.SetPixels(offest.Item1, offest.Item2, width, height, @new.GetPixels()); RenderTexture.active = previous; RenderTexture.ReleaseTemporary(tmp); } return @out; }
} |
最后合并的结果