Why 3Dc may not always be a better solution

Status
Not open for further replies.
DeanoC said:
To be pedantic, the nVIDIA example is NOT a normal map. A normal by defination always has normalised length. A normal is defined on the unit sphere.
Um, actually it is a normalized normal map in this case. This technique relies upon the base texture having texel values that are normalized to length one. The rest is a mathematical abstraction to approximate what would happen if you simply took enough samples of the base texture and averaged the lighting results, which physically results in MIP Maps not having texels normalized to length one and a resultant texture read not normalized.

Edit:
Oh, and by the way, the reason "normalized normal vector" is not redundant is simply because the word "normal" implies perpendicularity alone.
 
3Dc has a compression ratio of 2:1 compared to a 2-component 8-bit texture, although it can offer higher quality than an 8-bit texture, up to approximately 10 bits, so arguably it's about 2.5:1.
 
Scali said:
3Dc is faster than non-compressed normalmaps, no question about it, since it reduces bandwidth requirements at the cost of some extra instructions.

I know that when using two component normal maps you have to generate the third component yourself. When you say extra instructions, i assumed those are the instructions you are refering to... so the 3dc hardware doesn't automatically 'retrieve' the third component for you? :?: :?:
 
Infinisearch said:
I know that when using two component normal maps you have to generate the third component yourself. When you say extra instructions, i assumed those are the instructions you are refering to... so the 3dc hardware doesn't automatically 'retrieve' the third component for you? :?: :?:

Correct. Since you have a normalized normal, if you store x and y, you know that x^2 + y^2 + z^2 = 1.
So z^2 = 1 - x^2 - y^2.
Hence z = sqrt( 1 - x^2 - y^2 ).

