Well, let’s get technical for a second here. There will always be some quantisation because the LED pixels themselves have, at best, 8 bits per channel of color data. If we decided to run at 1/2 brightness, now we only have 7 bits per channel; at 1/8th brightness, we only have 5 bits per channel, and so on.
And when we drop the brightness (or V, related issue) very low, like say “8”, then there are, at best, only three bits of color per channel: only eight levels of Red, eight levels of Green, and eight levels of Blue that can be mixed to make the resulting colors. And one of the levels in each case is “off”/“black”, so really there’s even less dynamic range to work with.
This is all exacerbated here by the fact that in order to provide a roughly linear scale for of apparent brightness for “V”, the FastLED HSV code has a built-in gamma correction of 2.0. And the practical upshot of that is that when you put medium-low “V” values (eg, less than 30) into an HSV value, it gets converted to a lower numeric brightness as an RGB value. Dan dumped some of the actual numbers here so you can see: https://github.com/FastLED/FastLED/issues/196#issuecomment-127462961
So there’s sort of an ‘upper limit’ on color rendering quality given the dual constraints of (1) 8-bit-per-channel digital LED outputs, and (2) gamma correction on the “V” axis to make apparent brightness’ more linear.
You can retain more useable bits if you draw your colors into the leds[] array at “full brightness” (high “V”), and then use the FastLED.setBrightness() control to dim the whole strip down. That retains roughly another two bits of dynamic range because of the FastLED temporal dithering.
But if you formulate HSV colors with low “V”, you’re going to get quantisation no matter what. Actually, for that matter, if you formulate RGB colors with low values, you’re going to get quantisation, too!
At a certain point it all comes down to the fact that when the LEDs are dim, your eye can see big differences between (1,0,0) and (2,0,0) and (3,0,0), and the color (0,0,3) looks very ‘far away’ from (1,0,2). The LED strips use integer steps, and at low brightness your eye can see them clearly.
Obviously, despite all that, Dan and I are always trying to make your animations come out as awesomely as we can… and that’s what started us down the “scale8” rabbit hole again!