We introduced Stage3D last year and the momentum behind has never stopped growing but there is one area we did not give all the details. The ATF file format, it is mentioned here and there, so what’s up with this? Some of you may have seen it in the documentation for Stage3D referred as the compressed texture file format, but we never shared any tools to create those famous ATF textures.
Before we package the ATF tools with the AIR SDK, I am happy to share here in advance the ATF tools so that you guys can start leveraging the ATF format now!
So what is it?
First, let’s start by talking about what compressed textures are.
When doing GPU programming with any technology, you have two options for how you handle your textures. You can go compressed or uncompressed, very simple. So, what is the difference?
- When using uncompressed textures, a good old uncompressed file format like PNG is used and uploaded to the GPU.
- Because GPUs don’t support such a file format natively, your texture is actually stored in CPU memory, when it could actually be stored on the GPU memory!
- Same thing applies for JPEG images, make no mistake, graphics chipsets don’t know anything about JPEG which would also be decoded on CPU memory.
- Of course, each platform has different support for compressed textures depending on the hardware chipset being used.
Platform | Format |
---|---|
ImgTech (iOS) | PVRTC |
Qualcom (Android) | ETC1 |
Mali (Android) | ETC1 |
NVidia (Android) | ETC1/DXT1/DXT5 |
Android (PowerVR) | PVRTC/ETC1 |
Windows | DXT1/DXT5 |
MacOS | DXT1/DXT5 |
Why ATF?
As you can imagine, if you would develop a game targeting iOS, Android and desktop, you would need to supply your textures compressed to each format for each platform. Which would look like this:
- leaf.png encoded to DXT for Windows and MacOS
- leaf.png encoded to ETC1 or DXT for Android (Nvidia)
- leaf.png encoded to PVRTC for iOS (ImgTech)
Of course it is a pain to provide all the different versions of the textures, detect at runtime which platform you are running on and upload the corresponding texture. Wouldn’t it be cool if you could just rely on one single container, that would wrap all the textures for each platform and Flash Player or AIR would extract automatically the texture required depending on the platform? So here comes ATF.
The ATF internals
Really, think about the ATF format as a container for lossy images. Here is below a little figure showing very sinply the structure of a default compressed ATF file:
By default, all textures format (PVRTC (4bpp), ETC1, and DXT1/5) are embedded in the ATF file so that for each platform, AIR or Flash Player automatically extracts the appropriate texture. But in some cases, you may want to target mobile only and why should you embed desktop related textures or Android if you are targeting iOS only? To cover this, you can also embed the PVRTC textures only inside the ATF file, making your assets smaller.
The figure below illustrate the idea:
As you can imagine, the same applies to ETC1 if you are targeting Android:
If you know about ETC1, you may wonder how we handle transparency then? We use a dual ETC1 approach with two textures, one for the alpha channel and one for the colors.
And finally on desktop only, where only the DXT texture can be provided:
The difference between DXT1 and DXT5 resides in alpha support. DXT1 does not support transparency, DXT5 does. Automatically the ATF tools will detect if your images have transparency and select the proper DXT version for you. Also note that ATF is not alpha pre-multiplied.
Now, if you want to store uncompressed textures inside an ATF file, you can also do that:
Why would you do that you may ask? Well, you may want to use uncompressed textures but still want to leverage cubemap, automatic mipmap support or even texture streaming.
Ok, now apart from the fact that hardware requires those textures to be compressed, what is the value for your content?
Yes, what does it bring you?
- Faster rendering
- Lower texture memory requirements (extremely important on devices like the iPad1 where memory is very limited)
- Faster texture uploads into texture memory
- Automatic generation of all required mip-maps (note that you can disable this if needed).
- Additionally, the use of compress textures allows the application to utilize higher resolution textures with the same memory footprint.
How to use the tools
The main tool you need to know about is png2atf , which as you can guess, takes a png and gives you an ATF file:
//package leaf.png with all 3 formats (DXT5, PVRTC and ETC1x2) C:\png2atf.exe -c -i leaf.png -o leaf.atf [In 213KB][Out 213KB][Ratio 99.9703%][LZMA:0KB JPEG-XR:213KB] //package specific range of mipmaps C:\png2atf.exe -c -n 0,5 -i leaf.png -o leaf0,5.atf [In 213KB][Out 213KB][Ratio 99.8825%][LZMA:0KB JPEG-XR:213KB] //package only DXT format C:\png2atf.exe -c d -i leaf.png -o leaf_dxt5.atf [In 85KB][Out 85KB][Ratio 100.045%][LZMA:0KB JPEG-XR:85KB] //package only ETC1 format C:\png2atf.exe -c e -i leaf.png -o leaf_etc1.atf [In 85KB][Out 85KB][Ratio 100.045%][LZMA:0KB JPEG-XR:85KB] //package only PVRTC format C:\png2atf.exe -c p -i leaf.png -o leaf_pvrtc.atf [In 42KB][Out 42KB][Ratio 100.089%][LZMA:0KB JPEG-XR:42KB]
As mentioned earlier, what if you wanted to store uncompressed a uncompressed texture inside your ATF? For this, just don’t use the -c argument:
//package as uncompressed (RGBA) format C:\png2atf.exe -i leaf.png -o leaf_rgba.atf [In 341KB][Out 43KB][Ratio 12.8596%][LZMA:0KB JPEG-XR:43KB]
Another cool feature is that ATF can also be used with streaming, to generate 3 sub-files you can do this:
png2atf -m -n 0,0 -c -i cubecat0.png -o cubecat_c_high.atf png2atf -m -n 1,2 -c -i cubecat0.png -o cubecat_c_med.atf png2atf -m -n 3,20 -c -i cubecat0.png -o cubecat_c_low.atf
For info, texture support streaming shipped in Flash Player 11.3/AIR 3.3. Make sure to create the texture with streaming on, by using the streamingLevel arguments of the Texture.createTexture() API.
If you have used the texturetool from Apple to generate your PVR textures, this is the same approach. Another tool called pvr2atf , which is a command line utility converts PVR texture files to ATF files. The tool works similarly to png2atf except that you have to provide input files in the PVR texture format.
To convert a PVR file to an RGB or RGBA ATF file run the command as such:
C:\> pvr2atf -i test.pvr -o test.atf [In 4096KB][Out 410KB][Ratio 10.0241%][LZMA:0KB JPEG-XR:410KB]
Also, you can use ATF for a cubemap texture:
//to create a ATF for cubemap texture, //prepare png file for each side of the cube as: // -X: cube0.png //+X: cube1.png // -Y: cube2.png //+Y: cube3.png // -Z: cube4.png //+Z: cube5.png C:\png2atf.exe -c -m -i cube0.png -o cube.atf
ATFViewer is a GUI tool which previews and inspects ATF files. The primary purpose is to audit DXT1, ETC1 and PVRTC compression artifacts. You can open and view ATF files by either using the ‘Open…’ menu item or by dragging a file from Explorer into the window. The Snippet preview area shows you an example of how to load a particular ATF file in raw ActionScript 3 Stage3D code.
Below is an example of a test file from Starling, you can preview the texture for each format and also have a little code snippet at the bottom which tells you how to use it in ActionScript 3 with Stage3D:
Note that when opening an ATF texture containing only specific compression, the ATFViewer will show this, below we opened an ATF file containing only the DXT textures, you can see that ETC1 and PVRTC in the texture types list are greyed out:
Let’s have a look now at how we can use compressed textures with the Stage3D APIs.
Using compressed textures with Stage3D
To use compressed textures with Stage3D, you need to use theTexture.uploadCompressedTextureFromByteArray API with one of the two relatedContext3DTextureFormat constants (Context3DTextureFormat.COMPRESSED_ALPHA andContext3DTextureFormat.COMPRESSED ):
class Example { [Embed( source = "mytexture.atf", mimeType="application/octet-stream")] public static const TextureAsset:Class; public var context3D:Context3D; public function init():void{ var texture:Texture = context3D.createTexture(256, 256, Context3DTextureFormat.COMPRESSED_ALPHA, false); var textureAsset:ByteArray = new TextureAsset() as ByteArray; texture.uploadCompressedTextureFromByteArray(textureAsset, 0); } };
In the context of a cubemap texture, you would write:
var texCubemap:CubeTexture = context3D.createCubeTexture(256, Context3DTextureFormat.COMPRESSED_ALPHA, false); var textureAsset:ByteArray = new TextureAsset() as ByteArray; texCubemap.uploadCompressedTextureFromByteArray(textureAsset, 0);
Also, depending on the format of the texture, “dxt1” or “dxt5” is needed in the texture sampler of your fragment shader:
- Nothing needed for Context3DTextureFormat.BGRA , same as before
- “dxt1” for Context3DTextureFormat.COMPRESSED (whatever the texture format used, DXT, PVRTC, or ETC1)
- “dxt5” for Context3DTextureFormat.COMPRESSED_ALPHA (whatever the texture format used, DXT, PVRTC, or ETC1)
Integration with Starling
Great news, Starling already supports ATF textures through theTexture.uploadAtfData API. Find here all the details about ATF and Starling, but it is as simple as this:
[Embed(source="starling.atf", mimeType="application/octet-stream")] public static const CompressedData:Class; var data:ByteArray = new CompressedData(); var texture:Texture = Texture.fromAtfData(data); var image:Image = new Image(texture); addChild(image);
Yes, as simple as this .
Limitations
I want to highlight that even if ATF will be very useful for 2D content (like with Starling), ATF has been mainly designed for 3D textures purposes. So what does it mean?
The compression applied to the textures is lossy and may impact too much the quality of your assets. Things like RGBA8888 and RGBA4444 for PVR are not supported and could be an issue.
But we need your feedback and testing to see how we can improve ATF and add support for more compression types. So let us know!
Requirements
One thing to keep in mind is that to cover the entire set of capabilities for ATF textures, you need:
- If you are using Starling, you need at least Starling 1.2. Just pull the latest version from Github .
- If you are using Stage3D directly, you need to use the latestAGALMiniAssembler
- You need at least the AIR SDK 3.4. Download Flash Builder 4.7 which comes out of the box with the AIR 3.4 SDK.
- You need to target at least Flash Player 11.4/AIR 3.4
- You need to add the following compiler argument: ”-swf-version=17”
Download
Download the ATF tools here . Which contains:
- The ATF tools binaries (Linux, Mac, Windows).
- ATF specification
- ATF User Guide with some more details.
Enjoy!