rl.ColorNormalize does not return normalized values
Hi.
It seems that the method rl.ColorNormalize() does not actually return normalized values, instead returning values close to the original RGBA values.
For example:
c := rl.NewColor(0x7F, 0x7F, 0x7F, 0xFF) // Arbitrary
fmt.Println(c) // {127 127 127 255}
normalized := rl.ColorNormalize(c) // Should normalize c to {0.5,0.5,0.5,1}
fmt.Println(normalized) // Instead we get {127.99608 127.99608 127.99608 257}
For some reason this issue is masked by the fact that rl.ColorFromNormalized() returns the original values if they haven't been modified:
fmt.Println(rl.ColorFromNormalized(normalized)) // {127 127 127 255}
However modifying the supposedly normalized values yields unpredictable results when they are converted back to colors
normalized.X /= 2
fmt.Println(normalized) // {63.99804 127.99608 127.99608 257}
fmt.Println(rl.ColorFromNormalized(normalized)) // {191 127 127 255}
This problem seems to stem from the implementation of rl.ColorNormalize()
// ColorNormalize - Returns color normalized as float [0..1]
func ColorNormalize(col color.RGBA) Vector4 {
result := Vector4{}
r, g, b, a := col.RGBA()
result.X = float32(r) / 255
result.Y = float32(g) / 255
result.Z = float32(b) / 255
result.W = float32(a) / 255
return result
}
This would work fine if color.RGBA returned the r,g,b,a values of the original color struct, however, this method actually returns the 32-bit "alpha-premultiplied color" values in the range 0 <= C <= A[^1]. This means that the return values have been scaled to a range of 0->65535 instead of the expected 0->255
The simplest solution would be to amend ColorNormalize() to avoid the RGBA method and keep the values in their original uint8 form:
func ColorNormalize(col color.RGBA) Vector4 {
result := Vector4{}
r, g, b, a := col.R, col.G, col.B, col.A
result.X = float32(r) / 255
result.Y = float32(g) / 255
result.Z = float32(b) / 255
result.W = float32(a) / 255
return result
}
I can make a PR to fix the issue, unless I'm missing something obvious.
[^1]: This is what the documentation claims. The actual code does not seem to do this. I'm planning on starting an issue/PR for image/color to correct this. Even if this gets fixed it wouldn't change the issue presented here.
Ignore the footnote. Turns out it's up to the developer to ensure the values are premultiplied, making the use of the color.RGBA struct in raylib-go wrong as I'm pretty sure Raylib doesn't use premultiplied values for color. Instead color.NRGBA should be used. Should I open a second issue/PR to address this?
Yes, PR would be nice, thanks.