1 /*! \page texture-atlases Texture Atlases
3 * <h2 class="pg">Using Texture Atlases in DALi </h2>
6 * <h3> Example demo application </h3>
8 \image html image-wall.jpg
11 <h3> Application above is running slow as there are many small individual images displayed (50)</h3>
15 <td> Launch Time </td>
17 <td> Has to perform: <br>- 50 file open requests and multiple reads for each image</td>
20 <td> Memory Usage </td>
23 <br>- 50 Dali::Image objects
24 <br>- 50 OpenGL Textures
28 <td>Rendering Performance </td>
31 <br>- 50 glBindTexture calls per frame ( each OpenGL calls takes time)
32 <br>- 50 a frame = 3000 calls per second @60 FPS.
33 <br>- Texture switching is a major state change in the GPU
40 * <h3> Solutions to problem: Use a Texture Atlas</h3>
42 A texture atlas is simply one larger image that contains smaller images. A texture atlas is sometimes called a
43 sprite sheet, bitmap sheet or texture pack.
48 Dali::ImageActor has the ability to display a portion of an image using ImageActor::PixelArea setting.
49 For example to display the first 3 image in the atlas
51 \image html example-code.jpg
53 <h3> Result of using an Atlas</h3>
56 <td> Launch Time </td>
58 <td> Has to perform: <br>- 1 file open request </td>
61 <td> Memory Usage </td>
64 <br>- 1 Dali::Image objects
65 <br>- 1 OpenGL Textures
69 <td>Rendering Performance </td>
72 <br>- 1 glBindTexture calls per frame ( each OpenGL calls takes time)
73 <br>- 1 a frame = 6- calls per second @60 FPS.
78 <h2> Atlas creation guide </h2>
80 Many tools exist for creating texture atlases.<br>
81 In the following example we are using a tool called TexturePacker as DALi has an exporter script for it.
82 The exporter automatically generates a source file that has the ImageActor::PixelArea pre-defined.
85 <li> Download http://www.codeandweb.com/texturepacker </li>
86 <li> Launch TexturePacker </li>
87 <li> Go to the menu File -> Preferences</li>
88 <li> Set the "Exporter directory" to be the location of dali-toolkit/texture-atlas-exporter <br></li>
89 \image html texture-packer-preferences.jpg
91 <li> <b> Restart the application! </b></li>
92 <li> Select DALi 3D framework for new project</li>
94 \image html texture-packer-startup.jpg
96 <li><h3> Create the atlas </h3> <br></li>
97 \image html texture-packer-add-sprites.jpg <br><br>
98 <li><h3> Click publish to produce the files </h3></li><br><br>
99 \image html texture-packer-publish.jpg <br><br>
101 <h2> Using the generated cpp file </h2>
103 The generated cpp file contains 3 different ways of describing the atlas. <br>
104 Copy and paste the section that best suits your application.
105 <ul><li> Lookup table. Includes code for storing the table in a std::map for fast lookup.</li>
106 <li> constants. </li>
107 <li> JavaScript property map ( see the Dali JavaScript programming guide on how to use it).
109 <h3> Using the lookup table </h3>
111 Cut and paste the lookup table code into your application.
115 \\ The following code is automatically generated.
117 const char* ATLAS_FILE_NAME( "my_first_atlas.png" ); ///< Atlas image filename
120 * Structure to hold image name and position within the atlas.
126 unsigned int x,y,w,h;
127 Dali::BlendingMode::Type blendMode; // only enable blending if image has alpha
133 const ImageInfo ImageAtlas[]=
135 { "blocks-ball", 2, 198, 51, 51, BlendingMode::ON },
136 { "bubble-ball", 288, 74, 32, 32, BlendingMode::ON },
137 { "gallery-small-52", 2, 2, 128, 128, BlendingMode::OFF },
138 { "icon-change", 219, 2, 37, 34, BlendingMode::ON },
139 { "icon-cluster-carousel", 180, 2, 37, 34, BlendingMode::ON }
142 const ImageInfo* GetImageInfo(const char* name)
144 typedef std::map< const char*, const ImageInfo* > LookupMap;
145 static LookupMap lookup;
148 for( unsigned int i = 0; i < ATLAS_IMAGE_COUNT; ++i)
150 lookup[ ImageAtlas[i].name ] = &ImageAtlas[i];
153 LookupMap::const_iterator iter = lookup.find(name);
154 if( iter != lookup.end() )
156 return (*iter).second;
158 DALI_ASSERT_ALWAYS(0 && "image name not found in atlas");
164 To use the lookup table you can do something like this:
167 // Example function on how to get an image info from the table
169 std::string fileName = std::string( DALI_IMAGE_DIR ) + ATLAS_FILE_NAME;
170 Image imageImage = Image::New( fileName );
172 const ImageInfo* info(NULL);
174 info = GetImageInfo("blocks-ball");
177 ImageActor ballActor = ImageActor::New( imageAtlas, ImageActor::PixelArea( info->x, info->y, info->w, info->h) );
178 ballActor->SetBlendMode( info->blendMode );
180 info = GetImageInfo("bubble-ball");
183 ImageActor bubbleActor = ImageActor::New( imageAtlas, ImageActor::PixelArea( info->x, info->y, info->w, info->h) );
184 bubbleActor->SetBlendMode( info->blendMode );
188 <h3> Using the constant definitions </h3>
190 1. Cut and paste the constant definition code into your application.
192 You'll notice the code below won't compile because C++ variables can't have a dash character.<br>
193 E.g. BLOCKS-BALL, BUBBLE-BALL will cause errors. Do a search and replace for - and replace with underscores.
194 This is one reason why using lookup table which holds the filename as a string maybe easier to use.
197 \\ The following code is automatically generated.
199 const char* ATLAS_FILE_NAME( "my_first_atlas.png" );
202 * Structure to hold position / blend mode within the atlas.
207 ImageInfo(unsigned int x,unsigned int y,unsigned int w,unsigned int h, Dali::BlendingMode::Type mode)
208 :pixelArea(x,y,w,h),blendMode(mode)
210 ImageActor::PixelArea pixelArea;
211 Dali::BlendingMode::Type blendMode; // only enable blending if image has alpha
215 const ImageInfo BLOCKS-BALL( 2, 198, 51, 51 ,BlendingMode::ON );
216 const ImageInfo BUBBLE-BALL( 288, 74, 32, 32 ,BlendingMode::ON );
217 const ImageInfo GALLERY-SMALL-52( 2, 2, 128, 128 ,BlendingMode::OFF );
220 2. To use it, you can copy example code from the generated cpp file which looks
223 void LoadAtlasImages()
225 std::string fileName = std::string(DALI_IMAGE_DIR) + ATLAS_FILE_NAME;
226 Image atlasImage = Image::New( fileName );
227 ImageActor Blocksball = ImageActor::New( atlasImage, BLOCKS_BALL.pixelArea);
228 Blocksball.SetBlendMode( BLOCKS_BALL.blendMode );
230 ImageActor Bubbleball = ImageActor::New( atlasImage, BUBBLE_BALL.pixelArea);
231 Bubbleball.SetBlendMode( BUBBLE_BALL.blendMode );
238 <h2> Atlas creation tips </h2>
241 <li> Compress the atlas - \link Texture_Compression Compressing Textures \endlink <br></li>
242 <li> Avoid adding large images to the Atlas.<br>
243 E.g. don't add background images to it. Medium to large images should
244 be kept seperate. <br><br>
245 \image html atlas-size.jpg
248 <li> Try to ensure the atlas contains only images that are frequently used. <br>
249 There's no point in having images taking up GPU texture memory if they're not displayed.<br>
251 <li> Avoid very large atlases <br>
252 Try to create multiple atlases based on how they are used within your application.<br>
254 Alternatively Texture packer has the option to split atlases ( search help for Multipack)