Home Technical Talk

My experiences with DDS NM Compression

polycounter lvl 19
Offline / Send Message
kodde polycounter lvl 19
Hey guys,

I was enlightened by one of my colleagues today on how DDS channel weighting works and we also discussed a few concepts on how to optimize this when it comes to normal maps.

So far my test environment has been Maya 2011 (64-bit), a simple custom CGFX shader and Photoshop CS4 with the Nvidia DDS plugin. Also tried The Compressonator, think I used it for the 3Dc texture.

I just thought I'd share my comparison with you. This is still quite new to me so please do enlighten me if I'm doing anything wrong or if I could improve on what I'm doing here.

nmcompressioncomparison.th.jpg

Replies

  • cman2k
    Options
    Offline / Send Message
    cman2k polycounter lvl 17
    This looks pretty much right to me. The only one you aren't showing which is used a fair bit is half-res with uncompressed, which is pretty common.

    Recently at my job we started supporting DXT5 with xRBG (I think?) similar to what is described here -> http://developer.nvidia.com/object/real-time-normal-map-dxt-compression.html

    This meant we had to change our shaders around and disallow alpha channels for normal maps, but the results have been dramatic in terms of quality increase.
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    cman2k wrote: »
    This meant we had to change our shaders around and disallow alpha channels for normal maps, but the results have been dramatic in terms of quality increase.

    cman2k> I can imagine. It definitely feels like something worth looking into if you haven't already for a game production.

    The Compressonator has some tweakable fields where you can weight the channels yourself. I have noticed that it does make a difference, but it seems minimal. I had expected that one could get very differing results by altering these. There has to be some parameters or restrictions when it comes to this which I have yet to grasp :P
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    I updated the pic in the original post. Included your suggestion cman2k. Works quite nice with this particular scenario.

    One thing that does not come through in my examples is that the half-res version would not have as crisp details if there were any? I mean my normal map in this case is mimicking a quite soft shape. A small crisp detail would probably seem considerably more blurred/low res.
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    New comparison today. This time with a normal map which simulating a more realistic scenario. Yesterday was just a polygon plane trying to be a quite bulgy surface. It's arguable that a difference in shape of that caliber ought to justify altering the geometry of the low poly to match the shape better.

    This time I used The Compressonator for all textures except for the 8.8.8 unsigned ones. Find it weird that the DXT5 saves today differ in size from those yesterday. They are 512x512px today as well. Only thing that differs was saving them from Photoshop yesterday and The Compressonator today.

    Also I realized that I had not been using the 3Dc method yesterday as the screenshot states. It's actually the standard known as DXT5_nm. I cannot get 3Dc DDSs to load in Maya T_T

    gimme3dc.th.jpg
  • Eric Chadwick
    Options
    Offline / Send Message
    Cool tests! I do know that Nvidia's DDS plugin has some problems reading the 3Dc it creates, and they look bad in other tools too, like XnView. I bet Nvidia is writing the file incorrectly. I would depend more on AMD to get it right.

    I don't quite understand the reasoning behind sticking X in both red and green, as you seem to be doing in the fourth example of the 2nd image.

    I thought DXT5_nm was Y in green, X in alpha, with red and blue blanked out to the same solid value as each other so they don't interfere with the compression of green. Is this what you're doing?

    I think I'm missing something. What exactly are you storing in each of the channels in your examples for xGBR, xRBG, GBxR, and xGxR?
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    Eric> Thanks :)

    Sorry if my text elements are confusing.
    I'm writing which channels i use of the RGBA space and which original input.
    So for example the DXT5_nm example i wrote "xGxR". I took the contents of the red channel and put it in the alpha channel. Then I blanked (black) the red and blue channel. I then saved this as a DXT5 with Compressonator. I altered the CGFX shader to read from these channels and reconstructed the Z input using example code from Nvidia's page on Normal map compression.

    "x" meaning blank in this case. I realize this is confusing since sometimes these are also refered to as XYZW.

    When trying the 3Dc I used Compressinator to compress and save the file. This was the output which Maya would not read. This might be on Maya's side? Not supporting 3Dc standard DDSs?
  • Eric Chadwick
    Options
    Offline / Send Message
    I don't know about Maya's 3Dc support... I haven't had the chance to use the format in production, I've just been interested in checking it out. It could be either that your card doesn't support it (unlikely these days) or that Maya's hardware shader doesn't (more likely).

    DXT5_nm written in your notation would be xRxBG I think. R and B blanked, G left alone.

    But if you're trying out combos where you blank out different channels in DXT5, then I guess that means you're not just using Green and Alpha for your Y and X vectors... you're trying to store in Red or Blue. Good to test and see for your self, but I think you're definitely going to get worse results. :)

    As I understand it, the reason DXT5_nm uses the Green channel is because Green is compressed using a slightly higher bit depth, because the compression uses 5:6:5 color (5 bits red, 6 bits green, 5 bits blue). And the Alpha channel uses 8bit compression.

    So apparently Green and Alpha are the best two channels to use, and the way the compression works, the algorithm samples all three color channels at the same time. If there's differing data in the three channels, then more errors are introduced because it has to recreate a wider sample of values. Dunno if that makes much sense. :(
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    I got this explained for me quite briefly today.

    From what I could understand you store data to be able to recreate blocks of 4x4 pixels. Within this 4x4 block only the first and second pixel has stored color values. You also store how to interpolate between these two stored color values across the 4x4 block.

    Since we perceive certain colors to differently and also due to how monitors work you weight how important the different RGB channels are in relation to each other. Somewhere around 0.3 0.6 0.1 in Compressonator if I remember correctly.

    So when creating the DDS it will analyze a 4x4 block and choose the color of the first and last pixel based on how much of it is present and the weighting between the color values.

    I could be wrong with this. Just only starting learn this now.


    I'm not sure what is the correct way to write how you store your channels to be honest. But I'm doing pretty much what you are saying. Trying out which channels work best to store normal map data. I've tried established ways and also done some mixing on my own to get some perspective :)

    I didn't know about the different color depths your are mentioning. Going to try to read up on that tomorrow. Thanks for sharing.
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    This is what the Compress window looks like in Compressonator 1.50. I'm trying to write in same manner as they do.

    compressonatorcompressi.jpg
  • Eric Chadwick
    Options
    Offline / Send Message
    Ah, weird way to identify them. Do they have docs explaining exactly what each DXT5 method means? Doesn't make much sense just looking at it. Like, what would the difference be between xGBR and RBxG?

    For DXT, this page was helpful for me...
    http://msdn.microsoft.com/en-us/library/bb694531%28VS.85%29.aspx
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    Thanks for the link.

    The documentation that comes with the install is really brief, hardly cover this topic.

    This is my take on their notation:

    Let's say that your precomputed normal map has three channels, RGB.
    A DXT5 has four channels for you to use, RGBA.

    A "xGBR" would be as follows
    R: x (nothing/black)
    G: G (you maintain the existing data)
    B: B (you maintain the existing data)
    A: R (you moved the data that was originally in the R channel to this channel)

    A "RBxG" would be as follows
    R: R (you maintain the existing data)
    G: B (you moved the data that was originally in the B channel to this channel)
    B: x (nothing/black)
    A: G (you moved the data that was originally in the G channel to this channel)

    Put in words the "xGBR" would value the R(X) the most, and the weighting when it comes to precision of the G(Y) and B(Z) would be ~0.6 and ~0.1.

    The "RBxG" would value the G(Y) the most and the weighting when it comes to precision of the R(X) and B(Z) would be ~0.3 and ~0.6.
  • kodde
    Options
    Offline / Send Message
    kodde polycounter lvl 19
    This was the link I read up on and got some sample code that I implemented in my test shader.

    http://developer.nvidia.com/object/real-time-normal-map-dxt-compression.html
  • Eric Chadwick
    Options
    Offline / Send Message
    Ah, cool, makes much more sense now, it's all relative to RGBA.

    Thanks for sharing your tests!
  • arrangemonk
    Options
    Offline / Send Message
    arrangemonk polycounter lvl 15
    there are new compression methods in dx11 wich are way better
    bc3_bc7.png
  • Eric Chadwick
    Options
    Offline / Send Message
  • Eric Chadwick
    Options
    Offline / Send Message
    Cool powerpoint, worth a look. Now I understand BC7! Thanks for the image arrangemonk.

    BC7 is still the same old block compression like DXT, but each 4x4 block can use a different mode for allocating the precision, out of 8 modes. Pretty cool idea.
    bc7_blocks.jpg
  • throttlekitty
Sign In or Register to comment.