DDS texture conversion
Work in progress This article or section will be worked on in the upcoming hours or days. See history for the latest developments. |
about dds usage
Some of you may have noticed that we have some dds textures in the flightgear data, mostly in the scenery textures. This texture format got some interessing properties, and some drawback.
The main advantages in using mipmapped dds compressed texture instead of png (jpg, rgb etc) are:
- it's loaded direclty in ram without any modification, speeding up the loading time.
- it's a compressed format wich stay compressed in ram, saving ram space.
- it contains the mipmap, so FG don't need to make them on loading, as it does for other format.
- making a tar.gz with dds texture compress them in the gunzip stage, making the archive smaller.
- the normalmaps looks better with dds texture.
the drawbacks are:
- depending the texture size, they take more space on the hard disk.
- they are not supported by all the GPU/driver, specificaly the open source driver can't display them.
- it is a lossy format, so it's not something to be used to work on the textures, for this it's better to keep using .png in the development stage.
in the following, we will assume that the advantages are what we need: save space in ram and have a faster 3D loading, on a compatible driver/GPU, and at the cost of some disk space.
As the texture development is easier to be made in lossless format, and dds being unsupported on some system, we won't ask for a dds usage in git, but we will see how to go from .png (rgb, jpg ...) to .dds. there's a case where it's good to have dds originaly in git, it's when the mipmaps are not done by a tools, but by hand, eg for scenery textures.
tools
there are some plugins for gimp or photoshop do make dds, but here we will use tools working in command line, we don't want to open each texture by hand ;) but speed up conversion with scripts:
both are available for mac and windows, and in most linux distributions (check nvtt for the nvidia tools)
let's go
preamble: the code line here works on linux bash, for windows the syntax can be slightly different.
before converting the texture, we start by some verification:
- is there a space in the texture name? if yes it's better to rename it with a "_", and change the reference in the.ac/.xml.
- is the texture size a power of 2? if no it's better to start by resizing the texture, otherwise it will give mapping error in FG. eg for a 265x500 test.png, we can do:
mogrify -resize 256x512! test.png
if you got a 256x1 size (or any with a dimensio = 1), don't convert it to dds, there's no need and fg will give an error.
next we have 3 case; texture without alpha, texture with alpha, and normalmap. in all the case the texture need to be vertically flipped before the conversion. The dds conversion will work whith all the texture format supported by image magick, and there's a bunch of them!
Here are the steps, by texture type case:
- texture with no alpha layer: we flip the texture, ensure to have a.png (nvcompress didn'twork with .rgb as input) then convert using the -bc1 option:
convert test.rgb -flip -format png temp.png; nvcompress -bc1 temp.png test.dds; rm temp.png
- texture with alpha layer: we can see with identify alpha information:
identify -verbose test.rgb
here's the tip: if the min value for the alpha component is 255, that means the texture is full opaque, and the alpha channel is useless (except in some case the channel is used for shininess or similar)! so in this case, we remove the alpha channel and convert with the bc1 option:
convert test.rgb -flip -alpha off temp.png; nvcompress -bc1 temp.png test.dds; rm temp.png
if we need to keep the alpha channel we use the bc3 option:
convert test.rgb -flip temp.png; nvcompress -bc3 temp.png test.dds; rm temp.png
- normal maps: an extra step is needed for normal maps, the normals are displayed inversed with dds format.
So you can inverse the normal in the effect file (ex needed), or a color inversion in the texture do the job, with a bc5 option. As we have a normal map as original texture, we will tell it to ncompress, but you can use a height map instead (without the "-normal" option). something not clear here is that the normal texture in png, converted to dds, looks way better in FG: proof.
convert test-norm.rgb -flip -negate temp.png; nvcompress -bc5 -normal -tonormal temp.png test-norm.dds; rm temp.png
note that you need to have an extra line in the .eff file, to tell the normals are .dds:
<normalmap-dds type="int">1</normalmap-dds>
scripted conversion
Now is time to put the pieces together, and to use a bash script to convert fgdata parts to dds:
Aircraft folder
- Generic: this folder contains lots of pieces used by the planes, pilots, effect etc. The textures here are sometimes directly called from the Aircrafts. that's why we convert to dds, but we keep the original textures, in case they are needed for some plane referencing non dds texture from this folder.
- Instrument & Instruments-3d: considered as a plane folder, all textures converted to dds, and the original texture is removed
- plane: all the textures are converted to dds, then removed, and if there's some normal map, the normal map type is set to 1.
bugs
with rembrandt and dds textures with alpha layer, used in animation for opaque objects, the result can be strange (a fluo uniform color). the solution is to remove the alpha layer for textures used in opaque objects, so be sure to keep alpha textures only for transparent objects in the modeling stage.