I want to be able to compress textures at runtime.
I’ve noticed that compressing textures using Texture2D.Compress produces very poor results. The texture will look pixely and noisey.
When importing a texture through Unity editor, results look much better.
Out of curiosity, I tried compressing a texture outside of unity into DDS format (DXT5) using a CLI tool called compressonator, and then importing it into Unity to see what would happen. Unity does indeed recognize that the texture is already compressed DXT5, and thus will not allow you to compress it further. The texture looks just as good as when Unity editor compresses a texture.
Ok, great. So I thought maybe I could just load this external DDS at runtime, then, and get the same result? By skipping the 128 byte header, you can read DDS textures using Texture2D.LoadRawTextureData, as was explained in this Unity answers post. However, when reading a texture this way, it will have the same bad quality as compressing a texture through Unity API. Pixely and noisy.
How can that be? Why would importing a raw DDS through Unity editor produce a better result than reading it through script?
var folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
var path = System.IO.Path.Combine(folder, "some_dds_file.dds");
var bytes = System.IO.File.ReadAllBytes(path);
var DDS_HEADER_SIZE = 128;
byte[] dxtBytes = new byte[bytes.Length - DDS_HEADER_SIZE];
Buffer.BlockCopy(bytes, DDS_HEADER_SIZE, dxtBytes, 0, bytes.Length - DDS_HEADER_SIZE);
var tex = new Texture2D(2048, 2048, TextureFormat.DXT5, false);
tex.LoadRawTextureData(dxtBytes);
tex.Apply();