Android OpenGL Texture Compression
Asked Answered
C

4

55

I need some help finding information (or an example) of how to use texture compression for Android. I have a lot of PNG's right now and I need to reduce the amount of memory they take up. I was looking at PVR compression but I can't figure out how to use this within OpenGL.

Could some point me in the right direction or offer some examples as I cannot find anything.

Characteristically answered 5/2, 2012 at 11:20 Comment(0)
K
85

There are mainly four texture compression types supported on Android:

  • ETC1 (Ericsson texture compression). This format is supported by all Android phones. But, it doesn't support an alpha channel, so can only be used for opaque textures.
  • PVRTC (PowerVR texture compression). Supported by devices with PowerVR GPUs (Nexus S, Kindle fire, etc.).
  • ATITC (ATI texture compression). Used in devices with Adreno GPU from Qualcomm (Nexus One, etc.).
  • S3TC (S3 texture compression). This texture compression is used in the NVIDIA chipset integrated devices (Motorola Xoom, etc.)

More detailed information here and here.

In short, if your textures don't have alpha, you can use ETC1. If they do have alpha, and you want to support all devices, you must have your textures compressed in the other three types and load them according to the device.

How to use:

  1. Compress your png files (You can use a tool like ETC-Pack, PVRTexTool, ATI Compressonator, Nvidia Texure Tools according to the type of texture) and add to your project assets.

  2. Determine which extensions are available in the device, if you're not using ETC1:

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    
         String s = gl.glGetString(GL10.GL_EXTENSIONS);
    
         if (s.contains("GL_IMG_texture_compression_pvrtc")){
              //Use PVR compressed textures         
         }else if (s.contains("GL_AMD_compressed_ATC_texture") ||
                  s.contains("GL_ATI_texture_compression_atitc")){
              //Load ATI Textures           
         }else if (s.contains("GL_OES_texture_compression_S3TC") ||
                    s.contains("GL_EXT_texture_compression_s3tc")){
             //Use DTX Textures
         }else{
             //Handle no texture compression founded.               
         }
    
    }           
    
  3. Load compressed texture as raw data.

  4. Use glCompressedTexImage2D instead of glTexImage2D:

    public void onDrawFrame(GL10 gl) {
    
       ....
    
       gl.glCompressedTexImage2D(GL10.GL_TEXTURE_2D, level, internalformat, width, 
                                 height, border, imageSize, data);
    
    }
    
Kinakinabalu answered 1/3, 2012 at 10:20 Comment(8)
Hi @Xilliah, the thread is old and it's possible you're right, but this solution is working quite well in several of my projects. If you think it's incorrect you can do two things, or you tell what do you think is wrong and I'll be glad to try to fix it or please feel free to add another answer with a correct solution... Constructive comments please!.Thanks.Kinakinabalu
Hello Gergonzalez. I made a mistake and was incorrect, but was unable to remove the comment for some reason. Just me being silly again. Your answer helped!Prepay
Nice! Glad to help :)Kinakinabalu
ETC can be used with alpha, see ETC Texture Compression and Alpha Channel Handling malideveloper.arm.com/develop-for-mali/sample-code/…Attractant
What about Mali devices, I don't believe they support any of those three formats w/alpha. The newer ones can use ETC2 because it's part of the ES 3.0 spec, but if you have to support four different compressed formats for your textures w/alpha you may be better off just leaving them uncompressed because you're not going to save any disk space.Xylidine
Just to point out, this solution won't reduce the total size of your images (most likely), although it will reduce the size of those images used in GPU memory.Pase
You can have different builds of your app that are targeted to specific devices and have only one texture compression. Google Play will offer the appropriate variant to your users based on their device.Younts
GL_OES_texture_compression_S3TC seems to does not exists. Where do you seen it ?Frictional
P
5

This is an ol thread, so I thought I'd update it with the information available on http://devtools.ericsson.com/etc ETC2 is mandatory in the Khronos standards OpenGL ES 3.0 and OpenGL 4.3.

Permute answered 23/3, 2013 at 22:18 Comment(0)
T
3

You should not use just PVR compression on Android, since that will not work with all models. To get around that you should either only use ETC1 (mandated on all GLES 2.0 devices) or have separate texture packs for separate GPU modes. The android dev guide has a helper class to load the compression format.

You can use etcpack to do compression.

Note that you will not get an alpha channel with ETC1 - you can do some fancy fragment shading tricks to get around that by having the alpha channel as a separate texture.

Theorize answered 5/2, 2012 at 13:20 Comment(3)
I did try that however Eclipse doesnt know what ETC1Util is and it cant find an import...any reason for that issue?Characteristically
"you should either only use ETC1 (mandated on all GLES 2.0 devices)" I don't think it is mandatory on OpenGL ES - It looks, to me, to be an extension: see khronos.org/registry/glesLegitimist
It is an extension to GLES 1.0/1.1, but is mandated for GLES 2.0.Theorize
M
3

Just wanted to point out etc1 isn't supported by all android devices, contrary to what gergonzalez said

Caution: The ETC1 format is supported by most Android devices, but it not guaranteed to be available. To check if the ETC1 format is supported on a device, call the ETC1Util.isETC1Supported() method.

https://developer.android.com/guide/topics/graphics/opengl.html#textures

Manoff answered 21/4, 2014 at 20:35 Comment(1)
That sucks, so there's only one guarantee it seems: The ETC2/EAC texture compression formats are guaranteed to be available when using the OpenGL ES 3.0 API..Linskey

© 2022 - 2024 — McMap. All rights reserved.