You have to apply this formula in the shader to calc the z-component manually. The texld will give you the valid x and y automatically (well, not really, it's scaled and biased to 0..1 range, like regular rgba storing normals).
Just like with DXT compression, the decompression is transparent.
 
Probably not. It's not much added code, and it allows 3Dc to essentially be a generalized texture compression format that will work properly with any two-component data.
 
Chalnoth said:
Probably not. It's not much added code, and it allows 3Dc to essentially be a generalized texture compression format that will work properly with any two-component data.

Thats true but you wouldn't have to use the third component, you could just mask it.
 
True, I suppose, but then again, I guess that you'd need a new texture format if you made the simple change of allowing the hardware to do the renormalization, since it would probably break current usage of 3Dc.
 
Scali said:
However, normalmaps have an entirely different problem, which is related to mipmapping. Most people are probably familiar with the 'sparkling' of specular highlights when rough surfaces are viewed from a distance. Multisampling AA doesn't help to solve this problem.
A possible solution is to unnormalize the normals in the mipmaps.
By varying the length of the normals, the intensity of the highlights can be controlled, and sparkling can be reduced.

Hello, sorry to bother you yet again however I was just wondering if there was a particular reason why a developer who wants to use the 'unnormalized normal maps trick' and wants to use 3dc couldn't just store the 'error term' somewhere else? And if that somewhere else is a seperate texture map why can't they then compress the 'error term map' with whatever compressor would best suit the data?
 
Well, what you could do, I suppose, is make a second 3Dc texture to hold the third component (and a heightmap if you want to do parallax mapping). Then you could just perform the technique like normal, but you're losing much of the performance advantage in using 3Dc, since you both have to do two texture reads, and are storing twice as much data.

Granted, it's still a storage space win over uncompressed, and it'll still look better than using DXT5, but the two texture reads will probably mean that it'll be a performance loss.
 
Infinisearch said:
Hello, sorry to bother you yet again however I was just wondering if there was a particular reason why a developer who wants to use the 'unnormalized normal maps trick' and wants to use 3dc couldn't just store the 'error term' somewhere else? And if that somewhere else is a seperate texture map why can't they then compress the 'error term map' with whatever compressor would best suit the data?

As Chalnoth already more or less indicates, it's a matter of performance vs quality. DXT5 is the most compact way we know to store this information. Using no compression is the way that gives the best quality. 3Dc would fall somewhere in between. You may be able to get better quality than DXT5, but the cost is higher. Depending on the situation, you could even choose to go for no compression. If you are not bandwidth-limited, that may be a faster solution than sampling 2 3Dc maps.
 
Chalnoth said:
Well, what you could do, I suppose, is make a second 3Dc texture to hold the third component (and a heightmap if you want to do parallax mapping). Then you could just perform the technique like normal, but you're losing much of the performance advantage in using 3Dc, since you both have to do two texture reads, and are storing twice as much data.

Granted, it's still a storage space win over uncompressed, and it'll still look better than using DXT5, but the two texture reads will probably mean that it'll be a performance loss.

You can store a spare channel along with any texture that doesn't have alpha.
Eg. if your diffuse texture has no alpha and would be stored in DXT1 you can put the extra channel in the alpha and use DXT5. That's only a 4 bits/pixel cost.

Or you could use 3Dc and have the other component store the displacement for offset mapping.

I think it is time for people to realize that a material has many source channels that doesn't neccessarily map 1:1 to the actual textures stored in memory.
 
Scali said:
Using no compression is the way that gives the best quality. 3Dc would fall somewhere in between.
Note that depending on the application and the implementation 3Dc can be higher quality than 8-bit maps.
 
Hyp-X said:
You can store a spare channel along with any texture that doesn't have alpha.
Eg. if your diffuse texture has no alpha and would be stored in DXT1 you can put the extra channel in the alpha and use DXT5. That's only a 4 bits/pixel cost.
True, but then you'd need to expect that every surface will have the same texture that has this property. Depending upon how the game is programmed, and how shaders for the game are built, this may not be a reasonable expectation.

Or you could use 3Dc and have the other component store the displacement for offset mapping.
Right, but, once again, this is still two texture reads instead of just one for a four-component texture format.
 
Chalnoth said:
Well, what you could do, I suppose, is make a second 3Dc texture to hold the third component (and a heightmap if you want to do parallax mapping). Then you could just perform the technique like normal, but you're losing much of the performance advantage in using 3Dc, since you both have to do two texture reads, and are storing twice as much data.

Granted, it's still a storage space win over uncompressed, and it'll still look better than using DXT5, but the two texture reads will probably mean that it'll be a performance loss.
Some interesting points have been brought up in this discussion - let me give my take on things here -

1. DXT5 using three components is not really close to 3DC in quality of normal representation, so comparing them directly as if they were is rather unfair. Although using DXT5 in a two-component mode can usually give a reasonable approximation of 3DC, storing the third component makes the compression quality significantly worse because you have to compress a two-component colour block, with those two components not necessarily being well correlated - this can cause significant compression artifacts in some cases. The compression quality of 3-component DXT5 is moderate, and usable in many cases, but not really comparable to 3DC.

2. If you want to use parallax mapping or a related technique with DXT5 compression then you need to use two textures anyway - you can't use the spare component to store the height for the same reason as above - you would now have a 3-component colour block with even worse correlation and therefore break your compression quality further. As a result you still need two texture reads if you want to do parallax mapping and use DXT5 normal-map compression. If you want to do parallax mapping with 3DC then you get the same storage cost, but much higher quality - you can either store the third component of the normal map in the spare 3DC channel of the second texture (if you want to do denormalisation), or use it for some other surface characteristic like shininess if denormalisation is not desired.

Further to this the two texture reads probably have no major performance impact in applications using reasonably complex pixel shaders, where the ratio of ALU ops to texture reads is usually reasonably high. The achieved compression rate, although now relatively modest at 2:1 compared to uncompressed source data, is still highly significant (reducing 256MB of textures to 128MB is not to be sneezed at) - you will almost certainly find that the gains from reducing the required texture bandwidth almost certainly outweighs any losses from requiring two texture reads.

- Andy.
 
Of course, one other thing to keep in mind is that the interpolation inherent in any of the compression formats available may do screwy things with this MIP mapping technique anyway, so it may be undesireable to use any current compression.
 
Some more questions based on the last few posts:

In the same way 3DC seems to be more suited to normal maps than DXT5 is DXT compression or 3DC suitable for height maps, gloss maps or storing error terms in the first place?

Chalnoth said:
Of course, one other thing to keep in mind is that the interpolation inherent in any of the compression formats available may do screwy things with this MIP mapping technique anyway, so it may be undesireable to use any current compression.

Can't you manually make mip-map levels? And on a related note, Is there any other possible way to get rid of the sparkly problem mentioned in the OP besides the method described in the nvidia paper?
 
Use 2 coordinate polar system and you shouldn't have the aliasing issues (at least not as bad as any system using Cartesian coordinates). The issue has to do with bilinear and trilinear filtering is not a method to interpolate between vectors. Its much better to use a polar coordinate system and interpolate theta, phi, and magnitude.

For items like normal mapping doubt it would be a huge improvement but for things like scientific displaying of vector data (say flow of some liquid/air around an object) it's much more accurate to use polar coordinates for interpolating the sparse data when creating streamlines or advecating particles through them. There is also other methods that I dont know of that are supposed to be better than polar coordinates but I've not checked them out. For my stuff in the past polar coordinates has been good enough.

Also polar coordinates can be easily used with 3DC if desired and will require only 7 lines of code or so for the calculation of getting your more often used normal vector (so not cheap at the moment but for the future should be no issue when our video cards laugh at 200 line shader programs)
 
Infinisearch said:
In the same way 3DC seems to be more suited to normal maps than DXT5 is DXT compression or 3DC suitable for height maps, gloss maps or storing error terms in the first place?

DXT is pretty much based on the idea that colours don't change all that much in a 4x4 block, and they can be approximated by storing two RGB values and doing simple interpolation for all 16 pixels. This basically means that if you want to store multiple channels, they would have to be similar in some way, else the interpolation will be very inaccurate.
It also means that if values differ greatly within a 4x4 block, there will be considerable compression artifacts.

3Dc compresses the components separately, so you can easily use 2 completely different channels in the same texture.
The idea of the compression is similar to DXT, and it also uses 4x4 blocks.

Can't you manually make mip-map levels?

Yes, this is possible.

And on a related note, Is there any other possible way to get rid of the sparkly problem mentioned in the OP besides the method described in the nvidia paper?

You can ofcourse use supersampling instead, but it's a lot slower.
And there are variations on NVIDIA's method...
NVIDIA's paper also has some references to earlier work on reducing normalmapping aliasing. You might want to check those out. None of them are particularly suited for realtime-usage though.
 
Status
Not open for further replies.
Back
Top