Search Unity

Can't compress a runtime loaded PNG texture to DXT1, instead of DXT5?

Discussion in 'Scripting' started by unisip, Jan 4, 2012.

  1. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    I'm loading png images at runtime into textures, because PNG happens to have a better compression ratio than JPG on images that contain vector graphics.
    Since I don't care about the alpha channel of those PNG images, I owuld like to compress them to DXT1 rather than DXT5 (twice smaller in RAM and VRAM).
    However, I can't seem to get that to happen.
    Here is what I'm doing in C#:

    Texture2D tex = new Texture2DTextureSize, TextureSize,TextureFormat.DXT1,false);
    tex.LoadImage(myByteArray); //where myByteArray contains the PNG data
    tex.Compress(false);

    The weird thing when I do that is that the inspector says my texture is DXT5, and the displayed image has strange colors (like the encoded data is DXT5 but the texture format information somehow remained DXT1).

    Aside the fact that this is inconsistent, is there a way I can get a runtime-loaded PNG image to compress to DXT1 and NOT DXT5?
     
  2. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    Ok, just to complement the above message:
    - Unity compresses 24bit textures to DXT1, and 32bits textures to DXT5
    - a 24bit JPG will load in a 24bit texture and compress to DXT1
    - a 8bit JPG will load in a 32bit texture and compress to DXT5

    To avoid any issues with the compression, the texture can be created for TextureFormat.RGB24, and then compressed.
    What's missing here is the ability to get rid of the alpha channel of the texture object (to force it to compress to DXT1).

    Any ideas on how to achieve that?
     
  3. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    You can always define the compression type yourself.
    Switch the texture to Advanced mode then you can select the explicit compression.

    Getting rid of the alpha channel otherwise requires code (texture importer likely) that cuts the alpha channel at that point already.
    Thats also where you could force apply the compression basing on a naming scheme by the way


    the reason it chooses DXT5 and DXT1 like that is that DXT1 is only RGB information while DXT5 is A and RGB so as long as you have A in it will be DXT5 (technically you could also use DXT3 but its not smooth gradients there thus its often avoided for anything but alpha masking and similar special cases where you have descrete alpha values)


    Another thing to keep in mind: you can use the photonshop exporter plugin from nvidia to export DDS directly including their mipmaps and get full control over the texture and compression without ever going through png
     
  4. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    Thanks, Dreamora, although this doesn't really answer my question.
    My images are loaded in code, so I can't go into the inspector settings and modify them.
    As a side note, DXT1 does support RGBA, but stores A with a single bit, enabling simple alpha masks for alpha testing.

    Anyway, right now it seems that I could either:
    - write my own texture importer to get my JPG and PNG files in a 24bits RGB texture, then use compress on it
    - do some clumsy and likelly fairly slow array copy from the loaded 32 bits texture into a 24bits texture, then use compress on it

    In either case, compression is done synchroneously and potentially causes a framerate hickup.

    In an ideal world, being able to fill the texture in its final compressed format directly would be awesome --> I could load the JPG/PNG in a custom reader, compress it to DXT, all in a separate thread, and finally load the result into a texture object. That way, texture loading wouldn't hurt either VRAM nor application frame rate
     
  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    In an ideal world you wouldn't use PNG at all if you want DXT textures you would use WWW and load the DDS directly, you would get more control and a better quality, a significantly shorter loading time, no 2 hickups (once for the png LoadImage call and once for the compression) and this thread wouldn't exist ;)
     
  6. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    Right! Except in the project I'm working on I have no control of how the images are delivered to me. I'm posting requests to a web server and I get the images in whatever format the guys taking care of the server part decide (in fact, either JPG or PNG).

    Anyway, I guess it's time to ask Unity to make those texture operations multi threaded :)