View Full Version : short normals

07-29-2010, 05:02 AM
Does sending normals as bytes, shorts or ints, mean that you need to glEnable(GL_NORMALIZE), unless you want to play with the normal magnitudes?

Rosario Leonardi
07-29-2010, 05:24 AM
From the reference page ;)
"Byte, short, or integer arguments are converted to floating-point format with a linear mapping that maps the most positive representable integer value to 1.0 and the most negative representable integer value to -1.0."

07-29-2010, 06:08 AM
Indeed, but the conversion to floats does not necessarily preserve unit normal length, i.e. no normalization is prescribed after the conversion. Or is it?

07-29-2010, 06:40 AM
When your buffer contains fixed-point data (byte,short,int), the normalization depends on how you treat it. In other words, you should tell GL that your data is stored as fixed-point. This is specified in the 4th parameter of glVertexAttribPointer.

Rosario Leonardi
07-29-2010, 07:57 AM
It doesn't depend on the type of the data.
If you are sure that your data are nomalized don't need to enable GL_NORMALIZE.
The only difference is that with float/double the lenght of the array must be 1.0 while with byte the lenght must be 127, with short (2^16)-1 and with int (2^32)-1

07-29-2010, 08:15 AM
I think one cannot guarantee lengths such as you specified. We're dealing with integers and there's a square root involved in calculating the lengths. I suppose the normal does get close to unity length, after conversion into floats, if it was of unity length before the conversion into integers.

One of the components, say, c3^2 = 2^n - 1 - c1^2 - c2^2

After that c3 = +-sqrt(c3^2), which can produce a real number, not an integer.

Rosario Leonardi
07-29-2010, 10:34 AM
I don't understand your concern, you have a vector specified by byte (like normal on a texture), it's only a scaling factor.

If magnitude({ x, y, z}) == 1 also will be magnitude(s*{x, y, z}) / s
There are finite maths approximation problem but for most graphic application an error of 1% is not a problem.

Let's say you have { 0.0, sqrt(2)/2, sqrt(2)/2 } as a float
in integer it became { 0, 90, 90 }

0 + 90^2 + 90^2 = 16200
127^2 = 16129.. close enought

With your example... c1 = 0, c2 = 90
c3^2 = (2^n - 1)^2 - c1^2 - c2^2
c3 = 89.604... that converted to byte is 90

If you use integer you are even more precise than float (precision that get lost in the conversion).

07-29-2010, 10:54 AM
Well, then we agree, that for normals of as much unity length as possible (not close to unity), glEnable(GL_NORMALIZE) is needed, when sending integer normals to the GPU.