Tuesday, July 1, 2014

Ericsson Texture Compression

I recently added support for the new OpenGL ES 3.0 compressed texture formats, ETC2 and EAC.

Now with Animated GIF technology.  2002 here we come!

Compressed Textures?

Compressed textures have been in OpenGL ES on iOS for quite a while.  What they let you do is represent a texture in less memory.  The hardware will do a little bit of math as it fetches a pixel, giving you a real RGBA value in the shader.

This is nice if you're short on memory when doing animation and we animate a lot when doing weather.

Sure, I wanted to animate this one too.  You're welcome.

Before 3.0, iOS hardware supported PVRTC through an extension.  That's a fine format, but it suffers from one big flaw:  You can't load just a piece of a PVRTC texture, you have to load the whole thing.  WhirlyGlobe-Maply makes heavy use of dynamic textures, so that was a non-starter.

The ETC2/EAC Compressed Formats

PVRTC is clever, but clever can be overrated.  The new formats, ETC2 and EAC are less clever, but their support is much deeper.  Most importantly, they support glTexSubImage2d().

I rely on that command for the dynamic texture atlases. Since textures can come in at any time, via map tiles or font glyphs, I can't pre-construct the atlases; I have to do it dynamically.  PVRTC didn't support modifications to textures.  ETC2 and EAC do.

ETC2 / EAC Display Support

You'll find support for 7 of the compressed formats in WG-Maply 2.3.  The first three are immediately useful, the rest are a bit obscure.

  • MaplyImageETC2RGB8 - Nominally 8 bits per channel RGB.  This is compressed roughly 8:1 from the naive 32 bit RGB.
  • MaplyImageETC2RGBA8 - RGBA, 8 bits per channel.  Compressed 4:1 from naive 32 bit RGBA.
  • MaplyImageETC2RGBPA8 - RGB plus a single bit Alpha.
  • MaplyImageEACR11 - Single channel, nominally 16 bits.
  • MaplyImageEACR11S - Signed single channel.
  • MaplyImageEACRG11 - Two channel, nominally 16 bits.
  • MaplyImageEACRG11S - Two channel, signed.
The first one, RGB8, is useful for your full color basemap and the second one, RGBA8, is decent for full color transparent overlays.  The rest have their uses, but get weirder.

And I should Care Because....?

Let's do a little math.  WG-Maply likes to allocate 2048x2048 texel maps for its dynamic texture atlases.  For an RGBA texture, that takes up 16MB.  Now there are simple textures formats that just chop the lower bits out.  For some data sets that'll work in 8MB.  With ETC2 RGB8 you can represent the same data in 2MB.  That's either 8:1 or 4:1 depending on the data set and ETC2 looks much better.

The new texture formats are part of the OpenGL ES 3.0 standard.  Only a few devices support 3.0 at the moment, but that list is getting bigger every day.  For some apps, it's a huge win.

Great, so How Do I Serve These?

Mention anything other than JPG or PNG to server developers and they look at you with a mix of loathing and fear.  You can't really compress these efficiently on the client side, so the server's got to serve them.

There's a free program called etcpack that will do the conversion for you.  I've run some tests myself (at the behest of a client) and found conversion to ETC2 RGB8 and RGBA8 pretty easy.  You still have to store the images, of course, but disk is cheap.  Right?


For certain kinds of apps ETC2 and EAC are a huge win.  If you use a lot of image overlays and you find yourself low on memory, they're worth a look.  Full support is in WhirlyGlobe-Maply 2.3.