ACES 2.0 CAM DRT Development

I have found that the SDR image sometimes looks brighter / more saturated than the HDR image. It looks even brighter / more saturated than the original linear rgb input. Then I remembered that DCamProf’s neutral tone reproduction operator was very good at matching the tone-mapped image with the linear image perceptually. So, I’ve looked into it and found that it uses mainly the luminance from a pure rgb curve for tone mapping. Only for more saturated colors the tone curve is applied on the input luminance and then used for the tone mapping:

  • Luminance is the same as a DCP tone curve applied in linear ProPhoto space
    • This means that the contrast and brightening will be the same as a standard DCP/RGB curve, so you can use the same curve shape.
    • Exception: for high saturation colors (flowers etc) a pure luminance curve is blended in, as it has better tonality.

Source: DCamProf


tonecurve applied on luminance
Tonecurve applied on the input luminance, which is then used for the tone mapping

output luminance from rgb tonecurve
Luminance derived from a pure rgb curve, which is then used for tone mapping

I personally do prefer the look of Anders Torger’s method (especially for red colors like in the example above) and I hope that it can improve SDR/HDR matching. Now I’m curious if it’s possible to use this method for the ACES DRT? I mean, is it possible to find an inverse of the transform?


I pushed a new proto version v042-pex that has a chroma compression without saturation boost. Available from my DRT prototype repo. Please test and see how that behaves compared to the previous one and how the Rec.709 and Rec.2100 appearance match looks. There’s not much difference to v035 in Rec.709.

I created LUTs for Rec.709, Rec.709 sim and Rec.2100 P3Limited, also available from the same repo under the LUT directory.

I also created an alternative version of Rec.2100 P3Limited LUT which maps middle gray to 13.3 nits. It’s there for testing to see what a lower middle gray mapping does to the appearance match when comparing against Rec.709.


Hi Pekka,

would it be possible to get also an OCIO config like @alexfry usually created for new versions?

37 posts were split to a new topic: Luminance-Chrominance Polarity Based Display Rendering Transform

OK, meeting is close, but better late than never.

New bakes:
ACES2 Candidates rev042 = CAM_DRT_v042_pex.blink
Which I think is the latest one @priikone endorses.

ACES2 Candidates rev043 = CAM_DRT_v043.blink
Which is a hybrid of CAM_DRT_v042_new_scaling.blink and my own CAM_DRT_v042.blink

rev043 also has different things set.
in gamut compression is off
reach primaries is Spectral Locus
And the gamut compressor is iterative

I also need to see what’s going on with inversion in v043, but need to call it a night.

1 Like

For the version that goes to testing can we have it as a DCTL?

I have tried to get Nuke non-commercial to work with Blinkscrip with no success. I have a Windows system with AMD hardware.

I would also like to run the test images on the 12.9" iPad M2 Pro with DaVinci Resolve for iPad to view in both SDR and HDR. Nuke does not run on iPad.


(An additional note is to be aware that some GPU cards have settings for graphics pixel bit format which is separate and differs from display color bit depth. From my understanding the pixel bit will effect the calculations, truncating them to the selected bits. Make sure that the GPU is set to 10-bit in both areas. The latest AMD Radeon Pro W7900 & 7800 go to 12-bit as do the upper end Nvidia. )

I’ve just pushed CAM DRT v042-pex3 to my repo.

v042-pex3 version brings the following changes:

  • New chroma scaling with the exponent suggested by @luke.hellwig.

  • New in-gamut compression algorithm that matches the look of the previous versions. It first expands colorfulness a little bit in the darker colors, and then compresses to create the path to white. The in-gamut compression no longer pushes values outside spectral locus (or is minimal compared to previous versions).

  • New HDR/SDR appearance match technique. The old technique of rescaling the tonescale to bring the chroma scaling ratios closer to 100 nits tonescale is no longer used. Instead, the ratios are used as is and the tonescale is not touched. The match is created by scaling the in-gamut compression parameters automatically by the peak luminance. This is simpler than the previous one.


LUTs and DCTLs are available in my repo for Rec.709, Rec.709 sim and Rec.2100 P3Limited.

Look compared to v035



Effect of in-gamut compression to values close to spectral locus

Input image:

Input chromaticities:

Scaled chromaticities (using the new exponent):

Fully chroma compressed chromaticities:

Then comparing to v035. v035 fully chroma compressed chromaticities:

The last two images show the difference between v042-pex3 and v035, and the problem that the older versions had that @alexfry has been talking about. In v042-pex3 the chromaticities are no longer pushed outward, or is only minimal compared to older versions.


Here are the DCTL versions

Thankyou Anton and Pekka both, but will we be able to have math DCTLs and not just a LUT? Thanks.

I gave a couple reasons in:

I’ve added some new baked variations to the LUT repo:

