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?

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.”

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?

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.

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

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.

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).

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.