Am I right in that you can't filter normal maps without renormalizing the things in the fragment shader? Ie. filtering will mess up the vector lenght as it's a scalar and not vector based process?
That also means that normal maps need to be turned off when you get further awa as small details will create aliasing artefacts. Am I right here? How do you handle this?
Kai Backman, programmer (Blog) ShortHike - Space Station Game
I can t wait for the ideas of others forums reader about that very interesting question.
You can still use mipmaps but without filtering. And i think normals map are less usefull when meshes are far. I was thinking myself about switching to details rendered into the diffuse texture for the second mipmap, and desactivate normal maps here. I know you can put mipmap manually into a .dds, but you probably already know that.
Yes, filtering on a normal map distorts the length of the normals.
However, the normal cannot get longer, only shorter. An even weighting between two almost-opposite normals yields a blended normal with almost no length. Sometimes this can be desirable.
For example, let's say that you use a normal map for a bumpy surface. Viewed from a great distance, a single screen pixel could cover an entire "bump". If you do not filter the normal map, but instead go with a nearest-point sample, then a very slight shift in the camera could sample a normal from the other side of the bump. This causes "sparklies" since the lighting (especially the specular component) could be completely different even though the viewpoint has barely moved.
If you use filtering and renormalize the sampled normal to unit length, the sparklies are eliminated since the sampled normal hardly changes. But there are other issues; since the normal is averaged over the entire bump, it is possible to get a normal that doesn't exist anywhere on the actual bump. A sharp bevel could average out to a normal which points straight up. This can lead to specular effects that do not match the surface detail, since the specular will be computed as if the surface were flat. A surface which has no specular highlights up close might suddenly gain them when viewed from a distance.
On the other hand, if you use filtering but do not renormalize immediately, you can do interesting things with the length of the sampled normal. The length of the sampled normal tells you how dissimilar the different normals that contributed to it were. A length near zero is a sign that opposite-facing normals were averaged together. I /really/ wish I could find a paper about this, but I've lost the bookmark to it. It describes a great way to modulate the specular component based on some function of the length of the vector.
I use Minification:Linear, Magnification:Linear, MipMap Linear and in the fragment shader I normalize the normal vector retrieved from the sampler. I have experimented with this in my material editor in real time changing the filter settings and I have found those settings look best close up and at a far distance and when moving towards/away from the object. I haven't noticed any bad specular artifacts with these settings.
It only really becomes a problem if you design your art with a lot of sharp creases in the normal map. The example in the paper (which I still cannot find!) was similar to a huge Lego brick, where the near-cylindrical bumps on top were done as a normal map. It's a very extreme example, and I think that most textures would never show the problem to a noticeable degree.
Multisampling cuts down on the sparkle effect anyway, and it's something that everyone should be enabling
However this paper was really fascinating because it prebaked the normal map and specular map together by shortening the normals according to how "dull" a patch of the surface was. This allowed the same pixel shader to handle materials of any shinyness and automatically make detailed surfaces more diffuse as they receeded into the distance, just as in real life. I will keep looking for it, I'll find the PDF eventually...
Thanks everyone! I'm happy this seems like a standard problem, that means it's easier to find solutions. For now I'll just renormalize and look into that nVidia paper later .. Hmm.. I wonder how expensive renormalization is in the fragment shader..
Kai Backman, programmer (Blog) ShortHike - Space Station Game
Not very expensive, normalisation is one of the things expected to happen a lot in fragment shaders so cards are optimized for that.
You could also try using a 'normalisation cubemap' instead, but I'm not sure wether that is faster or slower on modern hardware.
I would have thought sampling a normalisation cube map would still be the cheapest, since fragment processors are still heavily optimised for texel retrieval and the normalisation cubemap is nice and small.
Very true, the main task of fragment processors is to fetch textures, but in many cases the normalisation cubemap lookup is an dependent texture lookup. Those might be bad.
Kai-Peter wrote:But the cubemap does eat one texture unit .. And I'm running out of them already .. Hmm. I have to test this and see if it's worth the effort.
Err, if you're doing normal mapping you should have one already to re-normalise the interpolated vertex normals. Admittedly you can't re-use it on less than ps_2_0 hardware, but in that case you're probably not so worried if you lose a little quality on those cards.
This article is more on compression than on filtering but I found it a good read and the DXT5 works really well for reducing storage requirements and when being filtered. A8L8 also work well too. You'll have to modify your shaders as shown in the article: http://download.nvidia.com/developer/Pa ... ession.pdf