Home Technical Talk

DDS photoshop plugin explained

polycounter lvl 19
Offline / Send Message
poopinmymouth polycounter lvl 19
I got tired of not knowing what all the different options in the Nvidia DDS Photoshop export dialog box did, so I sat down and tried them all. I also did some online research for the types that weren't obvious. This isn't complete, as I'm sure I'll get some feedback on things I got wrong, or omitted, so please let me know about any parts that need changing. When it's finalized I'll add a PDF link so it can be kept handy.

http://www.poopinmymouth.com/tutorial/dds_types.html

poop.gif

Replies

  • Jesse Moody
    Offline / Send Message
    Jesse Moody polycounter lvl 18
    Thanks poops. I had something a while back that explained the differences between the files. I can't remember where I got it though
  • jgarland
    Thanks, Poop. That's a great quick overview of the different filetypes. I think I'd otherwise be lost. I certainly won't be as apprehensive about the different settings. smile.gif
  • IronHawk
    Offline / Send Message
    IronHawk polycounter lvl 10
    Great read poop. Thanks for taking the time to put this together.
  • Black_Dog
    Offline / Send Message
    Black_Dog polycounter lvl 17
    [ QUOTE ]
    This is the uncompressed 32-bit targa (8 bit alpha) equivalent DDS format. However it's larger than the original targa in filesize!

    [/ QUOTE ]

    DDS can contain mipmaps, so the additional size could well be those.
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Nice one, cheers Ben!
  • Daz
    Offline / Send Message
    Daz polycounter lvl 18
    Pretty new to the .dds format so this is a big help, many thanks Poop.
  • Jaco
    Offline / Send Message
    Jaco polycounter lvl 17
    Thanks, very helpful!
  • killingpeople
    Offline / Send Message
    killingpeople polycounter lvl 18
    your 8:8:8 sextion,
    "8:8:8 has no alpha."
    "8888.jpg" shows an alpha being used and labled as "8:8:8:8 (8-bit alpha)"
  • poopinmymouth
    Offline / Send Message
    poopinmymouth polycounter lvl 19
    [ QUOTE ]
    your 8:8:8 sextion,
    "8:8:8 has no alpha."
    "8888.jpg" shows an alpha being used and labled as "8:8:8:8 (8-bit alpha)"

    [/ QUOTE ]

    Whoops, I'll fix that, since it didn't have it, I didn't paste it into the photoshop file. Thanks for that.

    [ QUOTE ]
    [ QUOTE ]
    This is the uncompressed 32-bit targa (8 bit alpha) equivalent DDS format. However it's larger than the original targa in filesize!

    [/ QUOTE ]

    DDS can contain mipmaps, so the additional size could well be those.

    [/ QUOTE ]

    Hah! I forgot all about the mips, let me redo it without mips to give an accurate comparison.

    poop.gif
  • thnom
    Offline / Send Message
    thnom polycounter lvl 18
    The Palette options don't crash Photoshop if you actually Palette the image (make it 256 colours yourself)
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Nice Job, Ben!

    I think your DXT5_NM info might be a tad off. In my experience, you leave the green channel where it is and you put the red channel in the alpha channel. That's because the compression places more bits in the green channel than the red or blue channels. As far as I know, this mode is exactly like DXT5 with alpha except it does the channel rearranging for you.

    This info could be wrong. I haven't looked it up. But that's just my gut feeling.
  • poopinmymouth
    Offline / Send Message
    poopinmymouth polycounter lvl 19
    [ QUOTE ]
    The Palette options don't crash Photoshop if you actually Palette the image (make it 256 colours yourself)

    [/ QUOTE ]

    Should have tried that! I'll add those this weekend, thanks Thnom.

    [ QUOTE ]
    Nice Job, Ben!

    I think your DXT5_NM info might be a tad off. In my experience, you leave the green channel where it is and you put the red channel in the alpha channel. That's because the compression places more bits in the green channel than the red or blue channels. As far as I know, this mode is exactly like DXT5 with alpha except it does the channel rearranging for you.

    This info could be wrong. I haven't looked it up. But that's just my gut feeling.

    [/ QUOTE ]

    Sounds more right than my guess, I'll edit that part too, thanks Ben.

    poop.gif
  • Jay Evans
    Offline / Send Message
    Jay Evans polycounter lvl 18
    not that you want any more reading.. but here is another take on the same stuff. Pretty wordy but still good info.
    http://riccardlinde.com/gBxttut.html
  • malcolm
    Offline / Send Message
    malcolm polycount sponsor
    Yeah I wrote all this same shit down too when I was writing an article for ea knowledge. Poop I'm not sure where you're getting your file sizes from but dxt3 is much smaller than dxt5. Also dxt1, dxt3, and dxt5 all offer the same colour compression. So unless you are flicking some switches you're not going to get better results in the colour channel between the 3. There is also a ghetto version of dxt1 which stores the alpha channel in the colour map as black pixels, it's pretty much useless though because you see the black edges bleed in game where the transparent pixels are. I think you should use different screenshots, large photographic textures compress very well and do not show the artifacting dxt causes. Use a 128x128 texture with lots of gradients to show how the compression alters the image. Also an interesting note that our cg sup discovered which hurt us badly was nvidia dxt does not compress well if you give it dark images, it bands to shit. Don't ever give dxt a dark light map it will destroy it, he had to implement technology to fix this problem. I've tried the ati dxt as well compressinator it offers slightly different results but nothing better or worse.
    tgavsdxtthumb_01.jpg
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Yeah, very dark and desaturated colours into DXT1 and DXT5 result in patches of more saturated red/green, generally I always make dark colours more saturated now to avoid that happening as much.
  • Whargoul
    Offline / Send Message
    Whargoul polycounter lvl 18
    Malcolm - I think DXT3 & 5 are both the same file size, it's just the way they handle alpha is different (same # of bits stored though). I always use 5, 3 is complete shite unless your alpha has no gradients (all colour zones or something).
  • poopinmymouth
    Offline / Send Message
    poopinmymouth polycounter lvl 19
    I double checked to be sure, both doing a test in photoshop and looking it up online, and I'm 99.999% sure that DXT3 and DXT5 are identical in filesize. It's just the difference in the alpha.

    Yeah the photographic texture didn't work so well, if I get some time I'm going to redo it with a part normal map, part gradient image that you can blow way up to examine as a hyperlink.

    The rest of the fixes have been updated.

    poop.gif
  • Eric Chadwick
    Nice thread Ben. I always wanted something like this. Glad to see you putting it together.

    I found dxt3 better when the alpha had islands of black and white that were antialiased, like interface or font bitmaps. If I had gradients bigger than 4 pixels across, then dxt5 was always better. Here's a poor example.

    Nvidia is unlikely to update their PS plugin, until or unless they make a Cuda version. The zip on my site has a bunch more fixes though, have you tried it? I think it's v7.81 or something.
  • malcolm
    Offline / Send Message
    malcolm polycount sponsor
    Sorry Ben my bad you are correct dxt3 and 5 are the same file size! Not sure why I remember this being different? Yeah some normal map examples would be perfect as they are they hardest thing to compress I would imagine.
  • Eric Chadwick
    Oops, my zip is v8.21 beta. Feel free to host it if you like, or you can point people there, whatever. You can strip out the other files in the zip too. I asked Nvidia several times about my sharing it here and on my site, they've never responded. Maybe it's just me though.

    Taking a look at it again, the 3D Preview has a nice comparison feature built in, shows up to eight formats side-by-side incl. uncompressed. Pretty cool, might help out. If you hit Preview Settings, you can also toggle a "difference" view.

    There are also more formats to convert to in that version, here's a screengrab. I asked the guy at Nvidia to re-order them so it was easier for me to make sense of it all. Too bad Doug left, kinda pisses me off they aren't updating this thing, but I'd guess the power users are all using the command-line instead.
  • Eric Chadwick
    I went thru the programmer email-list threads I've saved about DXT. I know it's a lot of reading, but there's some really good info, might help your doc. Also answers some of the questions that have been asked...


    "Most textures used in games seem to fall in roughly four
    categories:
    1. Textures with a lot of relatively high-frequency content everywhere.
    Those are quite common and pretty well-behaved under DXT compression
    (i.e. they tend to come out quite nicely no matter how smart or
    stupid your DXT compressor is).
    2. Textures with mostly mid-frequency content and some localized
    high-frequency features. (Like textures for mechanical parts, fonts,
    and the like). They are also relatively common. Blocks with high-freq
    features come out pretty jaggy with all DXT compressors - no way to
    get nice edge antialiasing when you only have 4 shade levels per
    block smile.gif. The rest is usually OK.
    3. Textures with mostly low-frequency content. (Gradients, skies and the
    like). This is where differences between DXT compressors are most
    apparent, but in my opinion, even the best DXT compressors look
    pretty bad on this kind of textures (i.e. tend to produce a lot of
    banding no matter what).
    4. "Special-case" textures, i.e. those not intended to be viewed alone,
    but used as intermediate inputs in some shading calculation - this
    ranges from lightmaps over normalmaps to LUTs for pixel shaders.
    What they have in common is that they usually don't work well with
    stock DXT compressors and need some extra work to come out nicely
    (like considering DXT block boundaries in lightmap packing etc).
    "

    RE: #3...
    "There a good feature in [ATI's] TheCompressionator that can help in some hard cases.
    If you get banding in a blue sky, just increase the blue weighting in the options and the gradient quality should improve."


    RE: DXT1 vs. DXT3 vs. DXT5...
    "RGB accuracy of all the DXTn variants is identical."
    "You probably don't want to ever use DXT1 for stuff with alpha channels. The problem is that even if your original art only has full or nothing alpha, as soon as you generate mipmap levels, you need partial alpha or it starts to look really ugly. Unless you're using premultiplied alpha-blending (which you should, of course), this can cause problems with bilinear filtering."
    "DXT3 gives you 4-bit alpha, meaning 16 values evenly spaced between 0 and 1 for your entire image. DXT5 gives you 3-bit alpha that is interpolated between 2 grayscale endpoints, meaning you get 8 values linearly spaced differently for every 4x4 block of pixels in your image. In general, DXT5 provides better results than DXT3 because most 4x4 blocks of alpha don't cover the full 0-1 range. However, for textures that do cover that range well, DXT3 would be better quality."


    RE: Must dxt textures be powers of two?
    "DXTn [DXT1 thru DXT5] texture dimensions must be multiples of 4. This is because the compressed format breaks textures up into fixed 4x4 blocks.
    If the texture is being mip-mapped, then it must be a power of 2 in size. This is true whether it is DXTn compressed or not.
    So a DXTn texture can be 36x36 if it not using mip-mapping, but will fail if mip-mapping for that texture is also enabled."


    "ATI 3Dc format (ATI2N) is similar to DXT5 in that ATI 3Dc is like having two DXT5 compressed alpha channels." More about 3Dc here:
    http://ati.amd.com/developer/samples/dx9/3dcnormalcompression.html


    RE: Using DXT1 for normal map compression, using the R and G channels for X and Y...
    "if you're still targeting DX8 level hardware i'd strongly discourage using DXT1 as there's a NVIDIA hardware bug that produces wrong texels on GF3 and GF4 class cards (including the one in a certain console wink.gif when using DXT1. The error is small enough not to affect texture maps visibly, but can lead to a screen full of garbage pixels when you're compressing normal maps with DXT1 and use them for specular or reflection mapping.
    "DXT1 is expanded to 565 in the texture cache (dithered on the GF4, not dithered on DX3) rather than the 8888 it should have been expanded to. Quantising normal maps to 565, even with dithering, is going to cause some outrageous errors in lighting.


    RE: comparing different DXT compressors (ATI, Nvidia, Microsoft)...
    "After looking at all 3 tools here is what I concluded:
    - nVidia and ATI algorithm is more pleasing as they dont over dither compared to the D3DX october 2005 SDK release.
    - Older D3DX Microsoft implementation are really bad. I'm guessing the algorithm was recently revised ?
    - The ATI library is very clean, small and simple. (one header + one 65k .lib)
    - ATI and nVidia algorithm are so close to each other that I could not find an image that looked better (even zoomed 400%) using one or the other."


    RE: How both the DXT5n format (and the Nvidia DXT compressor) work...
    "A = norm.x
    G = norm.y
    R and B are unused so they are set to norm.y so that the compressor does not try to compress two colors, only the green channel.
    The compressor has to take into account R G and B for compression. The values are not independent, adding unrelated R and B values will compromise the G channel.
    Because you have only two endpoints in the DXT compression scheme, the compression algorithm attempt to fit a 3d line to the all 16 colors in a block. Treating the r g b values as 3d points.
    ...
    You are allowed two endpoints (and only two) that represent two palette entry colors. This is for every 4x4 block of texels.
    Then you can interpolate from these two colors. To compress well, you need to fit a line through your colors and only store the two endpoints.
    The index values tell you where along the line you can sample from for a grand total of 3 or 4 colors for the 16 texel block."
  • Eric Chadwick
    I didn't know what unsigned vs. signed means, so I asked one of the programmers here. Here's how he explained it to me. I added emphasis to highlight the meat of the issue...

    "Actually, we do use signed textures for normal maps, although we don’t support loading them at the moment. The unsigned normal maps are converted. The 8-bits-per-component signed normal maps we use store numbers in the range [-128, 127] whereas the equivalent unsigned normal map stores numbers in the range [0, 255]. The advantage of the signed normal map becomes apparent if we consider how the normal maps are sampled in the pixel shader.

    Values from a signed texture are mapped so that [-127, 127]->[-1, 1] when sampled in the pixel shader. Notice that -128 is not included in the source range. It appears that it is clamped to -127. Values from an unsigned texture are mapped so that [0, 255]->[0, 1]. The unsigned values must be scaled by 2 and biased by -1 in the pixel shader to move them into [-1, 1].

    The problem is that there is no way to represent 0 in the [-1, 1] range in an unsigned texture. If we try to transform 0 back from [-1, 1] into [0, 255] we get ( 0 + 1 ) / 2 * 255 = 127.5, which is not an integer. Therefore when it is stored in the texture it is rounded to 128, and when we map that back to [-1, 1] we get 128 / 255 * 2 – 1 = 0.003921568627450980392156862745098. With the signed texture, on the other hand, 0 represents 0 in both ranges.

    That means only a signed texture can represent a normal with no bend in the pixel shader, and that’s why we use it.

    We convert unsigned textures to signed by subtracting 128 from all the components, which maps 1 to -127, 128 to 0 and 255 to 127.
    "
  • Whargoul
    Offline / Send Message
    Whargoul polycounter lvl 18
    I'd call being off 0.3 degrees close enough to flat for me. It would be constant at least.

    And I prefer the DXn format for normal maps rather than the DXT5 method. It uses two channels, and has the same file size as the DXT5 map. So, same bits but packed into 2 channels = more accuracy for the same cost. And the hardware should return the 3rd channel (normalized) for you!
  • Eric Chadwick
    Yeah, I don't really understand why its an issue. Anyhow as soon as math starts appearing, my head starts swimming.

    DXn = 3Dc? Or something different?
  • PixelRambo
    [ QUOTE ]
    I didn't know what unsigned vs. signed means, so I asked one of the programmers here. Here's how he explained it to me. I added emphasis to highlight the meat of the issue...

    "Actually, we do use signed textures for normal maps, although we don’t support loading them at the moment. The unsigned normal maps are converted. The 8-bits-per-component signed normal maps we use store numbers in the range [-128, 127] whereas the equivalent unsigned normal map stores numbers in the range [0, 255]. The advantage of the signed normal map becomes apparent if we consider how the normal maps are sampled in the pixel shader.

    Values from a signed texture are mapped so that [-127, 127]->[-1, 1] when sampled in the pixel shader. Notice that -128 is not included in the source range. It appears that it is clamped to -127. Values from an unsigned texture are mapped so that [0, 255]->[0, 1]. The unsigned values must be scaled by 2 and biased by -1 in the pixel shader to move them into [-1, 1].

    The problem is that there is no way to represent 0 in the [-1, 1] range in an unsigned texture. If we try to transform 0 back from [-1, 1] into [0, 255] we get ( 0 + 1 ) / 2 * 255 = 127.5, which is not an integer. Therefore when it is stored in the texture it is rounded to 128, and when we map that back to [-1, 1] we get 128 / 255 * 2 – 1 = 0.003921568627450980392156862745098. With the signed texture, on the other hand, 0 represents 0 in both ranges.

    That means only a signed texture can represent a normal with no bend in the pixel shader, and that’s why we use it.

    We convert unsigned textures to signed by subtracting 128 from all the components, which maps 1 to -127, 128 to 0 and 255 to 127.
    "

    [/ QUOTE ]

    In English signed and unsigned means that you use a single bit that is a boolean value for whether the current number(integer) is a minus value or not.
    By using unsigned you can get higher values but sacrifice the negative spectrum.

    This is something that is mostly a performance issue. If you need that extra positive range and have absolutely no use for the negative range you use unsigned. You use it [unsigned integers] vigorously in C and C++ but I have had bad experiences with it in C# as various conversions don't handle them very well, and are mostly used when you're interfacing with legacy code or the Windows XP api(such as mouse messages for DirectX and OpenGL).
  • Eric Chadwick
    Eeeek, math!!!

    As an artist, I usually need it explained in visual terms. I think that's the whole reason poopinmymouth started his doc. MSDN's DXTn pages are gibberish to most game artists like me.

    I think we'll find some of the options in the DDS plugin are probably way beyond what a game artist needs to understand in their daily use. Signed/unsigned is likely one of those.
  • Whargoul
    Offline / Send Message
    Whargoul polycounter lvl 18
    DXn is one a the new formats used on the 360. I think it's 2 8-bit channels, for the red/green. Blue is obviously thrown out and recalculated. It is by far the most accurate (nearly the same as the original .tga's).
  • Rick Stirling
  • Eric Chadwick
    Good one.

    Poop, when you get a chance to work on this some more, I found some good image examples to build off of. UDN chose images that are both typical and atypical, to highlight exactly what's going on with the compression. I thought they did a great job. Also shows their "bright" format, same basic thing as DDS' 8bit paletted RGB.
    http://udn.epicgames.com/pub/Content/TextureComparison

    Though I think they focus a bit much on the Nvidia GF3/GF4 DXT1 problem, which makes it seem like DXT1 is always bad. Not so true anymore, since Nvidia fixed it post-Geforce4.

    Which console uses GF4 class hardware? Was it the original Xbox?
  • Eric Chadwick
    Yes it was Xbox.

    Looked up DXn, found this info. Thanks for the heads up Whargoul.

    "
    Xbox (NV2A) supports DXT1, DXT2/DXT3, and DXT4/DXT5 formats. That's S3TC.
    Xbox 360 (Xenos) adds some new compressed texture formats.

    DXT3A/DXT5A - single component, 4 bits precision
    DXN - two components, 8 bits precision per component
    CTX1 - two components, 4 bits precision per component

    DXN and CTX1 are useful for normal map compression (3Dc).

    Also, Xbox 360 DXT1 decompression is 32-bit, while Xbox DXT1 is 16-bit.
    "
    http://forum.pcvsconsole.com/viewthread.php?tid=19951
  • poopinmymouth
    Offline / Send Message
    poopinmymouth polycounter lvl 19
    I really am going to revisit this, I just have to find an evening this week to devote to it. Thanks a ton Eric/whargoul/malcolm/pixelrambo. I'll be incorporating this new info and making a better example image.

    poop.gif
  • Eric Chadwick
    Looks like Nvidia just updated their installer to 8.23, though the only thing they added was their new logo. smile.gif

    http://developer.nvidia.com/object/photoshop_dds_plugins.html
  • Eric Chadwick
    Hey, wondering if you still have the fuel for working on this.

    I added some info in a thread on the CrazyBump forum...


    DXT5nm = y in green, x in alpha, red & blue empty.

    When creating a DDS normalmap, the mip generation method is important. Nvidia has a great pdf called Let's Get Small that talks about the best way to make normalmap mips (grayscale->mips->normals, not grayscale->normals->mips). Makes a difference.

    Not good to use DXT1 for normalmaps because DXT5nm takes advantage of how DXT compresses the alpha separately from RGB, they don't influence each other the way the RGB channels do. DXT1 only has binary alpha.

    DXT5nm is great because the normalmap stays compressed on the card. You get some artifacts from the compression, but mostly in the Y/green channel, less in the X/alpha channel.

    3Dc looks pretty good, less artifacts than DXT5nm, but the same filesize. We don't support 3Dc at this point, otherwise I'd ask for that!


    DXT1 vs. DXT3 vs. DXT5:

    DXT1 is great if you don't have alpha. Same RGB compression method as DXT3 & DXT5, but about half the filesize.

    DXT3 is better if you have alpha with mostly solid black/white and thin antialiased edges. It creates less artifacts for rapid value changes within each 4x4 block of pixels.

    DXT5 doesn't do as well in that case, works better with slower value changes in each 4x4 block, like smooth gradients.

    I use DXT1 for color maps that don't have alpha, as long as I don't mind DXT artifacts. For critical colormaps (splash screens, etc.) I use 888 RGB dds, basically uncompressed 8bit color, plus mips if needed.


    Maybe this can nudge the Poop tutorial machine. More likely it's just a place to store info until I can pare is down into a wiki.
Sign In or Register to comment.