Skip to content

Commit 79f44fa

Browse files
Create HowTo_PackageTextures_On_Android.md (#73)
* Create HowTo_PackageTextures_On_Android.md * Update HowTo_PackageTextures_On_Android.md * Update HowTo_PackageTextures_On_Android.md Add header * Update HowTo_PackageTextures_On_Android.md * add an additional sample * rework a bit * Add Screenshorts * Update HowTo_PackageTextures_On_Android.md * Update HowTo_PackageTextures_On_Android.md * Rename HowTo_PackageTextures_Androd_Folder.png to HowTo_PackageTextures_Android_Folder.png * Update HowTo_PackageTextures_On_Android.md * Update index.md * Update index.md * Update index.md * Update HowTo_PackageTextures_On_Android.md * Some corrections and formatting --------- Co-authored-by: Simon (Darkside) Jackson <[email protected]>
1 parent 2b45678 commit 79f44fa

File tree

5 files changed

+230
-0
lines changed

5 files changed

+230
-0
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
---
2+
title: How to package Textures for Android?
3+
description: Describes how to support multiple Texture Compression formats for Android.
4+
requireMSLicense: false
5+
---
6+
7+
The Android ecosystem is unique in that the hardware it runs on can be from many different manufacturers.
8+
Unlike iOS or PC, you cannot always guarantee what graphics card a user will be using. For this reason, Android needs to have some special attention when shipping your game.
9+
10+
## Texture Compression
11+
12+
As stated in "[Why use the Content Pipeline](https://docs.monogame.net/articles/getting_started/content_pipeline/why_content_pipeline.html)", you need to be aware of the performance limitations on mobile devices.
13+
The graphics cards on mobile phones do not have the same kind of capabilities as those on the PC or Consoles. They usually have less memory and less power. So you need to make use of what you have in a more efficient way.
14+
15+
One of these ways is to use Texture Compression. As stated in "[Why use the Content Pipeline](https://docs.monogame.net/articles/getting_started/content_pipeline/why_content_pipeline.html)", this allows you to fit more textures on the graphics card than you could if you just used raw `RGBA` textures.
16+
17+
## How Android deals with textures
18+
19+
Fortunately, the Android engineers recognized that supporting all of these texture compression formats was not an easy task. So, with the introduction of the `.aab` file format, they added the ability to add multiple texture format files to the package. The way the `.aab` works is that it is not the final `.apk`. The final `.apk` will be built from the `.aab` when the game is delivered to the en- user device.
20+
21+
As a result, not all of the files in the `.aab` will make it to the device. It will filter out things like `.so` files for other cpu types, and yes, texture formats.
22+
23+
The `.aab` supports the following directory suffixes for texture compression:
24+
25+
| Texture Format | Suffix |
26+
| -------------- | ------ |
27+
| PVRTC | #tcf_pvrtc |
28+
| ATC | #tcf_atc |
29+
| ASTC| #tcf_astc |
30+
| S3TC | #tcf_s3tc |
31+
| DXT1 | #tcf_dxt1 |
32+
| ETC1 | #tcf_etc1 |
33+
| ETC2 | #tcf_etc2 |
34+
35+
> [!NOTE]
36+
> see [https://developer.android.com/guide/playcore/asset-delivery/texture-compression](https://developer.android.com/guide/playcore/asset-delivery/texture-compression)
37+
38+
MonoGame has its own [TextureProcessorOutputFormat](https://docs.monogame.net/api/Microsoft.Xna.Framework.Content.Pipeline.Processors.TextureProcessorOutputFormat.html) enumeration. It describes the type of Texture Compression you use when processing an image.
39+
40+
The following table shows you how to map that to the Suffix:
41+
42+
| TextureProcessorOutputFormat | Suffix |
43+
| -------------- | ------ |
44+
| PvrCompressed | #tcf_pvrtc |
45+
| AtcCompressed | #tcf_atc |
46+
| AstcCompressed| #tcf_astc |
47+
| DxtCompressed | #tcf_s3tc |
48+
| Etc1Compressed | #tcf_etc1 |
49+
| EtcCompressed | #tcf_etc2 |
50+
| Compressed or Color | No Suffix |
51+
52+
## Adding Texture Compression Suffixes
53+
54+
With the latest MonoGame we added support for being able to have one texture with multiple outputs. Previously it would only build the last item, but this has been fixed.
55+
56+
In the Content Editor:
57+
58+
1. Add a new folder for your desired Suffix. This is usually in the form of `Textures<suffix>`.
59+
![Add Folder](./images/HowTo_PackageTextures_Android_Add.png)
60+
2. Right-click on the new folder and Add an Existing File.
61+
3. Select the file you want to use for this Suffix and Add it
62+
![Folder Structure](./images/HowTo_PackageTextures_Android_Folder.png)
63+
4. In the Properties of the new file change the TextureFormat to the one that matches the desired Suffix.
64+
![Change Properties](./images/HowTo_PackageTextures_AndroidATSC.png)
65+
66+
In the `.mgcb` file directly you can do the following
67+
68+
```sh
69+
/processorParam:TextureFormat=PvrCompressed
70+
/build:Textures/LogoOnly_64px.png;Textures#tcf_pvrtc/LogoOnly_64px
71+
```
72+
73+
As documented the [/build](https://docs.monogame.net/articles/getting_started/tools/mgcb.html#build-content-file) command takes an optional `<destination_filepath>` after the `<content_filepath>`. We can use this to provide the target folder for our output.
74+
So in the example above, the `LogoOnly_64px.png` file will be compressed using `PvrCompressed` and then the output will end up in `Textures#tcf_pvrtc`.
75+
76+
> [!Important]
77+
> Some texture formats have specific size requirements. For example PVRTC Compressed Textures MUST be a Power of 2 and Square (e.g 1024x1024).
78+
> Many others need to be Power of 2. It is recommended that you make all your textures Power of 2 just to make life easier.
79+
80+
## Supporting Multiple Texture Compression Types
81+
82+
To allow your game to work on as many devices as possible we need to support multiple compression formats. Now that we know how to specify a specific texture compression format for a texture, how do we go about supporting multiple formats? It is really quite simple. We can duplicate the entry for each texture and specify a different `/processorParam:TextureFormat` and output path. For example, the following code is how we would build both `pcrtc` and `dxt` formats.
83+
84+
```sh
85+
#begin Textures/LogoOnly_64px.png for PvrCompressed
86+
/importer:TextureImporter
87+
/processor:TextureProcessor
88+
/processorParam:TextureFormat=PvrCompressed
89+
/build:Textures/LogoOnly_64px.png;Textures#tcf_pvrtc/LogoOnly_64px
90+
91+
#begin Textures/LogoOnly_64px.png for DxtCompressed
92+
/importer:TextureImporter
93+
/processor:TextureProcessor
94+
/processorParam:TextureFormat=DxtCompressed
95+
/build:Textures/LogoOnly_64px.png;Textures#tcf_s3tc/LogoOnly_64px
96+
```
97+
98+
In the Content Editor:
99+
100+
1. Add a new folder for your desired Suffix. This is usually in the form of `Textures<suffix>`.
101+
![Add Folder](./images/HowTo_PackageTextures_Android_Add.png)
102+
2. Right click on the new folder and Add an Existing File.
103+
3. Select the file you want to use for this Suffix and Add it
104+
![Folder Structure](./images/HowTo_PackageTextures_Android_Folder.png)
105+
4. In the Properties of the new file change the TextureFormat to the one that matches the desired Suffix.
106+
![Change Properties](./images/HowTo_PackageTextures_AndroidATSC.png)
107+
108+
As you can see, supporting multiple texture compression formats is quite easy.
109+
110+
## Sample `.mgcb`
111+
112+
```sh
113+
#begin Textures/LogoOnly_64px.png
114+
/importer:TextureImporter
115+
/processor:TextureProcessor
116+
/processorParam:ColorKeyColor=255,0,255,255
117+
/processorParam:ColorKeyEnabled=True
118+
/processorParam:GenerateMipmaps=False
119+
/processorParam:PremultiplyAlpha=True
120+
/processorParam:ResizeToPowerOfTwo=True
121+
/processorParam:MakeSquare=False
122+
/processorParam:TextureFormat=PvrCompressed
123+
/build:Textures/LogoOnly_64px.png;Textures#tcf_pvrtc/LogoOnly_64px
124+
```
125+
126+
## Using Android Asset Packs
127+
128+
The Google Play Store has some fairly strict limitations on package sizes for Android apps. However there are ways to extend these limits for large games and apps, which are known as `Asset Packs`. Simply put, an `Asset Pack` is a way to organize your game content/assets into separate pieces which can be downloaded shortly after installation or dynamically at runtime. For most games using the `Install Time` packs are the best option.
129+
130+
Using them in your game can be quite straight forward. It only requires a little bit of `MSBuild` markup in your Android platform `.csproj`.
131+
132+
```xml
133+
<Target Name="_MoveContentIntoPacks" AfterTargets="IncludeContent">
134+
<ItemGroup>
135+
<AndroidAsset Update="Content/Music/**/*.*" AssetPack="MyGameAssets" />
136+
</ItemGroup>
137+
</Target>
138+
```
139+
140+
This adds an `MSBuild` target to your project which will process all the items in the `Content/Music` folder and subfolders. It will place them in an `Asset Pack` called `MyGameAssets`. You can change the name of this pack as you wish. By default, this will be an `InstallTime` pack. So it will be installed at the same time as your game is. There is no need to do anything else, the assets will be placed in the usual location and opened via `Content.Load<T>`.
141+
142+
If you are using dynamic delivery and install packs at runtime, you will need to open the content from a different location. This is out of scope for this document.
143+
If you want to learn more about how to use these features please check out the following links:
144+
145+
- [Android Asset Packs](https://learn.microsoft.com/en-us/dotnet/maui/android/asset-packs?view=net-maui-9.0)
146+
- [Android Asset Packs for .NET & .NET MAUI Android Apps](https://devblogs.microsoft.com/dotnet/android-asset-packs-in-dotnet-android/)
147+
- [Play Asset Delivery](https://developer.android.com/guide/playcore/asset-delivery)
148+
149+
## Sample `.mgcb` with Multiple Compression Formats
150+
151+
```sh
152+
#----------------------------- Global Properties ----------------------------#
153+
154+
/outputDir:bin/$(Platform)
155+
/intermediateDir:obj/$(Platform)
156+
/platform:Android
157+
/config:
158+
/profile:Reach
159+
/compress:False
160+
161+
#-------------------------------- References --------------------------------#
162+
163+
164+
#---------------------------------- Content ---------------------------------#
165+
166+
#begin ContentFont.spritefont
167+
/importer:FontDescriptionImporter
168+
/processor:FontDescriptionProcessor
169+
/processorParam:PremultiplyAlpha=True
170+
/processorParam:TextureFormat=Compressed
171+
/build:ContentFont.spritefont
172+
173+
#begin Textures/LogoOnly_64px.png
174+
/importer:TextureImporter
175+
/processor:TextureProcessor
176+
/processorParam:ColorKeyColor=255,0,255,255
177+
/processorParam:ColorKeyEnabled=True
178+
/processorParam:GenerateMipmaps=False
179+
/processorParam:PremultiplyAlpha=True
180+
/processorParam:ResizeToPowerOfTwo=True
181+
/processorParam:MakeSquare=False
182+
/processorParam:TextureFormat=Compressed
183+
/build:Textures/LogoOnly_64px.png
184+
185+
#begin Textures/LogoOnly_64px.png
186+
/importer:TextureImporter
187+
/processor:TextureProcessor
188+
/processorParam:ColorKeyColor=255,0,255,255
189+
/processorParam:ColorKeyEnabled=True
190+
/processorParam:GenerateMipmaps=False
191+
/processorParam:PremultiplyAlpha=True
192+
/processorParam:ResizeToPowerOfTwo=True
193+
/processorParam:MakeSquare=False
194+
/processorParam:TextureFormat=PvrCompressed
195+
/build:Textures/LogoOnly_64px.png;Textures#tcf_pvrtc/LogoOnly_64px
196+
197+
#begin Textures/LogoOnly_64px.png
198+
/importer:TextureImporter
199+
/processor:TextureProcessor
200+
/processorParam:ColorKeyColor=255,0,255,255
201+
/processorParam:ColorKeyEnabled=True
202+
/processorParam:GenerateMipmaps=False
203+
/processorParam:PremultiplyAlpha=True
204+
/processorParam:ResizeToPowerOfTwo=True
205+
/processorParam:MakeSquare=False
206+
/processorParam:TextureFormat=DxtCompressed
207+
/build:Textures/LogoOnly_64px.png;Textures#tcf_s3tc/LogoOnly_64px
208+
209+
#begin Textures/LogoOnly_64px.png
210+
/importer:TextureImporter
211+
/processor:TextureProcessor
212+
/processorParam:ColorKeyColor=255,0,255,255
213+
/processorParam:ColorKeyEnabled=True
214+
/processorParam:GenerateMipmaps=False
215+
/processorParam:PremultiplyAlpha=True
216+
/processorParam:ResizeToPowerOfTwo=True
217+
/processorParam:MakeSquare=False
218+
/processorParam:TextureFormat=AtscCompressed
219+
/build:Textures/LogoOnly_64px.png;Textures#tcf_atsc/LogoOnly_64px
220+
```
221+
222+
## Also see
223+
224+
[MGCB File Format](https://docs.monogame.net/articles/getting_started/tools/mgcb.html#build-content-file)
225+
[Why use the Content Pipeline](https://docs.monogame.net/articles/getting_started/content_pipeline/why_content_pipeline.html)

articles/getting_to_know/howto/content_pipeline/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ requireMSLicense: true
2525
- [How to Extend the Font Description Processor to Support Additional Characters](HowTo_ExtendFontProcessor.md)
2626

2727
Describes the process of developing a custom content processor needed to add additional characters to a [FontDescription](xref:Microsoft.Xna.Framework.Content.Pipeline.Graphics.FontDescription) object based on the text that is required by the game.
28+
29+
- [How to Package Textures on Android](HowTo_PackageTextures_On_Android.md)
30+
31+
Describes how to support multiple texture compression formats on Android.
32+

0 commit comments

Comments
 (0)