{"id":103,"date":"2014-12-11T18:50:17","date_gmt":"2014-12-11T10:50:17","guid":{"rendered":"http:\/\/www.zhuyanbin.com\/?p=103"},"modified":"2014-12-18T23:37:46","modified_gmt":"2014-12-18T15:37:46","slug":"stage3d-compressed-textures-introducing-the-atf-sdk","status":"publish","type":"post","link":"https:\/\/www.yanbin888.com\/?p=103","title":{"rendered":"Stage3D compressed textures \u2013 Introducing the ATF SDK"},"content":{"rendered":"<p>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&#8217;s up with this?\u00a0Some 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.<\/p>\n<p>Before we package the ATF tools with the AIR SDK,\u00a0I am happy to share here in advance the ATF tools so that you guys can start leveraging the ATF format now!<\/p>\n<p><strong>So what is it?<\/strong><\/p>\n<p>First, let&#8217;s start by talking about what compressed textures are.<\/p>\n<p>When doing GPU programming with any technology,\u00a0you have two options for how you handle your textures. You can go compressed or uncompressed, very simple. So, what is the difference?<\/p>\n<div>\n<ol>\n<li>When using uncompressed textures, a good old uncompressed file format like PNG is used and uploaded to the GPU.<\/li>\n<li>Because GPUs don&#8217;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!<\/li>\n<li>Same thing applies for JPEG images, make no mistake, graphics chipsets don&#8217;t know anything about JPEG which would also be decoded on CPU memory.<\/li>\n<li>Of course, each platform has different support for compressed textures depending on the hardware chipset being used.<\/li>\n<\/ol>\n<div>Now get ready for the fun!\u00a0Here is below a little table to illustrate it:<\/div>\n<\/div>\n<table>\n<thead>\n<tr>\n<th>Platform<\/th>\n<th>Format<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>ImgTech (iOS)<\/td>\n<td>PVRTC<\/td>\n<\/tr>\n<tr>\n<td>Qualcom (Android)<\/td>\n<td>ETC1<\/td>\n<\/tr>\n<tr>\n<td>Mali (Android)<\/td>\n<td>ETC1<\/td>\n<\/tr>\n<tr>\n<td>NVidia (Android)<\/td>\n<td>ETC1\/DXT1\/DXT5<\/td>\n<\/tr>\n<tr>\n<td>Android (PowerVR)<\/td>\n<td>PVRTC\/ETC1<\/td>\n<\/tr>\n<tr>\n<td>Windows<\/td>\n<td>DXT1\/DXT5<\/td>\n<\/tr>\n<tr>\n<td>MacOS<\/td>\n<td>DXT1\/DXT5<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><strong>Why ATF?<\/strong><\/p>\n<p>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:<\/p>\n<ol>\n<li>leaf.png encoded to DXT for <strong>Windows<\/strong> and <strong>MacOS<\/strong><\/li>\n<li>leaf.png encoded to ETC1 or DXT for <strong>Android<\/strong> (Nvidia)<\/li>\n<li>leaf.png encoded to PVRTC for <strong>iOS<\/strong> (ImgTech)<\/li>\n<\/ol>\n<p>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&#8217;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\u00a0automatically\u00a0the texture required depending on the platform? So here comes ATF.<\/p>\n<p><strong>The ATF internals<\/strong><\/p>\n<p>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:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/01.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-107\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/01-300x240.png\" alt=\"01\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/01-300x240.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/01.png 420w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>The figure below illustrate the idea:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/02.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-108\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/02-300x240.png\" alt=\"02\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/02-300x240.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/02.png 420w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>As you can imagine, the same applies to ETC1 if you are targeting Android:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/03.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-109\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/03-300x240.png\" alt=\"03\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/03-300x240.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/03.png 420w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>And finally on desktop only, where only the DXT texture can be provided:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/04.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-110\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/04-300x240.png\" alt=\"04\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/04-300x240.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/04.png 420w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>Now, if you want to store uncompressed textures inside an ATF file, you can also do that:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/05.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-111\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/05-300x240.png\" alt=\"05\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/05-300x240.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/05.png 420w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>Ok, now apart from the fact that hardware requires those textures to be compressed, what is the value for your content?<\/p>\n<p><strong>Yes, what does it bring you?<\/strong><\/p>\n<ul>\n<li>Faster rendering<\/li>\n<li>Lower texture memory requirements (extremely important on devices like the iPad1 where memory is very limited)<\/li>\n<li>Faster texture uploads into texture memory<\/li>\n<li>Automatic generation of all required mip-maps (note that you can disable this if needed).<\/li>\n<li>Additionally, the use of compress textures allows the\u00a0application to utilize higher\u00a0resolution textures with the same memory footprint.<\/li>\n<\/ul>\n<div>Now the question is, how do you create such ATF files? It is very easy, we provide a few command line tools for that. Let&#8217;s have a look at how it works.<\/div>\n<p><strong>How to use the tools<\/strong><\/p>\n<p>The main tool you need to know about is <strong>png2atf<\/strong> , which as you can guess, takes a png and gives you an ATF file:<\/p>\n<pre class=\"prettyprint cs\"><span class=\"comment\">\/\/package leaf.png with all 3 formats (DXT5, PVRTC and ETC1x2)<\/span>\r\nC:\\png2atf.exe  -c  -i  leaf.png  -o  leaf.atf\r\n[In <span class=\"number\">213<\/span>KB][Out <span class=\"number\">213<\/span>KB][Ratio <span class=\"number\">99.9703<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">213<\/span>KB]\r\n\r\n<span class=\"comment\">\/\/package specific range of mipmaps<\/span>\r\nC:\\png2atf.exe  -c  -n  <span class=\"number\">0<\/span>,<span class=\"number\">5<\/span>  -i  leaf.png  -o  leaf0,<span class=\"number\">5.<\/span>atf\r\n[In <span class=\"number\">213<\/span>KB][Out <span class=\"number\">213<\/span>KB][Ratio <span class=\"number\">99.8825<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">213<\/span>KB]\r\n\r\n<span class=\"comment\">\/\/package only DXT format<\/span>\r\nC:\\png2atf.exe  -c d  -i  leaf.png  -o  leaf_dxt5.atf\r\n[In <span class=\"number\">85<\/span>KB][Out <span class=\"number\">85<\/span>KB][Ratio <span class=\"number\">100.045<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">85<\/span>KB]\r\n\r\n<span class=\"comment\">\/\/package only ETC1 format<\/span>\r\nC:\\png2atf.exe  -c e  -i  leaf.png  -o  leaf_etc1.atf\r\n[In <span class=\"number\">85<\/span>KB][Out <span class=\"number\">85<\/span>KB][Ratio <span class=\"number\">100.045<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">85<\/span>KB]\r\n\r\n<span class=\"comment\">\/\/package only PVRTC format<\/span>\r\nC:\\png2atf.exe  -c p  -i  leaf.png  -o  leaf_pvrtc.atf\r\n[In <span class=\"number\">42<\/span>KB][Out <span class=\"number\">42<\/span>KB][Ratio <span class=\"number\">100.089<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">42<\/span>KB]<\/pre>\n<p>As mentioned earlier, what if you wanted to store uncompressed a uncompressed texture inside your ATF? For this, just don&#8217;t use the -c argument:<\/p>\n<pre class=\"prettyprint cs\"><span class=\"comment\">\/\/package as uncompressed (RGBA) format<\/span>\r\nC:\\png2atf.exe  -i  leaf.png  -o  leaf_rgba.atf\r\n[In <span class=\"number\">341<\/span>KB][Out <span class=\"number\">43<\/span>KB][Ratio <span class=\"number\">12.8596<\/span>%][LZMA:<span class=\"number\">0<\/span>KB JPEG-XR:<span class=\"number\">43<\/span>KB]<\/pre>\n<p>Another cool feature is that ATF can also be used with streaming, to generate 3 sub-files you can do this:<\/p>\n<pre class=\"prettyprint undefined\">png2atf -m -n 0,0 -c -i cubecat0.png -o cubecat_c_high.atf\r\npng2atf -m -n 1,2 -c -i cubecat0.png -o cubecat_c_med.atf\r\npng2atf -m -n 3,20 -c -i cubecat0.png -o cubecat_c_low.atf<\/pre>\n<p>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 <em>Texture.createTexture()<\/em> API.<\/p>\n<p>If you have used the <a title=\"Apple Texturetool\" href=\"http:\/\/developer.apple.com\/library\/ios\/#documentation\/3DDrawing\/Conceptual\/OpenGLES_ProgrammingGuide\/TextureTool\/TextureTool.html#\/\/apple_ref\/doc\/uid\/TP40008793-CH108-SW1\" target=\"_blank\">texturetool<\/a> from Apple to generate your PVR textures, this is the same approach. Another tool called <strong>pvr2atf<\/strong> ,\u00a0which is a command line utility converts PVR texture files to ATF files. The tool works similarly to <strong>png2atf<\/strong> except that you have to provide input files in the PVR texture format.<\/p>\n<p>To convert a PVR file to an RGB or RGBA ATF file run the command as such:<\/p>\n<pre class=\"prettyprint css\"><span class=\"tag\">C<\/span>:\\&gt; <span class=\"tag\">pvr2atf<\/span> -<span class=\"tag\">i<\/span> <span class=\"tag\">test<\/span><span class=\"class\">.pvr<\/span> -<span class=\"tag\">o<\/span> <span class=\"tag\">test<\/span><span class=\"class\">.atf<\/span>\r\n<span class=\"attr_selector\">[In 4096KB]<\/span><span class=\"attr_selector\">[Out 410KB]<\/span><span class=\"attr_selector\">[Ratio 10.0241%]<\/span><span class=\"attr_selector\">[LZMA:0KB JPEG-XR:410KB]<\/span><\/pre>\n<p>Also, you can use ATF for a cubemap texture:<\/p>\n<pre class=\"prettyprint cs\"><span class=\"comment\">\/\/to create a ATF for cubemap texture,<\/span>\r\n<span class=\"comment\">\/\/prepare png file for each side of the cube as:<\/span>\r\n<span class=\"comment\">\/\/ -X: cube0.png<\/span>\r\n<span class=\"comment\">\/\/+X: cube1.png<\/span>\r\n<span class=\"comment\">\/\/ -Y: cube2.png<\/span>\r\n<span class=\"comment\">\/\/+Y: cube3.png<\/span>\r\n<span class=\"comment\">\/\/ -Z: cube4.png<\/span>\r\n<span class=\"comment\">\/\/+Z: cube5.png<\/span>\r\nC:\\png2atf.exe  -c   -m  -i  cube0.png  -o  cube.atf<\/pre>\n<p><strong>ATFViewer<\/strong> 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 \u2018Open&#8230;\u2019 menu item or by dragging a file from Explorer into the window.\u00a0The Snippet preview area shows you an example of how to load a particular ATF file in raw ActionScript 3 Stage3D code.<\/p>\n<p>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:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/06.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-112\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/06-300x239.png\" alt=\"06\" width=\"300\" height=\"239\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/06-300x239.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/06.png 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>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:<\/p>\n<p><a href=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/07.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-113\" src=\"http:\/\/www.zhuyanbin.com\/wp-content\/uploads\/2014\/12\/07-300x239.png\" alt=\"07\" width=\"300\" height=\"239\" srcset=\"https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/07-300x239.png 300w, https:\/\/www.yanbin888.com\/wp-content\/uploads\/2014\/12\/07.png 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Let&#8217;s have a look now at how we can use compressed textures with the Stage3D APIs.<\/p>\n<p><strong>Using compressed textures with Stage3D<\/strong><\/p>\n<p>To use compressed textures with Stage3D, you need to use the<em>Texture.uploadCompressedTextureFromByteArray<\/em> API with one of the two related<em>Context3DTextureFormat<\/em> constants (<em>Context3DTextureFormat.COMPRESSED_ALPHA<\/em> and<em>Context3DTextureFormat.COMPRESSED<\/em> ):<\/p>\n<pre class=\"prettyprint php\"><span class=\"class\"><span class=\"keyword\">class<\/span> <span class=\"title\">Example<\/span> {<\/span>\r\n[Embed( source = <span class=\"string\">\"mytexture.atf\"<\/span>, mimeType=<span class=\"string\">\"application\/octet-stream\"<\/span>)]\r\n<span class=\"keyword\">public<\/span> <span class=\"keyword\">static<\/span> <span class=\"keyword\">const<\/span> TextureAsset:Class;\r\n<span class=\"keyword\">public<\/span> <span class=\"keyword\">var<\/span> context3D:Context3D;\r\n\r\n<span class=\"keyword\">public<\/span> <span class=\"function\"><span class=\"keyword\">function<\/span> <span class=\"title\">init<\/span><span class=\"params\">()<\/span>:<span class=\"title\">void<\/span>{<\/span>\r\n<span class=\"keyword\">var<\/span> texture:Texture = context3D.createTexture(<span class=\"number\">256<\/span>, <span class=\"number\">256<\/span>, Context3DTextureFormat.COMPRESSED_ALPHA, <span class=\"keyword\">false<\/span>);\r\n<span class=\"keyword\">var<\/span> textureAsset:ByteArray = <span class=\"keyword\">new<\/span> TextureAsset() <span class=\"keyword\">as<\/span> ByteArray;\r\ntexture.uploadCompressedTextureFromByteArray(textureAsset, <span class=\"number\">0<\/span>);\r\n}\r\n};<\/pre>\n<p>In the context of a cubemap texture, you would write:<\/p>\n<pre class=\"prettyprint cs\"><span class=\"keyword\">var<\/span> texCubemap:CubeTexture = context3D.createCubeTexture(<span class=\"number\">256<\/span>, Context3DTextureFormat.COMPRESSED_ALPHA, <span class=\"keyword\">false<\/span>);\r\n<span class=\"keyword\">var<\/span> textureAsset:ByteArray = <span class=\"keyword\">new<\/span> TextureAsset() <span class=\"keyword\">as<\/span> ByteArray;\r\ntexCubemap.uploadCompressedTextureFromByteArray(textureAsset, <span class=\"number\">0<\/span>);<\/pre>\n<p>Also, depending\u00a0on the format of the texture, \u201cdxt1\u201d or \u201cdxt5\u201d is needed in the texture sampler of your fragment shader:<\/p>\n<ul>\n<li>Nothing needed for <em>Context3DTextureFormat.BGRA<\/em> , same as before<\/li>\n<li>\u201cdxt1\u201d for <em>Context3DTextureFormat.COMPRESSED (whatever the texture format used, DXT, PVRTC, or ETC1)<\/em><\/li>\n<li>\u201cdxt5\u201d for <em>Context3DTextureFormat.COMPRESSED_ALPHA\u00a0 <em>(whatever the texture format used, DXT, PVRTC, or ETC1)<\/em><\/em><\/li>\n<\/ul>\n<div>You can also check the specific\u00a0 <a title=\"Starling support for ATF\" href=\"https:\/\/github.com\/PrimaryFeather\/Starling-Framework\/commit\/7739a9e002e04659f7a5517f6093e0e77ccf430c\" target=\"_blank\">Starling commit for ATF support<\/a> \u00a0to see how it got integrated.<\/div>\n<p><strong>Integration with Starling<\/strong><\/p>\n<p>Great news, Starling already supports ATF textures through the<em>Texture.uploadAtfData<\/em> API. Find <a title=\"ATF Textures and Starling\" href=\"http:\/\/wiki.starling-framework.org\/manual\/atf_textures\" target=\"_blank\">here<\/a> all the details about ATF and Starling, but it is as simple as this:<\/p>\n<pre class=\"prettyprint cs\">[Embed(source=<span class=\"string\">\"starling.atf\"<\/span>, mimeType=<span class=\"string\">\"application\/octet-stream\"<\/span>)]\r\n<span class=\"keyword\">public<\/span> <span class=\"keyword\">static<\/span> <span class=\"keyword\">const<\/span> CompressedData:Class;\r\n\r\n<span class=\"keyword\">var<\/span> data:ByteArray = <span class=\"keyword\">new<\/span> CompressedData();\r\n<span class=\"keyword\">var<\/span> texture:Texture = Texture.fromAtfData(data);\r\n\r\n<span class=\"keyword\">var<\/span> image:Image = <span class=\"keyword\">new<\/span> Image(texture);\r\naddChild(image);<\/pre>\n<p>Yes, as simple as this .<\/p>\n<p><strong>Limitations<\/strong><\/p>\n<p>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?<br \/>\nThe compression applied to the textures is lossy and may impact too much the quality of your assets. Things like\u00a0RGBA8888 and RGBA4444 for PVR are not supported and could be an issue.<br \/>\nBut we need your feedback and testing to see how we can improve ATF and add support for more compression types. So let us know!<\/p>\n<p><strong>Requirements<\/strong><\/p>\n<p>One thing to keep in mind is that to cover the entire set of capabilities for ATF textures, you need:<\/p>\n<ul>\n<li>If you are using Starling, you need at least Starling 1.2. Just pull the <a title=\"Starling Framework\" href=\"http:\/\/www.bytearray.org\/github.com\/PrimaryFeather\/Starling-Framework\" target=\"_blank\">latest version from Github<\/a> .<\/li>\n<li>If you are using Stage3D directly, you need to use the latest<a title=\"AGALMiniAssembler\" href=\"https:\/\/github.com\/PrimaryFeather\/Starling-Framework\/blob\/master\/starling\/src\/com\/adobe\/utils\/AGALMiniAssembler.as\" target=\"_blank\">AGALMiniAssembler<\/a><\/li>\n<li>You need at least the AIR SDK 3.4. <a title=\"Adobe Flash Builder 4.7\" href=\"http:\/\/labs.adobe.com\/technologies\/flashbuilder4-7\/\" target=\"_blank\">Download Flash Builder 4.7<\/a> which comes out of the box with the AIR 3.4 SDK.<\/li>\n<li>You need to target at least Flash Player 11.4\/AIR 3.4<\/li>\n<li>You need to add the following compiler argument: \u201d-swf-version=17\u201d<\/li>\n<\/ul>\n<p><strong>Download<\/strong><\/p>\n<p>Download the ATF tools <a title=\"ATF Tools\" href=\"https:\/\/dl.dropbox.com\/u\/7009356\/atftools.zip\">here<\/a> . Which contains:<\/p>\n<ul>\n<li>The ATF tools binaries (Linux, Mac, Windows).<\/li>\n<li>ATF specification<\/li>\n<li>ATF User Guide with some more details.<\/li>\n<\/ul>\n<p>Enjoy!<\/p>\n<p>&nbsp;<\/p>\n<p>link:\u00a0<a title=\"http:\/\/www.tuicool.com\/articles\/Q3Ajay\" href=\"http:\/\/www.tuicool.com\/articles\/Q3Ajay\" target=\"_blank\">http:\/\/www.tuicool.com\/articles\/Q3Ajay<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We introduced Stage3D last year and the momentum behind <span class=\"ellipsis\">&hellip;<\/span> <span class=\"more-link-wrap\"><a href=\"https:\/\/www.yanbin888.com\/?p=103\" class=\"more-link\"><span>Read More &rarr;<\/span><\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-103","post","type-post","status-publish","format-standard","hentry","category-mobile"],"_links":{"self":[{"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/posts\/103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=103"}],"version-history":[{"count":3,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/posts\/103\/revisions"}],"predecessor-version":[{"id":115,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=\/wp\/v2\/posts\/103\/revisions\/115"}],"wp:attachment":[{"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yanbin888.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}