rev044 - Which is what @priikone showed in the meeting this moring, but with some of my iterative solver fixes merged (not active in this bake though.

rev044_B - Is the identical blink code, but with some different settings one the Nuke node.

  • IterativeGamutCompressor is On.
  • custp to mid blend is set to 0
  • Reach Compression Mode is on, and set to Spectral Locus

Both can also be found in the dev repro:

CAM_DRT_v044.blink is used by both
CAM_DRT_v044.nk and CAM_DRT_v044_B.nk (same code, different settings)

My one BIG caveat, is that the inverse pathway on the iterative gamut compressor isn’t working properly, and I’m not going to be able to sort it before I go away.

The difference between the two variations is pretty negligable when looking at “normal” images, and really only manifests with extreme colours and intensities.


Here is -4 stops with rev044_B Rec709 in Resolve (no RGC)
(I used _B version, as a better one in terms of handling this artifact)

Maybe it’s better to use a synthetic gradient for that? If I turn on RGC, it helps a little bit, but if I also add saturation in ACEScct using old Saturation knob (just a regular CDL-like saturation) from default setting 50 to 60, the transition becomes more visible again. I think, even if you’ll manage to somehow display this particular image without the sharp transition at all exposures, this balance will still be very fragile.

As to ver044 and ver044B there still seems to be some NANs produced with extreme examples. For example when looking at the red diver with torch: some white dots appear in black areas when I am using an exposure DCTL which is basically for linear input rgb = rgb * _exp2f(exposure). And all I need to do is turn that exposure node on and off, even with 0 exposure, and the dots go on and off. This does not happen in typical frames (without extreme colors.) (Only two nodes: a simple exposure DCTL and an ACES Transform with the new versions selected. Set up as documented on ACES Central.)

Also the white dots (NANs?) then go away when I turn on the Gamut Compress in the ACES Transform node, even if those values are minimally set at limits of 1.001 and thresholds of 0.000.

I am using Resolve on a Windows10-64 AMD system with the new rev044 & rev044B LUT based DCTLs and do not know if this might just be due to using the LUTs.

Had a quick look at the LUT-based DRT packages 44 and 44_B.

One thing I noticed is that dark colours swing a bit in an unexpected manner.
If you add a full red ramp in ACEScct through the pipeline, you notice a sudden turn towards orange.

Cyan have less of that effect.

Blues are desaturating more than other colours:

I would do some more testing in cinema environments with very dark shots. Sometimes it is difficult to get a rich, dark image in a cinema; further desaturation at the low end does not help.


I pushed a new version CAM DRT v045-pex to my prototype repo. This version brings the following changes:

  • Introduce “reach mode” chroma compression. The chroma compression space is now used to find out how far to reach out (the limit for chroma expansion/compression). The reach limit is normalized with the cusp of the same space. The primaries of the chroma compression space is changed at the same time. This significantly improves the inverse, as well as guarantees the chroma compression will not expand or compress colorfulness beyond that space. This is using same technique as @alexfry’s reach mode gamut mapping.

  • Make noise reduction optional and disabled by default. The new transforms doesn’t really increase noise anymore so noise reduction may be redundant.

  • Change gamut mapping parameters. Adds also clamp for maximum M that the transform handles. This is 2x the maximum M value for 10000 nit display. That value and any value above that would map only to display white or be always out of gamut even after gamut mapping. This avoids NaNs with the gamut mapper quadratic.

Rec.709 Inverse



Effect of chroma compression to chromaticities

Input chromaticities:

scaled chromaticities:

fully chroma compressed:



I believe the strange behavior @meleshkevich is pointing out is a similar sudden hue direction change in blue/cyan:

blue-cyan_hue_direction_change_v44.nk (298.5 KB)

1 Like

I think the example you posted is caused by the final gamut compression.
In you Nuke Script if you disable apply out of gamut compression the dent goes away.

I am concerned about the deepest shadows.

The good news is that I don’t see the dents in the deepest shadows in the Nuke-based implementation. So it seems that the LUT-based implementation has its difficulties down there.


I think the inability to quite reach the red primary is caused by a combination of the gamut approximation and the cusp smoothing. Looking at a 3D JMh plot around the red primary, setting cusp smoothing to zero, and using the iterative gamut boundary solve, shows the true location of the red primary:

Whereas using the gamut approximation and cusp smoothing the primary is clearly missed:

Note: The version used for this plot is @priikone’s latest, v045-pex, but I believe the same would apply to any recent version.

1 Like

Can you share your Nuke script? I can’t seem to reproduce this using Alex’s visualization Nuke script. Regardless of the approximation or cusp smoothing, neither can reach the red corner in that visualization when I try this (at least when none of the channels are negative). If you plot the actual (not approximation) Rec.709 boundary in JMh, does it reach the red corner?

It’s entirely possible I have done something stupid!

I did assume that since the iterative solve was accurately finding the cusp, what I was seeing was the cusp. But it is just compressed values, so maybe not.

I am not using Alex’s visualiser. I just take the output of the DRT in diagnostic mode 3 (which I believe should be compressed JMh) and run it through a simple polar to rectangular Expression and into a PositionToPoints node. The input is your locus ramps image.

Here is my nuke script:

Pex45_plot.nk (337.8 KB)