Nodes/radiance/ACES 2.0 Output Transform
ComfyUI Node

ACES 2.0 Output Transform

The one ACES node in this pack you actually want

By FXTD-Studios·Created 8 months ago·Updated about 18 hours ago· 246
ACES 2.0 Output Transform
  • image
  • image
  • transform_info
◄input_colorspaceACEScg►
◄output_transformACES 2.0 SDR (sRGB/Rec.709)►
◄peak_luminance100►
◄surroundDim►
◄exposure_adjust0.0►
◄creative_white_scale1.00►
◄gamut_compress_strength1.00►

What this node is for

If you've ever put an AI render next to a plate from a real camera and couldn't say why yours looked like a picture of a picture, the answer is usually not the model. It's that your pixels went from "some numbers" to "screen" through a colour pipeline nobody ever specified. This node is that pipeline, done properly: the ACES 2.0 Output Transform, scene-linear in, display-encoded out.

Radiance is an HDR/VFX toolset from FXTD Studios - 147 nodes, and by far the most of it is aimed at people finishing shots rather than prompting them. It shows up on r/comfyui occasionally as a "hidden gem for film and VFX" post, which is about right: it's a pro pipeline bolted onto a generation tool, and its audience is small and specific. The colour management corner of ComfyUI is thin in general; the KB's read is that it stays specialist because "the moment you need it you need all of it, and until then you do not need any of it." This is the node you need when you've crossed that line.

Reach for it when you're delivering to Resolve, Nuke or an HDR display. If you're making sRGB PNGs for the internet, you don't need it and you shouldn't wire it in.

How it actually works

The transform method runs a fixed six-step chain, in this order:

  1. Convert the input primaries to ACEScg (AP1).
  2. Apply exposure_adjust (in stops) and creative_white_scale.
  3. ACES 2.0 reach gamut compression.
  4. The ACES 2.0 tonescale - the "Daniele Evo" forward curve, the same Hill/Michaelis-Menten rational function the reference implementation uses.
  5. Convert AP1 to the target display primaries.
  6. Encode with the right OETF: sRGB curve, PQ, HLG, or gamma 2.6 for cinema.

The surround control isn't a vibe setting. It feeds ACES's contrast exponent g - Dark 1.10, Dim 1.15, Average 1.20. Dark is what a cinema is. Dim is a living room. Average is an office with lights on. Pick wrong and your blacks and highlights will look misjudged on the display you're actually grading for.

Inputs that matter

image wants scene-linear values where 18% grey is 0.18. A display-encoded sRGB image must be linearised first - this node does not remove a transfer curve for you, only converts primaries. Feed it a PNG straight off the decoder and you get a dark, contrasty mess.

input_colorspace tells it what primaries it's looking at: ACEScg, ACES2065-1, Linear_sRGB, Linear_Rec2020.

output_transform picks the target - SDR sRGB or P3-D65, Rec.2100 PQ at 1000/2000/4000 nits, HLG, or cinema P3 at D60 or D65. Match your monitor's actual calibration; D60 and D65 both target P3 but at different white points, and picking the wrong one is a subtle, annoying tint.

The optional knobs, briefly. peak_luminance (100 nits default) applies to the SDR and HLG outputs only - the PQ options are fixed by their name and cinema is fixed at 48 nits, so turning it does nothing there. exposure_adjust is straight stops. creative_white_scale is a linear multiplier on all channels, so 2.0 is +1 stop of exposure, not a white-point change - the tooltip says so explicitly, which saves you from the wrong mental model. gamut_compress_strength is the reach gamut compression amount, 1.0 = standard.

Outputs

image - display-encoded, 0 to 1, ready for a Write node or the Viewer. transform_info is a string describing exactly what ran. Strings don't get fed to image nodes; they exist so you can print them, log them, or stick them in a metadata chain. Wire it into Radiance's Write nodes or a note when you need to prove which transform produced a deliverable.

Install

ComfyUI Manager → search Radiance → install → restart → refresh the browser. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/fxtd-studios/radiance.git
cd radiance
python -m pip install -r requirements.txt

Windows portable users must use the bundled python_embeded\python.exe for that pip call. On first startup Radiance uses your $OCIO if you have one and otherwise falls back to OpenColorIO's built-in ACES studio config, so this node works without extra setup. No model download is needed for a transform.

Where people get burned

  • Display-encoded input. The single most common mistake. Linearise first (Radiance's colour-space convert, or your own chain) or the output is unusable.
  • Reading the output as scene-linear. It's 0–1 display-encoded. Anything downstream that expects HDR values will silently do the wrong maths.
  • Assuming peak_luminance does something on PQ or cinema. It doesn't.
  • OpenEXR on Python 3.14. The requirements file deliberately skips the OpenEXR wheel there (none exists yet) and falls back to OpenImageIO, then OpenCV. If you see EXR errors, that fallback chain is where to look.

Pair it with ACES 2.0 S-2126 Compliance if you want the node to tell you whether the transform actually hit its targets.

CategoryFXTD STUDIOS/Radiance/HDR

Inputs (8)

NameTypeDefaultDescription
imageIMAGEScene-linear image in the space chosen by input_colorspace (18% grey = 0.18). A display-encoded sRGB image must be linearised first.
input_colorspaceCOMBOACEScgPrimaries of the incoming linear image; it is converted to ACEScg (AP1) before the transform. No transfer curve is removed.
output_transformCOMBOACES 2.0 SDR (sRGB/Rec.709)Target display: sets primaries, encoding (sRGB, PQ, HLG or gamma 2.6) and peak. Output is display-encoded 0 to 1. Cinema D60 targets P3 at ACES white; Cinema D65 targets P3 at D65. Match the display calibration.
peak_luminanceoptFLOAT10048–10000Display peak luminance in nits for the SDR and HLG outputs. Ignored for the PQ outputs (fixed by their name) and Cinema (fixed 48 nits).
surroundoptCOMBODimViewing environment — affects contrast parameter g.
exposure_adjustoptFLOAT0.0-4–4Exposure adjustment in stops before transform.
creative_white_scaleoptFLOAT1.000.5–2Linear multiplier on all channels after conversion to ACEScg, so it acts as extra exposure (2.0 = +1 stop), not a white point change. 1.0 = no change.
gamut_compress_strengthoptFLOAT1.000–1.5ACES 2.0 reach gamut compression strength.

Outputs (2)

NameTypeDescription
imageIMAGE—
transform_infoSTRING—