per-pixel normalization with register_combiners!

On GeForce3 you may not need to waste a texture unit on a normalization cube map. You can approximate normalization with the technique described below. Normalization in the combiners also allows you to do more interesting things with normal maps, like alter the direction (with a non-uniform “bump scale”), add two or more normal vectors (“detail normal map” applied to a base normal map). There are probably many others. I encourage you to play around with this technique.

The approximation comes from Scott Cutler of NVIDIA, and is:

vec3 approx_normalize(const vec3 & v)
{
  float approx_factor = (3 - <v,v> ) / 2;
  vec3 v' = v * approx_factor;
  return v';
}

Using the nvparse RC1.0 register combiners description language,
this is the setup for normalizing primary color (col0). The input is
range compressed [0,1] since vertex colors can’t be signed. The
output is not range compressed, and it’s stored back in col0.

!!RC1.0
// col0 is a range compressed vector in [0,1]
// col0 is *less* than unit length
{ // combiner0
   rgb { // normalize col0 -- step 1
     spare0 = expand(col0) . expand(col0);
   }
}
{ // combiner1
   rgb { // normalize col0 -- step 2
     discard = expand(col0);
     discard = half_bias(col0) * unsigned_invert(spare0);
     col0 = sum();
   }
}
//... further combiners use col0 as a normalized vector in [-1,1]
out.rgb = ...;
out.a = ...;

That’s pretty much it. If you do the algebra, those combiner contortions map to
the “c-like” expression above. It uses the RGB portion of 1.5 general combiners.
Not too bad, and the results are really nice. Hope you can use this.
The latest SDK has an example of this in the Earth Sphere (bump_mapping__step_2)
demo.

Rich Geldreich, an XBox game developer, independently came up with a cubic approximation to normalization within the register combiners.

John Spitzer will be presenting this and related material in an upcoming NVIDIA whitepaper on register combiners and techniques that use them.
Thanks -
Cass

[This message has been edited by cass (edited 05-23-2001).]

its a nice topic wich shows what you can get out of it… i would prefer a rsq if i had the possibility, but as long as we just can add, multiply and dotproduct around in the rc’s, its great… even if its not usefull for me as gf2user… now you have to support GL_DOTPRODUCT_TEXTURE_1D_NV in the texshader and i would buy a gf3… but without, sorry, no…

if there will be a gf3mx, i will buy, cause its cheap enough for me… we’ll see…

I just completed a “detail normalmap” demo that uses the above technique, and it’s pretty neat. We’ll probably push it out to the web soon.

I’ll post a link to some screen shots in a bit.

Ok, here’s an example of doing “detail bump mapping”. In this example, I’m using a base normalmap that’s 512x512 and a detail normalmap that’s 256x256. The base map (NVIDIA logo) covers the quad, and the detail map (bricks) is repeated many times over the quad.

At each pixel we lerp between the base normalmap normal and the detail normalmap normal, and the result is renormalized. We use that new normal to perform per-pixel lighting – both diffuse and specular – all in a single pass, and we use only 2 texture units.

Here are the images:
http://www.r3.nu/~cass/nv/detail_normalmap__far.jpg
http://www.r3.nu/~cass/nv/detail_normalmap__near.jpg

[This message has been edited by cass (edited 05-25-2001).]

damn cool!

I can’t wait to see the results of Nvidia’s Shader contest - I bet there’s plenty of great stuff like this

hm… looks pretty, yes… but cass, you dont have to win the contest yourself, ok! nvidiaguys win theyr own boards, nice, uhh

hm… have to do something nice for the contest… letz see…