Page tree
Skip to end of metadata
Go to start of metadata

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 - is loaded instead of name.tga, if present. The TGA file will only load if the DDS is not present.

DDS files themselves are compressed - so are, like for like size, smaller than TGA but if the TGA file exists it will be a (slightly) lower quality but have improved load times - and nowadays a higher resolution DDS would look better than a smaller resolution TGA file.

DDS on Android/iOS - these work well enough there, but are not native. 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.

Some previous testing suggested these didn't work properly:

  • Small 32x32 inventory icons (need to check all other icons)
  • Water texture - TGA used for a water in a tile (tno01_water.tga, etc.)

  • Emitter - TGA used in an emitter (fxpa_smoke.tga, etc.)

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 can be used, 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:

NWN Crunch NameGIMP nameType Of DataData RatePalette SizeLine SegmentsUse For

RGB + optional 1-bit alpha0.5 byte/px41Color maps
Cutout color maps (1-bit alpha)
Normal maps, if memory is tight

RGB + 4-bit alpha1 byte/px41n/a

RGBA1 byte/px4 color + 8 alpha1 color + 1 alphaColor maps with full alpha
Packing color and mono maps together

Grayscale0.5 byte/px81Height maps
Gloss maps
Font atlases
Any grayscale image

2 × grayscale1 byte/px8 per channel1 per channelTangent-space normal maps

Texture Recommendations

You can now just use standard DDS files. The DTX3 versus DTX5 mainly differs in how it handles Alpha transparency; and

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.

Further DDS Notes

DirectDrawSurface (DDS) DXT3 Format

"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:
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 (note: All DDS files in NWN must be Square powers of 2)
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:
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 (note: All DDS files in NWN must be Square powers of 2)
04000000 = ChannelCount? RGBA
00100000 = dwPitchOrLinearSize: This is bytelength of the main map = 4096
0000803F = Alpha Premultipler endian float

Pixelformat Binary

Per Block:

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.


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:
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 (note: All DDS files in NWN must be Square powers of 2)
03000000 = ChannelCount? RGB
00080000 = dwPitchOrLinearSize: This is bytelength of the main map = 2048
0000803F = Alpha Premultipler endian float

Pixelformat Binary

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.
  • No labels