BZ2 Texture Converter Readme.txt
Nathan Mates
Last Updated 2006/04/22


   NOTE: this is for BZ2 modders only. Requires 1.3pb2a or later.

   This is an offline processing tool that allows you to convert
various texture files usable by BZ2 into a a more efficient format.
Textures are compressed via the 'DXT' texture compression algorithms,
which is a much more efficient file format, storing data in a format
easily readable by modern graphics cards, and all of the mipmaps for
that picture are generated up front for both speed and quality.

   DXT compression is a slightly lossy process. Thus, modders will
want to keep their original files (.tga, .pic, .png, .bmp, .jpg)
around, and convert to .dxtbz2 as a last step. Mods can then omit the
original files, which will usually provide some good size savings.
Also, by use of a cfg file, modders can tune how their textures are
compressed/mipped/etc.

   Included with this distribution is the cfg file used to compress
BZ2's textures. This should provide a good starting point to work with
the process. Everything is run by the program DXTGen.exe, which takes
the following commandline arguments:

DXTGen.exe InputDirectory Tuning.cfg OutputDirectory

   Note that the input and output must be directories. Reading/writing
.pak files is NOT supported. But, all modders know how to deal with
those files, right? 

   Modders should look at the BZ2DXTOptions.cfg included in the same
directory as this README to get an idea of what options are available
for the tuning cfg. There are three types of textures that need
special attention:

1) 640x480 shell backdrops (search for "bane_load" for a
sample). These should have "Skip = true" in their section. Doing this
isn't 100% necessary, but DXTGen.exe will skip those files anyhow.
All textures for DXTGen.exe must be a rectangular power-of-2 input
size.  [BZ2 may require square power-of-2]

2) Textures that are to be drawn as 2D icons onscreen (search for
"cmnd_attack" for a sample). These shold have "NumMips = 1" in their
section. This prevents DXTGen from generating unused mips for that
texture. However, (see more below), those icons should have a texture
size as close to 1:1 with their onscreen size. You can either tweak
texture sizes in something like Photoshop/Paint Shop Pro/etc, or use
DXTGen's PreScaleX/Y to scale them.

3) Textures referenced in a draw_planar odf chunk (search for "ring"
for a sample). These should have "PlanarAlphaBorder = 2" in their
chunk, otherwise garbage will tend to appear onscreen when certain ATI
cards/drivers are used. This change shouldn't make any noticeable
difference to the texture on any card.


----

   A bit more on the # mipmaps issue, from a forum post I made:

   As to settings on # mips, anything that's supposed to be 2D, such
as the wireframes and icons, should have #mips = 1. That prevents the
graphics card from using a lower resolution if it's shown at a size
smaller than 1 pixel :: 1 texel (i.e. much fewer pixels onscreen than
are in the texture). However, you should still try and match up the
pixel::texel ratio to be as close as possible to 1::1.

   As an extreme example, take a wireframe icon for a unit, that's
being displayed as 32x32 pixels. If the source .tga for that is
256x256, DirectX's initial inclination is to try and find a 32x32 mip
of that .tga, and use that instead. It's certainly a LOT more
efficient for the graphics card to read a 32x32 to display into a
32x32 region, versus reading 256x256 (memory hit) and shrink it down
to 32x32 (speed hit). It's far better for the modder to create a 32x32
texture and work from there. However, if you must override DirectX's
auto-mip-selections, setting #mips to 1 will prevent it from picking a
smaller mip.

   For 3D textures, it's usually to leave #mips at the default,
32. That will generate mips of the texture down to 4x4, and leave it
up to the graphics card to figure out which mip should be used to get
a 1::1 pixel::texel range. [The vid.render.mipbias introduced recently
gives a hint as to which mips should be used.]

   However, you shouldn't try and shove HUGE textures into a small
space. For example, I believe that's what's happening in [forum post
link deleted, referring to blurry textures on a unit's preview model
in the pregame MP "choose vehicle" dialog]. If you try and shove a
256x256 or 512x512 texture into a small space in the pregame UI, such
as for a unit's preview model in MP, it will tend to pick a smaller
mip. First off, the new offline converter should help shrink things
without getting as chunky. However, it'll make a LOT of sense to try
and get everything lined up so that your textures (use a different XSI
if needed in mpvehicles.txt) are as close to 1:1 with their displayed
size. That'll prevent graphics cards from picking a shrunk one to try
and counteract the modder's mistakes.

   Also, the #mipmaps setting in GamePrefs.ini is ignored with DXT
textures. This is because it's figured that the modder did the right
thing when they converted it -- they can review the results and
reconvert if they don't like things.

----

   Technical notes: this exe is linked against the nVidia DXT
compression library, freely available from nvidia.com. This exe also
uses DevIL.dll and ILU.dll, which are unmodified from
http://openil.sourceforge.net/download.php .  OpenIL (aka DevIL) is
available under a LGPL license, so by not modifying those DLLs and
providing a download link, I believe I've fulfilled all of the
requirements placed on their use/redistribution.



   For really advanced modders, the file format of a .dxtbz2 file looks
like this. It starts with this header:

struct DXTBZ2Header
{
	int m_Sig; // = = 'GSH!';
	int m_DXTLevel; // 1..5

	// "Representative" color, used by terrain. This is essentially
	// the color the bitmap would be if mipped down to 1x1.
	unsigned char m_1x1Red;
	unsigned char m_1x1Green;
	unsigned char m_1x1Blue;
	unsigned char m_1x1Alpha; // not used initially, set to 255

	int m_NumMips; // 1..n
	int m_BaseHeight; // of first mip
	int m_BaseWidth; // of first mip
};

   That is followed by a number of chunks

struct DXTBZ2Chunk
{
    int m_ChunkSize;
    unsigned char m_Data[m_ChunkSize]; // Variable-sized, see above for true size
};
