This tool was part of my research of rendering optimizations, where I came up with custom static batching. This is just a prototype and wasn't used in production.
With this tool I wanted to solve 2 problems
- inefficient textures usage
- reduce the number of batches and setpass calls
Before start I decided to collect some statistics to see how effectively we use textures on levels, as we have groups of assets that artists packed into atlases by the same setting/style or some other logic.
I made a simple tool which collects all meshes and textures from the scene, and renders all the meshes with the same material into render texture using their uvs as vertex positions, so I can see what parts of textures are really used in the scene.
And I found that we have some assets that brings big textures and use very small part of it. So I decided to go on and see if I can repack it somehow inside Unity. And I made this tool
How does it work?
- It collects all scene meshes grouped by materials
- In each mesh it finds uv shells and packs it in a list of
UVShell
data classes, here's simplified example:
public class UVShell
{
public List<int> indices = new();
public Rect rect; // bounding rect of uv shell
public Vector2 offset;
public Vector2 scale = Vector2.one;
}
it also handles uv overlaps to avoid texture chunk duplication
- Collects all found UVShells from all meshes into one list and packs it using bin packing algorithm by their
rect
s. Packing info stored inoffset
andscale
values. - It applies new offsets to the meshes uvs using data from
UVShell
. - Renders all the meshes into render texture using their new uvs as vertex positions, with the original texture applied.
- And finally it creates new material with new texture and applies to all MeshRenderers.
For the quick scene preview I used MeshRenderer.additionalVertexStreams, so I didn't modify original meshes.
It also calculates "best" size for the atlas using texel size of meshes, and there are some scaling options for each UVShell group.
Here are some demos of various tool iterations:
Why I decided to not use it eventually?
After the custom static batching, packing all scene meshes into one texture atlas gave almost no performance improvements, as scenes became more GPU bound after proper batching. And it brings some overcomplication and questions into art's pipeline. And also it's not possible to render the whole scene as one batch, since batching has limitation of 64000 vertices per batch.
It still might be useful in reducing runtime video memory usage if there are many inefficient textures. But it appeared that it wasn't that big problem for us. We just repacked some common assets into other atlases manually.