最近研究了一下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("Assets/512.jpg");
Texture2D tex128 = AssetDatabase.LoadAssetAtPath("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[]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;
}
}
最后合并的结果