private static Packer.Block[] ComputePack(IList <Texture2D> textures, out int width, out int height) { int num = textures.Count; Packer.Block[] blocks = new Packer.Block[num]; for (int i = 0; i < num; i++) { Texture2D tex = textures[i]; blocks[i] = new Packer.Block() { w = tex.width, h = tex.height, x = 0, y = 0, i = i, }; } Array.Sort(blocks, new BlockComparer()); Packer packer = new Packer(); packer.Fit(blocks, out width, out height); return(blocks); }
public static Rect[] PackTexturesCompute(out Texture result, IList <Texture2D> textures, int maximumAtlasSize = 2048) { int width; int height; Packer.Block[] blocks = ComputePack(textures, out width, out height); if (width < height) { throw new Exception("error"); } float scale = 1; if (width > maximumAtlasSize) { scale = (float)maximumAtlasSize / width; width = maximumAtlasSize; height = (int)(height * scale); } width = PowerOfTwo(width); height = PowerOfTwo(height); RenderTexture rt = new RenderTexture(width, height, 0) { enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; rt.Create(); ComputeShader cs = _computeShader; cs.SetTexture(_kernelId, "Target", rt); cs.SetFloat("Scale", 1 / scale); int len = textures.Count; Rect[] ret = new Rect[len]; for (int i = 0; i < len; i++) { Packer.Block block = blocks[i]; Texture2D tex = textures[block.i]; cs.SetTexture(_kernelId, "Pixels", tex); block *= scale; cs.SetInts("Offset", block.x, block.y); cs.Dispatch(_kernelId, block.w / 8, block.h / 8, 1); ret[block.i] = new Rect(block.x / (float)width, block.y / (float)height, block.w / (float)width, block.h / (float)height); } rt.GenerateMips(); result = rt; //result = new Texture2D(width, height); //RenderTexture tmp = RenderTexture.active; //RenderTexture.active = rt; ////TODO: !!! //result.ReadPixels(new Rect(0, 0, width, height), 0, 0); //UnityEngine.Profiling.Profiler.BeginSample("ReadPixels"); //result.Apply(false, true); //UnityEngine.Profiling.Profiler.EndSample(); //RenderTexture.active = tmp; return(ret); }