Nodes/radiance/Bake Viewer Grade
ComfyUI Node

Bake Viewer Grade

Stop grading the preview and grade the actual pixels

By FXTD-Studios·Created 8 months ago·Updated about 18 hours ago· 246
Bake Viewer Grade
  • image
  • image
◄exposure0.00►
◄offset0.000►
◄lift0.000►
◄gamma1.00►
◄gain1.00►
◄contrast1.00►
◄pivot0.18►
◄shadows0.00►
◄highlights0.00►
◄saturation1.00►
◄temperature6500►
◄hue_shift0.0►
◄lut_nameNone►
◄lut_intensity1.00►
◄color_scienceLinear (sRGB)►

You've been nudging the wheels in the Radiance Viewer for ten minutes and the shot finally looks right. Then you save it and it looks wrong again. That's not a bug: the Viewer's grade is a view. It changes what you see, not what's on the wire - the pack's own README says as much ("Viewer adjustments affect the preview unless you apply equivalent processing in the workflow"). Bake Viewer Grade is the node that closes that gap. It runs the exact same grading math RadianceViewer runs, and writes the result into the image tensor for real.

Reach for it when the grade is the deliverable - you liked what you saw, you want that baked into the EXR/PNG you hand off, or you want downstream nodes (upscalers, compositors, a video encode) to see graded pixels instead of the raw ones. If your grade is still exploratory, don't bake it; keep grading in the Viewer and iterate.

How it works

The node loops the batch, hands each frame to the same apply_grading function the Viewer uses, and returns the tensor. Grading happens in NumPy on CPU, so this is a per-frame pass, not a free shader. Two behaviours worth knowing: the output is not clamped - values above 1.0 survive, which is the point for HDR work - and NaN/Inf are cleaned up rather than allowed to poison the tensor.

The inputs that matter

Almost everything here is a grade parameter, so the interesting question is order. Exposure (exposure, in stops, multiplied as 2^x) happens before everything else, then the additive lift/offset, then the wheels.

The four wheels are lift, gamma, gain, offset. That's the classic lift/gamma/gain rig, and color_science decides where it runs: leave it on Linear (sRGB) for linear-light grading, or pick ACEScct to convert to ACEScct, do the wheel math there, and convert back. ACEScct is the friendlier space for shadow work - a lift in linear squashes fast.

Then the tone side: contrast around pivot (default 0.18, i.e. 18% grey in linear light - leave it there unless you know why you're moving it), shadows, highlights, saturation, and temperature in absolute Kelvin where 6500 is neutral. hue_shift rotates hue in degrees.

The one to be careful with is lut_name. It's a 27-entry list of built-in transforms applied last: display curves (sRGB (Display), Filmic (Cinematic)), camera log encodes (LogC3 (ARRI EI800), LogC4 (ARRI Alexa 35), Log3G10 (RED IPP2)), log-to-linear IDTs, and two analysis views (False Color, Clip Check). lut_intensity blends it 0–1. One output: image.

Install

ComfyUI Manager → search Radiance → Install → restart ComfyUI → 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 python_embeded\python.exe for that pip step. The requirement list is genuinely heavy - OpenImageIO, OpenColorIO, OpenEXR (skipped on Python 3.14, where no wheel exists yet), diffusers, accelerate - so budget a minute or two. No models to download for this node.

Where people get burned

The classic mistake is baking a display curve on top of a grade that already produced display-range values: pick sRGB (Display) once, not once per node in the chain, or you'll double-encode and wonder why the image looks washed out.

The second is contrast. The tooltip is refreshingly honest that this is a linear contrast around a pivot, not an S-curve, so values can go negative or past 1.0. Crush it hard with default pivot and you'll clip shadows you can't get back - and because the node doesn't clamp, that damage rides along silently into everything downstream.

Finally, remember this is permanent. There's no un-bake; the original pixel values are gone. If you might need to revise, keep a copy of the pre-grade branch in the graph.

CategoryFXTD STUDIOS/Radiance/Color

Inputs (16)

NameTypeDefaultDescription
imageIMAGEImage to grade, treated as linear Rec.709/sRGB primaries. The result is not clamped (values above 1.0 are kept); NaN and Inf are zeroed or capped.
exposureFLOAT0.00-10–10Exposure in stops, baked into the output: RGB is multiplied by 2^exposure before every other control.
offsetFLOAT0.000-1–1Additive brightness lift applied after exposure. Shifts all tones uniformly.
liftFLOAT0.000-1–1Shadow lift (black point raise). Raises the darkest values without affecting highlights.
gammaFLOAT1.000.01–4Mid-tone power curve, applied as x^(1/gamma) to positive values. Values > 1.0 brighten, < 1.0 darken the midtones.
gainFLOAT1.000–10RGB multiplier (slope), applied after lift. 1.0 = no change.
contrastFLOAT1.000–4Linear contrast around pivot: (x - pivot) x contrast + pivot, per channel. Not an S-curve, so values can go negative or above 1.0.
pivotFLOAT0.180–1Value left unchanged by contrast. 0.18 = 18% grey in linear light.
shadowsFLOAT0.00-1–1Shadow brightness, no tint: RGB is scaled by 1 + 0.5 x shadows x (1 - luma)^2. Positive brightens dark areas, negative darkens them.
highlightsFLOAT0.00-1–1Highlight brightness, no tint: RGB is scaled by 1 + 0.5 x highlights x luma^2 (luma clipped to 1). Positive brightens bright areas, negative darkens them.
saturationFLOAT1.000–5Global colour saturation. 1.0 = original, 0.0 = monochrome, > 1.0 = boosted.
temperatureFLOAT65002000–12000White balance in absolute Kelvin, 6500 = no change. RGB is multiplied by the blackbody colour of this temperature: lower values warm the image, higher cool it.
hue_shiftFLOAT0.0-180–180Global hue rotation in degrees. 0 = no change, 180 = complementary hues.
lut_nameCOMBONoneBuilt-in transform applied last, after the grade: display/tone-map curves, linear-to-camera-log encodes, log-to-linear IDTs, or analysis views (False Color, Clip Check). None and the separator do nothing.
lut_intensityFLOAT1.000–1Blend strength of the selected lut_name. 0.0 = bypass, 1.0 = full LUT application.
color_scienceCOMBOLinear (sRGB)Space for offset, lift, gamma and gain. ACEScct converts linear sRGB to ACEScct, applies them there and converts back; the other controls stay linear.

Outputs (1)

NameTypeDescription
imageIMAGE—