why not use faster division by 256?
Integer division by 256 would be faster, but you're not doing integer division, are you? Floating-point division doesn't generally have shortcuts based on specific values like that. If you have to do a floating-point division, you pay the cost of a floating-point division.
This Godbolt example shows that Clang, on high optimizations, doesn't find a way to make division by 256.0f any faster than 255. GCC and MSVC do get one small optimization: they substitute the division by a multiplication against the compile-time computed value of 1/256.0f, which is an exact floating-point number. But you can accomplish the same thing by having your code explicitly multiply by (1 / 255.0f)
, so again, there is no advantage.
Now, there are theoretically faster ways to normalize an unsigned integer value into a float. But these generally rely on direct bit manipulation of a floating-point value, and may not actually be faster than just doing the floating-point math. You'd have to profile it under the specific circumstances you intend to use them under to make it work.
what are the actual consequences of slightly lower float values? Anything actually discernible?
The consequences could be anything. As far as modern OpenGL is concerned, the meaning of every value you provide to OpenGL is determined entirely by your code. Indeed, your code could add a division by 0.996 to rescale the number and thus there would be no real difference.
It is easy to write a piece of shader code that will break if you refuse to pass a properly normalized floating-point value (anything that does if(value == 1.0f)
, which is required to be true if you did normalization correctly). I can just as easily write code that wouldn't care. There is no general answer; it all depends on what you're doing with it.
Compatibility OpenGL is essentially the same way: it all depends on what you're doing with it. It may be fixed-function rather than shaders, but there's still plenty of room in there for you to define the meaning of that number.
Because the viability of the result is based on information which you cannot know at the level of a simple normalizeIntegerToFloat
function, what you ought to do is provide the caller of the function with a choice. Provide an accurate version and a lossy version. What you absolutely should not do is make the lossy version the default. If the user of the function sees a performance problem, they can switch to using the lossy version to help alleviate it.