Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Best way to compress a TextureArray in mobile

Discussion in 'General Graphics' started by carcasanchez, Oct 2, 2020.

  1. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Hello, there.
    I am working in Oculus Quest, and I have the Texture Compression set to ASCT in Build Settings, but the TextureArrays I am using are prompting errors of having an unsupported format (DTX5), which leads me to think that Texture Arrays compression is not overriden at all by these settings.
    I have tried to change texture format when generating the arrays. ASCT_6x6 works fine, but the alpha channel (which I need for some under the hood calculations) is lost in the process. I tried then ASCT_RGBA_6x6, but Unity warns me about this format being not supported by the platform
    I tried then RGBAHalf, which I read somewhere that is not bad for Android. Works perfect, keeps alpha, but the resultant array is incredibly heavy (almost half a gigabyte), in comparison with previous formats.
    I could try and go back and forth between formats, but I would like if any of you could give me a little bit of insight about what could be the best format for a texture array in mobile, without losing the alpha channel.
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,571
  3. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Hi, thanks for the link, we studied it, but it didn't solve our problem.
    We actually managed to convert a texture array to whichever format we want. Our issue is that we didn't manage to find what format is best for our needs.
    I studied the ASTC 6x6 format again and, in fact, alpha channel is stored. But, since we store specific data on that channel, compression seems to ruin it.
    So, we are trying to figure an Oculus Quest compatible format, which keeps alpha channel without losses.
    RGBA formats are almost good, but their size is too much (we ended up with a texture array of half a gigabyte!)

    EDIT: I am open to use a texture specifically to alpha channel in Alpha8, and kept the original in ASTC, but I would like to know about possible other options
     
    Last edited: Oct 5, 2020
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,960
    Hi!
    Did you try using ASTC 4x4? It should have less artifacts than 6x6.
    If you need to keep alpha uncompressed, you have to split your texture into two.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,309
    Generating texture arrays in the editor is a huge pain. It often won't let you generate arrays in the format for the target platform, instead limiting you to the platform you're currently running ... i.e.: in the editor you're sometimes limited to the desktop PC formats, which might be why the DXT5 error came up.
    (Though technically the Adreno GPU in the Quest does support DXT5, even if Unity doesn't seem to think so.)

    Unity 2020.2 finally fixes a lot of this, mainly by making texture arrays first class citizens of the texture importer, allowing you to have all of the same per platform format options, but that's still in alpha.

    Back to the topic of formats. If you use any of the GPU specific compressed texture formats, like ASTC or ETC2, you will loose data. All GPU specific texture compression types are lossy! If you need the data stored in a texture channel to be exactly the data you stored, you must use an uncompressed format. There's no way around it. ASTC 4x4 has some of the best quality compression around, but it is still lossy.

    As for what format you should use, that depends greatly on the data you're trying to store. You've mentioned ASTC 6x6, RGBAHalf, and Alpha8. All 3 of those are very different.

    As mentioned before, ASTC is a compressed format. The different NxN options are the pixel size of the blocks used by the texture, with a block always using 128 bits. The larger the block size, the more compression, but the worse the image quality. ASTC 4x4 matches the memory usage of DXT5 at 8 bits per pixel, but is generally a much higher quality than DXT5. ASTC 6x6 tends to be about the same as or slightly better than DXT5 in quality, but is only ~3.5 bits per pixel making it a good default for color images with or without alpha. Unlike DXT5, ASTC automatically compresses blocks as either RGB+A or RGB data, so any block with fully opaque alpha can be slightly higher quality than those with some alpha. But it still won't match uncompressed as the data is being compressed in a lossy way. ASTC is a super complex texture format though.

    Alpha8 is an 8 bit per pixel uncompressed single channel format. If the data you're storing is a single byte, for example the alpha of a Color32, then this is perfect for you. Absolutely use this.

    RGBAHalf is a 64 bit per pixel, 16 bit per channel, uncompressed RGBA half precision floating point format. This is great if you're looking to store a floating point value between ±65,504 that only needs about 3-4 decimals of precision. If you just need a single channel, or only need that Color32 alpha ... don't use this.
     
  6. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Thanks for the detailed insight, bgolus.
    I will continue work, and I will let you know how everything goes
     
  7. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,630
    Be sure to profile your use of TextureArray on the Quest. It is supported but comes at a cost.
     
  8. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    @carcasanchez You could use ETC2 RGBA. Similar to DXT5 it stores the alpha channel in a separate subblock, so it's uncorrelated to the RGB channels.

    If you need ASTC 6x6 because of the lower bit rate you could try to compress that texture with an external tool and tweak the weighting of the channels to preserve as much of the alpha channel as possible. Unity uses ARM's astcenc compressor internally but does not expose all the settings.
    Unity supports importing compressed textures in .ktx, .pvr, .dds, .astc files.
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,309
    I got the impression @carcasanchez was packing data in the alpha, or at least needed perfectly accurate per-texel values. Technically ASTC also stores alpha uncorrelated too (sometimes). But it doesn't change the fact they're both compressed and if they need accurate values, neither are going to give you that.
     
  10. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Thanks everyone, we have managed to get to a solution we are happy with.
    What we needed, was to pack a value into the alpha channel. We were doing it by dividing by 64, but then I realized that the range of the value was firmly between 0 and 8.
    Just by dividing by 10, we managed to normalize it between 0 and 1 with only one decimal, and seems that ASTC respected it better. We still have some artifacts, but are within the range of acceptable.
    We ended up using ASTC4x4 with "best" compression, and looked good.
    I am still having performance issue with texture arrays in Quest, but they are of other nature, and I think I will post a separated thread.
     
  11. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,630
    Please do. Texture arrays would be nice to use on Quest.