Expand sRGB color space

Hello. Due to legacy reasons my code base working color space is sRGB. I’d like to make it possible for artists to pick colors outside of this color space, as you can imagine, changing working color space to another wider one means lots of changes and tons of work.

Let’s say in our color pickers I provide colors outside sRGB color space (the colors will clip when displayed in color picker), when is time to display the game rendered image, can ACES take these out-of-srgb colors and map them within the srgb range? Do I use the ODTs found here?: aces-dev/transforms/ctl/odt at dev · ampas/aces-dev · GitHub


1 Like

Hello and welcome to ACEScentral !

As you will most likely find in the code, the ODTs also clip out-of-gamut values.

// Handle out-of-gamut values
// Clip values < 0 or > 1 (i.e. projecting outside the display primaries)
linearCV = clamp_f3( linearCV, 0., 1.);

May I ask you why you want to go to a wider working/rendering space and what are you trying to achieve ? Out of curiosity ?

I have given it many thoughts and many tests to finally set the working/rendering space of our movie to linear_rec709.


Am trying to give our artists the ability to use rec2020 colors, as it stands today, rec709 is all they get with our tools, even when the game renders in an HDR monitor. I guess what am trying to solve is how can I provide our artists the ability to use HDR colors without having to make a ton of changes. I thought that by allowing them to step out of the working gamut, ACES could take those out of range srgb values and some how do gamut compression. At the same time, those out of working gamut values would map well within the rec2020 color range and therefore allow the aritsts to use rec2020 colors as well. Let me know if this makes sense.

Hello and sorry for the late reply,

I think what you describe is what the Output Transform Virtual Working Group is currently trying to achieve for ACES 2.0 with Gamut Compression and such.

What you could look into if you want to expand the color palette of your artists is the OCIO role “color_picking” as implemented in Autodesk Maya. Maybe ? Or just switch the OCIO role “scene_linear” to P3 or BT.2020 with the usual issues. Are your HDR monitors really Rec.2020 ? I am not sure if they can reach 100% of this gamut yet.

To be honest, I haven´t seen a single Display Transform that does not clip or skew at some point with wide gamut… Maybe AgX will do that someday. This is why I switched back to BT.709 until someone solves this riddle.



I think the consequences of working with the rec. 2020 color space are not to be taken lightly. I have myself evaluated it and, while it might be ok as a rendering space if one were willing to transform the colors sampled from textures by a 3x3 matrix everytime one samples from textures, it is definitely not ok for textures as the color space is so big that it requires 10-bit precision so you have to either say goodbye to your alpha channel and use BC6 texture compression (or uncompressed fixed-point RGB10A2) or use a texture compression format that is not precise enough for such a large color space. On the other hand, the P3 color space encoded with the sRGB gamma curve (i.e. Display-P3), would not require additional precision in textures and you could keep using BC7 (please ditch BC1 and BC3). Of course, you have to take into account the different color space in your shaders :slight_smile:


@jmgilbert Assuming that ACES 2.0 handles the mapping of colors outside of the sRGB space into it, do you think is a good idea to leave the sRGB pipeline intact, but allow artists to pick colors outside of this space so that when we want to render HDR we can better take advantage of rec2020? The thinking behind this is that the colors outside of sRGB will better map into the broader rec2020 color space and as a result we can display an image closer to the artist’s intent.

That depends on whether you want to store those colors inside textures or not. If you want to render in sRGB but have textures that store colors outside sRGB gamut using sRGB primaries then you have to store negative values in linear space. Because of that, if I was allowed to do such a big change, I’d go for a full P3 pipeline (textures, picker and rendering space), color grade in ACEScg (which we do at Larian) then have the DRT map that back to the correct color space for display (that’s what you’re using ACES for :slight_smile: ). An issue with using a full P3 pipeline is that some 3rd party software packages might not support it (hello Substance).

