PDA

View Full Version : GLSL normalize and length on zero vectors



Schnulla
08-30-2010, 09:13 AM
Hi,

I wonder how zero vectors are handled by normalize
and length (i.e. normalize(vec3(0.0, 0.0, 0.0)))?

I have some calculations that take a position and
substract another position to get a direction
vector and then normalize this vector.

What happens if both positions are nearly or really
equal thus the direction vector is zero vector?

Somehow I found nothing about this in the spec =/

Thanks!

lobbel
08-30-2010, 09:34 AM
Hello,
you may have a look at NVIDIA's GPU programming guide.
They suggest not to normalize zero-vectors. You can check the
length before normalizing the vector to avoid normalizing
zero vectors or almost zero vectors.

Here is the linkt to the programming guide

http://developer.download.nvidia.com/GPU_Programming_Guide/GPU_Programming_Guide_G80.pdf

regards,
lobbel

Schnulla
08-30-2010, 11:47 AM
Hi!

Thanks for the link. But even if I check the length
like I would do in a software normalize function
I wonder how I should handle length == 0 in the
shader... I mean for example I calculate some
direction vector for a light source or for eye
position and do some lighting calculation based
on this direction vector.

But if I am not able to calculate this direction
vector because he is just zero how should I proceed?
I guess this would require a lot of extra code
for checking and handling this edge case that
might slow down the whole shader? :(

But on the other side it could happen quite often
if my light source touches an object's triangle
or vertex.

david_f_knight
08-30-2010, 12:37 PM
You are right to be concerned about dividing by zero in shader programs. However, I think there's some subtlety to it. The OpenGL spec requires that the GL pipeline not stop in the case of division by zero, but does not specify what a GL implementation must do in that case.

You have a couple choices:

1) you could ignore the GLSL built-in normalize() function, and code a do-it-yourself normalization function that is something like this:
len = length (vector);
normal = (len == 0.0) ? vec3 (0.0, 1.0, 0.0) : vector / len;

2) assume that the GL implementor (nVidia, AMD, etc.) has done something like what is in choice (1) and live with it. The only thing is that since the spec doesn't state what should be done when the length is zero, it is up to each implementor to choose for themselves, which means inconsistent behavior from different GL implementations. Ultimately, though, that may not be a big deal because it *is* wrong to divide by zero, and the result *is* undefined, so there is *no* correct response. It's just a question of having a *consistent* response or not regardless of brand of GL implementation.

In any case, you don't want errors to compound. If the length of the unnormalized vector is zero, then you still want the normalized vector to have a length of 1.0 so that numerical problems downstream won't occur. The direction of this normalized vector is arbitrary.

Schnulla
08-30-2010, 04:20 PM
Thanks for your suggestions!

I think I'll try to somehow handle zero vectors.
Maybe if a light source sits directly on a vertex
and I get a zero vector I just say the fragment
receives maximum possible illumination from this
light source without any further dot product
calculations.