Hob_Gadling wrote:Should probably post this here too...

If someone among the readers knows what this is all about:

https://kwasi-ich.de/blog/bytenormals/let me or integ3r know about it. We got some good stuff brewing, but we don't understand the underlying structure well enough.

OK, so, a Normal is some kind of lighting-thing I don't know much about, but I think I can explain the computer-math on the website you linked.

When pre-calculated, the normal is given as a three-dimensional vector of length 1. The Normal consists of 3 floating-point numbers that span the range from -1 to 1. That's one float for the x-dimension, 1 float for the y-dimension, and 1 float for the z-dimension, or 12 bytes in total.

That's a lot of bytes, so naively we may think to convert each float to an 8-bit integer to represent the normal and make that 3 bytes instead of 12. However, this introduces some rounding errors, as the floats are rounded towards zero when converted to ints. The normals will always be vectors pointing to the surface of a sphere of radius 1. To reduce these rounding errors, the webpage suggests making the normal-vector point to spaces inside and outside the sphere.

This is the diagram they use. We have a 2D normal (red) described with 8 bytes of floating-point data, which gives the red

*dot*. We want to convert it to 2 bytes of int data. If we multiply each float by 127 and convert to an int, we get the green

*dot*. The integer values are described by the grid-lines, and the green dot can only lie where the grid lines intersect. Here, (6,4) However, looking at the green line, we can see that when we draw the normal onto the sphere of radius 1, it's quite far from the red line. This is because of rounding.

And that's no good!

So what this website proposes is to describe the normal with points that can also be outside or inside the sphere. By making the 2 bytes point to (8,6), the yellow dot, we get a vector that's much closer to the red line

*but is not of length 127*. This way of storing normals as vectors of any length anywhere on [-127 127]^3 allows far greater accuracy than only storing normals as vectors of length 127.

So basically, instead of converting float_x to int_x, float_y to int_y, float_z to int_z for storage and then back again for calculations, this method determines which vector (int_x, int_y, int_z) is most parallel to (float_x, float_y, float_z) and stores that instead. It takes the same 3 bytes, but is more accurate and basically no more computationally intensive.

If that wasn't clear, tell me and I might be able to whip up some pseudocode that shows how normals are stored this way.