Why don't hexadecimal color inputs use the renderer's color space?

My renderer’s color space is three.LinearSRGBColorSpace.

When I use new three.Color(r,g,b) object for a material color, the result is accurate.

However, when I use a hexadecimal (like 0xbe936), the resulting color is not accurate.

Why don’t hexadecimal inputs use my renderer’s color space?

renderer.outputColorSpace = three.LinearSRGBColorSpace;

const beigeA = new three.MeshBasicNodeMaterial({
    color: new three.Color(190 / 255, 147 / 255, 109 / 255)
});

const beigeB = new three.MeshBasicNodeMaterial({
    color: 0xbe936d
});

Example image:

principle of least surprise? :smiley:

Well, the documentation for Color says that hexadecimal inputs are converted to the working color space automatically, but that doesn’t appear to be happening in my case:

A Color instance is represented by RGB components in the linear working color space, which defaults to LinearSRGBColorSpace. Inputs conventionally using SRGBColorSpace (such as hexadecimals and CSS strings) are converted to the working color space automatically.

Their default values for color space differ:

setHex( hex, colorSpace = SRGBColorSpace )
setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace )

Whether this is intended behaviour or not, I cannot comment.

Note: the defaults above are from the source code, the docs say something different for setRGB.

2 Likes

Note that the renderer has both a working color space (default: Linear-sRGB) and an output color space (default: sRGB), so “renderer’s color space” might mean multiple things.

Hexadecimal encodings are usually sRGB — encoding Linear-sRGB color to hexadecimal is lossy enough to be visible easily. Similarly CSS color strings (like “crimson”) are defined to be sRGB. So in both of these cases THREE.Color assumes the input is sRGB and converts to the working color space. In other cases THREE.Color assumes that you’re providing input in the working color space, unless otherwise specified by the colorSpace parameter.

Same behavior in Blender’s color picker, where the hexadecimal (and not RGB) input is gamma corrected, so {0.5, 0.5, 0.5} == #BCBCBC.

4 Likes

Thanks for that detailed info, I understand now.