The bonus is that if you have uncalibratable Dell monitors that use a native P3 color space in SDR then they will correctly interpret the code values in non color-managed software (at least until you get to the DRT stage where properly implementing color management is quite hassle under Windows :slight_smile: ). I was assigned an issue by an artist using such a monitor that basically said : “Colors look different in Photoshop than in the game”. The conclusion was that she had correctly installed an ICC profile for her monitor so color-managed software would work correctly but games are typically not color-managed so the monitor was stretching sRGB code values to P3 gamut.

1 Like

My situation is simpler than yours I think. All of our pipelines are made with sRGB in mind, including the color pickers. Our textures are all sRGB as far as I know. In our game, I want to let artists pick colors outside of sRGB for stuff like light colors, for example. Our lighting is done in sRGB linear, but since some of those colors will be outside of sRGB, I need a way to map them back into sRGB (this is where I think ACES 2.0 will help me). If am rendering in HDR, I want those same sRGB linear colors to map inside of rec2020 correctly as well.

Would I have to worry about negative linear values my case?

Yes. Colors outside the sRGB gamuts map to negative values when converted back to sRGB primaries. Since you want Rec. 2020 primaries, let’s take pure linear Rec. 2020 red. If you want to keep doing your lighting in sRGB gamut, you would have to convert that Rec. 2020 red to sRGB gamut using the following 3x3 matrix :

   [ 1.66050   -0.58770   -0.07280]
   [-0.12460    1.13300   -0.00840]
   [-0.01820   -0.10060    1.11871]
type or paste code here

Matrix is shown as row-major since it is copy-pasted from my HLSL code and reformatted to more normal math notation so your sRGB color would be :

    sRGB_Red   =  1.66050 * Rec2020_Red - 0.58770 * Rec2020_Green - 0.07280 * Rec2020_Blue
    sRGB_Green = -0.12460 * Rec2020_Red + 1.13300 * Rec2020_Green - 0.00840 * Rec2020_Blue
    sRGB_Blue  = -0.01820 * Rec2020_Red - 0.10060 * Rec2020_Green + 1.11871 * Rec2020_Blue

which gives you (1.66050, -0.12460, -0.01820) as your mapped color in linear sRGB space. So, already, we both have negative values and a value that’s higher than one which is normally used for HDR colors in 3d rendering. That’s why you have to do your lighting in a color space that is big enough to contain all the values from your color pickers. Otherwise, you can end up with negative values which can cause an infinite amount of problems. The only way to end up with all positive numbers is to actually pick a color that’s representable in sRGB gamut.

There are other ways of solving this like applying gamut compression before transforming to sRGB space but then you’re not really really allowing to pick colors outside of sRGB space :slight_smile:

If I spoke in too technical terms then maybe these resources will be of help :

Hi @jmgilbert Could you say more about the reason for making the rendering space P3-D65 as opposed to ACEScg?

Also what is the issue with Substance (Painter) you alluded to above? Is this still the case?

Ok, I just noticed that I hadn’t answered this yet. There are many reasons to this. First, it’s a good compromise between the lowest common denominator which is sRGB (not taking into account cheap laptop panels) and non-existant future hardware that will be able to display the full Rec.2020 gamut (for all intent and purposes, ACEScg is 99% the same as Rec.2020). The D65 white of P3-D65 is also the same as the white point of sRGB and it’s also the same as the displays so that’s much less hassle. Whether there’s a creative whitepoint applied further down the post-processing chain is an art decision, not a technical one so that’s of no concern here. However, the major reason of not exceeding P3 gamut for rendering is 8-bit texture compression. We can already forget about DXT1, DXT3 and DXT5 because these formats can barely compress sRGB textures with acceptable quality. However, BC7 is of high-quality enough that it can compress a wider-gamut texture in P3 with acceptable quality without causing too much banding. Of course, if an alpha channel is not needed, BC6H can be used as it can compress 3 16-bit half float channels in the same amount of bits that BC7 uses for 4 8-bit unsigned integer channels.

Not sure whether Substance Painter can support wide gamut now but, 7 years ago, it could only support sRGB while Substance Designer was able to support multiple colorspaces already.

Hope that answers the question,