Accurate Colors in replaced tonemapper: Linear Hex vs sRGB hex

I was tasked with getting a color on the screen that was an exact match for the value in a Figma doc, 12171DFF. Despite putting 12171DFF into the Hex sRGB field in the color picker, when we looked at the color in the viewport in the unlit scene it was not 12171DFF.

It was eventually determined that the problem must be in the tonemapper, and so I decided to replace the tonemapper with a custom one. There’s a fair bit of discussion of this sort of topic eg. this thread Struggle Against Tonemapper

Eventually I did successfully get the color to match, but my lingering problem at the moment is that I don’t really know why it works or how I got it to work.

Despite various threads pointing out the sRGB checkbox in the Color Picker as being relevant I found that that did nothing really at all.

In order to get the proper color, I needed to set 12171DFF into the Hex Linear field of the Color picker and then in the custom tonemapper material directly output from PostProcessInput0 to Emissive output.

I guess it makes sense. We want this color directly and I guess the output of the tonemapper is supposed to be in linear color space.

However the curious thing is that the way the hex values in the Color Picker update I just assumed that the Hex Linear was doing some conversion of Hex sRGB into Linear Colorspace and that it was the same color. The Unreal documentation has little to say here. Color Picker | Unreal Engine Documentation

If I put 12171DFF into the Hex sRGB and then try to convert in my tonemapper from sRGB to Linear by using the method described in many places by applying Power to 1/2.2 I would expect to get the same value but I do not. If I use the provided sRGBtoLinear Material Function I don’t get the right value either.*

I’m happy I got this to work but left confused about so many things.

What is the Color Picker doing?
Why is it that it only works when adding the value to Hex Linear?
Was there a way to get the value I wanted from an sRGB value?

  • as an aside I find it interesting that the sRGBtoLinear function yields different results than the Pow(x, 1/2.2) that everyone says to use… What is the difference and what should one be using?