DDS files make up a large portion of the textures in the game. Some simple notes for NWN:EE below.
Main DDS Notes
DDS versus TGA
DDS files override TGA files - name.dds is loaded instead of name.tga in most cases. See Content Load Order for more information.
DDS files themselves are compressed and efficient at loading onto a GPU - so are, like for like size, smaller than TGA (even with RLE compression) but if the TGA file exists it will be a (slightly) lower quality but have improved load times and proper mipmaps - and nowadays a higher resolution DDS would look better than a smaller resolution TGA file.
Bioware tended to use TGA files for:
- GUI elements (they don't mipmap) mouse cursors, button textures, etc. - these are usually gui_ files and loadscreens
- Emitter textures (VFX like fireballs and the like) - and they turned of mipmaps in the TXI file - these are usually fxpa_ files
TGA files are also useful for all game Icons since BIoware checks for a TGA file existing to load any texture. The toolset also uses TGA files.
DDS on Android and iOS - these work well enough there, but are not native. They are converted through some engine code to KTX then loaded. More information about the native format and how it overrides/replaces DDS or TGA should come in time (for inclusion in nwsync manifests for instance).
DDS Limitations in NWN:EE
You can use DDS for all textures from what has been tested but there may be issues. Make sure to test it out.
They are also useful if you scale up the quality by sizing up images (with brand new textures or by resampling the old ones) since some cases (such as saving the game) an overlarge TGA may crash it.
These always work:
- Creature models, placeables, tileset models, VFX emitters, icons
- Note that certain older VFX - like old water - had a texture size limit of 256x256, and may be TGA only
These work with toolset caveats:
- DDS Loadscreens do not load in the toolset, but will in game
- DDS item icons will not scale properly in the toolset (bigger ones get cut off) but do in game (version 8193.37 will fix this)
Need to test these items:
- Certain icons were reported not to work but should now work in EE (Specifically smaller 1 square item icons)
DDS Support in NWN:EE
There are 3 major ways of doing DDS files in NWN:
Right now support is
- Bioware standard - this is DTX3 format, with a flipped Y axis. This is what the game ships with most of its textures.
- BC1 BC3 BC4 and BC5. Crunch calls these DXT1 DXT5 3DC, and DXTN
- NWN Crunch is recommended to use, or any DDS plugin (or GIMP etc.)
Tool Application Notes
- GIMP 2.10 has DXT compression built in.
- If you save an export as a DDS it lets you choose the compression type. No plugin required.
- You will need to flip your image vertically since OpenGL has an inverted Y.
- Symmetric recommends not using the Gimp feature due to quality issues. Instead use NWNCrunch (see below).
- NWN crunch to BioDDS does this flipping for you
- but if you export as normal DDS with crunch or NWN crunch, you should use the -unflip -yflip commands in case you’re working with sources with mixed Y orientations, such as TGA’s
BC1 - BC5
From here: http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/
| NWN Crunch Name | GIMP name | Type Of Data | Data Rate | Palette Size | Line Segments | Use For | |
|---|---|---|---|---|---|---|---|
| BC1 | RGB + optional 1-bit alpha | 0.5 byte/px | 4 | 1 | Color maps Cutout color maps (1-bit alpha) Normal maps, if memory is tight | ||
| BC2 | RGB + 4-bit alpha | 1 byte/px | 4 | 1 | n/a | ||
| BC3 | RGBA | 1 byte/px | 4 color + 8 alpha | 1 color + 1 alpha | Color maps with full alpha Packing color and mono maps together | ||
| BC4 | Grayscale | 0.5 byte/px | 8 | 1 | Height maps Gloss maps Font atlases Any grayscale image | ||
| BC5 | 2 × grayscale | 1 byte/px | 8 per channel | 1 per channel | Tangent-space normal maps |
| FOURCC | DX 10/11 Name | Description | Alpha premultiplied? | Compression ratio | Texture Type |
|---|---|---|---|---|---|
| DXT1 | BC1 | 1-bit Alpha / Opaque | Yes | 6:1 (for 24-bit source image) | Simple non-alpha |
| DXT2 | BC2 | Explicit alpha | Yes | 4:1 | Sharp alpha |
| DXT3 | BC2 | Explicit alpha | No | 4:1 | Sharp alpha |
| DXT4 | BC3 | Interpolated alpha | Yes | 4:1 | Gradient alpha |
| DXT5 | BC3 | Interpolated alpha | No | 4:1 | Gradient alpha |
| N/A | BC4 | Interpolated greyscale | N/A | 2:1 | Gradient |
| N/A | BC5 | Interpolated two-channel | N/A | 2:1 | Gradient |
Texture Recommendations
You can now just use standard DDS files. The DTX3 versus DTX5 mainly differs in how it handles Alpha transparency; https://www.fsdeveloper.com/wiki/index.php?title=DXT_compression_explained and http://wiki.polycount.com/wiki/DXThttp://wiki.polycount.com/wiki/DXT
DTX3 uses a sharp alpha channel. DTX5 uses a interpolated alpha channel, which is better for things like having alpha gradually appear at the edges of clouds or similar textures.
Both are the same file size and both are compressed in similar ways.
For the purposes of different fancy maps/PBRs you should use nwn_crunch which defaults to these settings with diffuse (base texture) having default settings
| File Type | DTX type | Other options | Notes |
|---|---|---|---|
| Diffuse | Default (seems to be DXT5A) | Not all diffuse textures require the alpha channel (ie if no transparency) | |
| Normal | -DXN | -normalize -uniformMetrics | DXN appears to be "3DC" compression |
| Specular | -DXT5A | ||
| Metallicness | -DXT5A | -minvalue 5 | |
| Roughness | -DXT5A | -DXT5A -invertcolors | |
| Glossiness | -DXT5A | ||
| Height | -DXT5A | ||
| Illumination | -DXT1 | No transparency allowed on illumination |
Further DDS Notes
DirectDrawSurface (DDS) DXT3 Format
From microsoft.com:
"The DirectDraw Surface file format (.dds) was introduced with DirectX 7 to store uncompressed and compressed (DXTn) textures. The file format supports mipmaps, cube maps, and volume maps. The DDS file format is supported by DirectXTex, DirectXTK, legacy D3DX, and other DirectX tools. Starting with Direct3D 10, DDS files support texture arrays."
Sample Texture:
dxtRBG.dds
This sample was created with Binomial's Crunch with -dxt3 encoding.
Header Binary
44445320 = DWORD (magic number) containing "DDS " (0x20534444) 7C000000 = dwSize //unused 07100A00 = dwFlags //unused 40000000 = dwHeight (Hex = 64 pixels high) 40000000 = dwWidth (Hex = 64 pixels wide. Note: All DDS files in NWN should be Square powers of 2, ie 64x32 or 32x32) 00100000 = dwPitchOrLinearSize: This is bytelength of the main map (1 pixel = 1 bytes average, HxW) = 4096) 00000000 = dwDepth //unused 07000000 = dwMipMapCount (Typically log2 of width or height, +1) //unused 00000000 = dwReserved1 //unused 00000000 = dwReserved2 00000000 = etc. 00000000 = etc... 00000000 = ... 00000000 = ... 00000000 = ... 00000000 = ... 00000000 = ... 00000000 = ... 00000000 = dwReserved11 //unused 20000000 = ?? //unused 04000000 = ChannelCount? RGBA 44585433 = ddspf PixelFormat (DXT3) //unused 00000000 = ?? //unused 00000000 = ?? //unused 00000000 = ?? //unused 00000000 = ?? //unused 00000000 = ?? //unused 08104000 = dwCaps (Surface complexity, mipmapping support) //unused 00000000 = ?? //unused 00000000 = ?? //unused 00000000 = ?? //unused 00000000 = ?? //unused
Pixelformat Binary
DDS uses block compression to encode 4x4 blocks of 16 pixels at a time using BC3 format.
DXT3 encoding as shown below in Bioware Pixelformat Binary.
There are some differences between the preferences of Bioware's encoder and other encoders.
- When faced with a block of pure color, for example, the Bioware Encoder will provide two identical colors for color 1 and 4, and then address all 16 pixels as the 1st color (00) (makes sense to me).
- Other DDS compressors, with the same block, tend to offset the 2nd endpoint by 1 bit, and with non-zero identical endpoints, choose color number 2 (01)
- It is also worth nothing that the Bioware DDS tool encodes images from the top left, instead of the bottom left, causing many source images to become "flipped" after encoding.
- TGA files with top-left encoding do not become flipped.
- Contrary to Microsoft's encoding, Bioware DDS headers write width before height.
Bioware RGBA DDS Format
The Bioware DDS format was used while the soon-to-be-industry-standard DDS format was in its formative stages. It lacks a lot of the configurations that the Direct3D Format soon adopted.
Sample Texture:
bioRGBA.dds
This sample texture has not been created by the Bioware DDS tool, but is instead a hex edited version of the crunch file to contain a suitable header, but identical pixel data.
This texture has been tested in game and renders correctly.
Header Binary
40000000 = dwWidth (Hex = 64 pixels wide) 40000000 = dwHeight (Hex = 64 pixels wide. Note: All DDS files in NWN should be Square powers of 2, ie 64x32 or 32x32) 04000000 = ChannelCount? RGBA 00100000 = dwPitchOrLinearSize: This is bytelength of the main map = 4096 0000803F = Alpha Premultipler endian float
Pixelformat Binary
Per Block:
FFFFFFFF
FFFFFFFF
These 8 bytes are used to address the alpha value of each of the 16 pixels. These values are then multiplied by the alpha float for dynamic range.
The first two bytes are used to store two alpha endpoints using 0-255 byte format, and derive an 8 color index using linear interpolation.
The following 6 bytes address a 8 value color index using 3 bits each pixel, for each of the 16 pixels.
FFFFFEFF
00000000
The first 4 bytes uses two 2 byte RGB565 (16 bit) values to designate the first and fourth color values used for indexing the color. 2nd and 3rd colors are derived from the endpoints using linear interpolation.
Each byte pair's bits are encoded as follows: GGGRRRR GGGBBBBB
The second four bytes uses sixteen 2 bit values to reference the color indices. 00, 01, 10, or 11.
Bioware RGB DDS Format
3 channel DDS files are used in NWN and created automatically by the bioware Conversion tool for 24 bit RGB TGA textures.
These DDS files have no alpha channel, and so the premultiplier is always 0000803F (1), and the LinearSize is one half byte per pixel without alpha information each block((DWORD1 x DWORD2)/2 = DWORD4)
Sample Texture:
bioRGB.dds
This sample texture has not been created by the Bioware DDS tool, but is instead a hex edited version of the crunch file to contain a suitable header, and has had it's alpha bytes removed. This texture has been tested in game and renders correctly.
Header Binary
40000000 = dwWidth (Hex = 64 pixels wide) 40000000 = dwHeight (Hex = 64 pixels wide. Note: All DDS files in NWN should be Square powers of 2, ie 64x32 or 32x32) 03000000 = ChannelCount? RGB 00080000 = dwPitchOrLinearSize: This is bytelength of the main map = 2048 0000803F = Alpha Premultipler endian float
Pixelformat Binary
FFFFFEFF
00000000
Same encoding as RGBA, but, without the alpha bytes.
Additional Notes
- I did not discuss Mipmapping in this document.
- Microsoft's documentation on the DDS format, including bitflags, can be found here.
- Helpful documentation with examples regarding Block Compression techniques can be found here.
- It is worth noting that the NWN RGB format uses 8 bytes per block.When compared "fairly" to a TGA of identical size, those 8 bytes supply texture information for 16 pixels, whereas 24-bit TGA formats consume 3 bytes per pixel.16 pixels of 24-bit RGB TGA data would require 48 bytes.
- It is also worth noting that with mipmapping, which was not discussed, (and adds 33% onto the file size), will decrease the memory required for a texture that does not require a high level of detail (distant), whereas a TGA texture will always require it's full size in memory if it is being rendered.