The NVIDIA Texture Tools library (NVTT for short) is a C++ library that allows you to create textures compressed in any of the DX10 texture formats, and apply certain transformations to them such as mipmap generation, and normal map conversion.
By default NVTT is compiled as a shared library. To use it in your application you only have to link it implicitly. With gcc that's achieved using `-lnvtt`, and with Visual Studio you have to add `nvtt.lib` to the Linker -> Input -> Additional Dependencies field of the project settings. Dynamic linking the library explicitly is not recommended.
All the members of the API are in the `nvtt` namespace. Members outside of the `nvtt` namespace should not be considered public and are subject to change. If you want your code to always stay compatible with the latest release of NVTT, you should not include other headers, nor use members outside of the `nvtt` namespace.
As new features are added to NVTT, binary compatibility will always be preserved. That should allow upgrading to new versions without even having to recompile the application code.
It takes the texture defined by `InputOptions`, compresses it according to the `CompressionOptions` and outputs it according to the `OutputOptions`. These classes are documented in detail in the following sections.
The `InputOptions` class describes the images that compose the compressed texture, and several image processing operations that can be applied to them.
If the width, height or depth of the provided mipmap does not match the one expected by the layout the function returns false, otherwise it returns true.
Again, since 3D textures are not supported, the depth argument should always be set to 1.
Each of the faces of the surface is composed of a mipmap chain. You can provide each of these images explicitely with the `setMipmapData` method, but you can also disable mipmap generation or let the library compute the mipmaps procedurally. The following method provides some control over this process:
In order to output mipmaps for each of the faces of the surface, the `generateMipmaps` argument should be set to true.
If the mipmap image is not provided explicitly by the application, and generate mipmaps is enabled, then the mipmaps will be generated automatically from the previous level using a downsampling filter.
By default the entire mipmap chain is generated, but it's possible to limit the number of mimap levels generated with the `maxLevel` argument. When `maxLevel` is set to -1, this argument has no effect.
`MipmapFilter_Box` is a [http://developer.nvidia.com/object/np2_mipmapping.html polyphase box filter]. It's the default option and good choice for most cases.
`MipmapFilter_Triangle` uses a triangle filter. The kernel has a larger width and thus produces blurrier results than the box filter. It's not a polyphase filter so it's not recommended for non power of two images.
`MipmapFilter_Kaiser` is a Kaiser windowed sinc filter. That's generally considered the best choice for downsampling filters, but in order to obtain best results it may be required to tweak some of the parameters of the filter, otherwise the resulting images could suffer from ringing artifacts or the result may not be as sharp as desired. The default values of the parameters are generally safe, but it's possible to tweak them using the following method:
When evaluating the color of texels that are near the border, the Triangle and Kaiser filters usually sample outside of the texture. By default, NVTT assumes the texture wrapping mode is to mirror, because that generally looks good, but better results can be achieved by explicitly specifying the desired wrapping mode. That can be done with the following method:
By default, both the `inputGamma` and the `outputGamma` are set to 2.2. Gamma correction is only applied to the RGB channels. It's not applied to the alpha channel and it's never applied to normal maps. You can disable gamma correction by setting these values to 1.0 as follows:
If the input image is a normal map, it may require some special treatment. For example, gamma correction won't be applied, and some operations will only be active for normal maps. To indicate that the input image is a normal map the following method is used:
*TODO*: Are the mipmaps generated from the heightmap or from the normal map? from the normal map. Normal map conversion is only done to the input images.
`Quality_Fastest` will select a quick compressor that produces reasonable results in a very short amount of time. Note that this is not a real-time compressor. The code is not highly optimized, but still it's generally one order of magnitude faster than the normal CPU compression mode. If you need real-time compression you can find more resources at: [RealTimeDXTCompression].
`Quality_Production` will generally produce similar results as `Quality_Normal`, but it may double or triple the compression time to obtain minor quality improvements.
`Quality_Highest` is a brute force compressor. In some cases, depending on the size of the search space, this compressor will be extremely slow. Use this only for testing purposes, to determine how much room is left for improvement in the regular compressors.
Selecting a compression quality that's not available won't produce any error, but instead it will fall back to another compression mode. If `Quality_Production` is not available, `Quality_Normal` will be used instead, and if `Quality_Normal` is not available, `Quality_Fastest` will be used. `Quality_Highest` will never be used as a fallback.
Not all the compressors are GPU accelerated. Some formats can be compressed relatively fast, but others are much more expensive. Currently GPU acceleration is implemented only for the slowest compression modes, as shown in the following table:
High quality texture compression is a complex problem that would be very hard to solve using traditional GPGPU approaches (that is, using the graphics API, vertex, and fragment shaders). For this reason GPU compression is implemented in CUDA. Note that currently, CUDA is only available on NVIDIA !GeForce 8 series.
The GPU compressors do not provide exactly the same result as the CPU compressors. However, the difference between the two compressors is always very small and not noticeable to the eye.
In order to minimize memory allocations NVTT will call writeData as soon as compressed data is available. Some compressors output one block at a time, while others output many.