Texture file format
- Textures should be in PNG format.
- Textures must be power-of-two sizes (width and height must be 64, 128, 256, 512, etc; non-square sizes like 256x512 are fine too).
- Textures go in an art/textures/ directory (typically binaries/data/mods/public/art/textures/).
- Everything should then work automatically. If you care about the details or want more control over visual quality, see the rest of this page.
Photoshop's PNG exporter apparently doesn't handle alpha channels in a useful way. You can fix this by getting an old version of the SuperPNG plugin (e.g. here) and replacing the default PNG plugin, to use SuperPNG for loading and saving.
PNG files are small on disk, but they expand to 32-bit raw RGBA format in video memory when they're loaded. Reducing video memory usage is important for performance, especially on lower-end hardware. DXTC (also known as S3TC) is a way to store compressed textures in video memory, in three different formats (DXT1, DXT3, DXT5). For example, a 512x512 texture is:
- RGBA: 1024 kB
- DXT1: 128 kB
- DXT3: 256 kB
- DXT5: 256 kB
Compression allows us to increase the number or size of textures by 4x or 8x without hurting performance. The tradeoff is that the compression is lossy, causing ugly artifacts in some textures.
DXT1, DXT3 and DXT5 all compress the RGB channels in precisely the same way. The only difference is the alpha channel. The Wolfire Games blog (no relation to Wildfire Games) has some examples.
- DXT1: 1-bit alpha - good for textures that are all solid, or for UI elements with non-antialiased transparency masks. Generally unsuitable for non-solid world textures - even if the texture only needs 1-bit alpha, its mipmaps are likely to need semi-transparent pixels. Also unsuitable for player-colour alpha layers - RGB colour data is lost in areas with 0 alpha.
- DXT3: 4-bit alpha - good for textures with a wide range of alpha values in a 4x4 block of pixels; bad for smooth alpha gradients.
- DXT5: 3-bit alpha gradient - good for smooth gradients; fine for most of the cases where DXT3 is good. You should generally use this instead of DXT3.
Graphics hardware can't resize textures downwards (e.g. when zooming out) with high quality, so we pre-compute scaled versions and store them as mipmaps. Textures that are never scaled down (e.g. GUI elements) should not have mipmaps, to save space.
There are many ways to do the resizing, with effects on the sharpness of the textures when zoomed out. The NVIDIA Texture Tools page gives examples of different filtering methods and of gamma-correction.
Automatic texture conversion
Artists should save and upload textures in PNG format, and the game engine will automatically perform the mipmapping and compression and will cache the result so that it can load quickly next time. This allows us to losslessly edit the textures and tweak the conversion settings, and avoids problems with textures being manually exported with the wrong settings.
The texture conversion settings are specified in textures.xml files. For example, art/textures/ui/global/button/textures.xml might say:
<?xml version="1.0" encoding="utf-8"?> <Textures> <File pattern="*" format="dxt5" mipmap="false" alpha="transparency"/> <File pattern="button_wood.*" format="rgba"/> </Textures>
Each <File> line matches some filenames, and applies certain settings to them. If a filename matches multiple lines, later settings will override earlier settings. The textures.xml file applies to all textures in the same directory, and in all subdirectories - e.g. you can specify some common default settings in art/textures/ui/textures.xml for all UI textures, then override them with specific settings in subdirectories.
pattern="..." determines which filenames are matched by that line. The pattern can include wildcards: ? matches any character, * matches any sequence of zero or more characters.
The available settings are:
- Use uncompressed RGBA format (useful for small textures where DXTC compression artifacts are unacceptable).
- Use DXT1 format.
- Use DXT3 format (will automatically switch to DXT1 if the texture is solid).
- Use DXT5 format (will automatically switch to DXT1 if the texture is solid).
- Generate mipmaps.
- Don't generate mipmaps.
- Texture is a normal map (with XYZ coordinates in RBG (sic) components).
- Texture is not a normal map.
- Alpha channel represents transparency - the RGB of pixels with A=0 can be ignored.
- Alpha channel represents player colouring - the RGB of pixels with A=0 are still important.
- Use box filter for mipmaps (generally recommended).
- Use triangle filter for mipmaps.
- Use Kaiser filter for mipmaps.
- kaiserwidth="3.0" kaiseralpha="4.0" kaiserstretch="1.0"
- Set Kaiser filter parameters (be very careful when modifying these).
By default the behaviour is defined in TextureConverter?.cpp. As of now (2017)
- Settings settings;
- settings.format = FMT_DXT1; (DXT1 Format)
- settings.mipmap = MIP_TRUE; (Mipmaps Enabled)
- settings.normal = NORMAL_FALSE; (Normal Maps are not used)
- settings.alpha = ALPHA_NONE; (Alpha is ignored)
- settings.filter = FILTER_BOX; (Graphic filtering is using box smoothing)
- settings.kaiserWidth = 3.f;
- settings.kaiserAlpha = 4.f;
- settings.kaiserStretch = 1.f;
You can keep the game running (typically in a window) while editing textures. When you save changes to the texture, the game should automatically reload and start displaying the new file.
If you edit a settings.xml file while the game is running, it should automatically reload and reconvert all textures to use the new settings, so you can quickly experiment with the different modes.