AM Grade RGB
The same Nuke grade, one slider per channel
- image
- video
- image
- video
AM Grade RGB is AM Grade with the training wheels off. Same Nuke Grade math, same order of operations - but instead of one blackpoint, one gain, one gamma applied to all three channels, you get separate R, G, and B controls for every parameter. 24 float sliders plus the two clamps and the reverse toggle, and yes, it looks like a wall of widgets. That's not a design flaw; it's the point.
It ships in comfyui-am-vfx-tools ("AM VFX Tools/Color" category), Adrian Meyer's 13-node VFX toolkit. Both Grade nodes call the exact same grade_apply function in _core/grade.py - AM Grade broadcasts one value across the channels, AM Grade RGB feeds it a per-channel tensor. Mono vs. RGB is purely a UI decision.
When you actually need per-channel
You don't need it for "make the whole frame brighter" - that's AM Grade. You need it when the problem is in one channel:
- Skin tones - the classic. Reds are too hot but you don't want to touch the rest of the frame.
- Bad white balance - a magenta cast is really "too much blue channel / not enough green"; fix it per-channel instead of fighting it with saturation.
- Matching a plate - if your generated footage sits next to real footage that was shot under different lighting, per-channel blackpoint/gain is how you match it.
The parameters mirror AM Grade exactly: blackpoint_r/g/b, whitepoint_r/g/b, lift_r/g/b, gain_r/g/b, multiply_r/g/b, offset_r/g/b, gamma_r/g/b, then reverse, black_clamp, white_clamp. The tooltip-less fields are self-explanatory once you've seen the mono version.
The mechanism, briefly
The math is identical to AM Grade, computed per channel:
A = multiply * (gain - lift) / (whitepoint - blackpoint)
B = offset + lift - A * blackpoint
out = sign(A*x + B) * pow(|A*x + B|, 1/gamma)
Sign-preserving pow so negative values don't produce NaN, black_clamp on by default (clips negatives to 0), white_clamp off by default (lets scene-linear highlights above 1.0 live). Pure torch, per-pixel, alpha-preserving.
Inputs: image and optional video (lazy per-frame, alpha untouched, image ignored when video is wired). Outputs: image (same shape/channels) and video.
Installing it
Same single install as the rest of the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/am-pipeline-prod/comfyui-am-vfx-tools.git
cd comfyui-am-vfx-tools
pip install -r requirements.txt
Restart ComfyUI, or search comfyui-am-vfx-tools in ComfyUI Manager.
Where people get burned
Same scene-linear assumption as AM Grade - blackpoint/whitepoint of 0/1 expect linear float data, so feed it color-managed input. And a workflow-ergonomics warning: 24 sliders is a lot of state to save in a workflow JSON and a lot to bisect when something looks wrong. My honest advice: start with AM Grade, get the grade close, and only drop into AM Grade RGB when a single channel is actually misbehaving. If you're reaching for the RGB version to fix everything, you're probably solving the wrong problem - that's what white balance and a color match are for.
Inputs (26)
| Name | Type | Default | Description |
|---|---|---|---|
| blackpoint_r | FLOAT | 0.000 | — |
| blackpoint_g | FLOAT | 0.000 | — |
| blackpoint_b | FLOAT | 0.000 | — |
| whitepoint_r | FLOAT | 1.000 | — |
| whitepoint_g | FLOAT | 1.000 | — |
| whitepoint_b | FLOAT | 1.000 | — |
| lift_r | FLOAT | 0.000 | — |
| lift_g | FLOAT | 0.000 | — |
| lift_b | FLOAT | 0.000 | — |
| gain_r | FLOAT | 1.000 | — |
| gain_g | FLOAT | 1.000 | — |
| gain_b | FLOAT | 1.000 | — |
| multiply_r | FLOAT | 1.000 | — |
| multiply_g | FLOAT | 1.000 | — |
| multiply_b | FLOAT | 1.000 | — |
| offset_r | FLOAT | 0.000 | — |
| offset_g | FLOAT | 0.000 | — |
| offset_b | FLOAT | 0.000 | — |
| gamma_r | FLOAT | 1.000 | — |
| gamma_g | FLOAT | 1.000 | — |
| gamma_b | FLOAT | 1.000 | — |
| reverse | BOOLEAN | false | — |
| black_clamp | BOOLEAN | true | — |
| white_clamp | BOOLEAN | false | — |
| imageopt | IMAGE | Image batch to grade. | |
| videoopt | VIDEO | Optional VIDEO input. When wired, returns a lazy `GradedVideo` wrapper applying the grade per-frame on consumption — no IMAGE materialisation here. Alpha (when present) passes through untouched. `image` is ignored when `video` is wired. See invariant 28. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Graded image batch (same shape and channels as the input). |
| video | VIDEO | Lazy VIDEO output — emits a `GradedVideo` wrapper when `video` is wired, else a zero-copy `VideoFromComponents` around the IMAGE batch. None when no input is wired. |