RC Film Grain
Film grain that respects your highlights
- image
- image
- grain_map
Add noise to a render and you get texture - but it's flat texture. Real film grain isn't flat. It piles up in the shadows, thins out in the highlights, and reads differently on skin than on a bright sky. RC Film Grain is the node that understands this: it generates grain, then modulates that grain by the luminance of the image, so dark areas get more of it and bright areas stay cleaner. It's the difference between "I put a filter on this" and "this looks like it was shot on film."
It's one of the more grown-up nodes in the RC Image Compositor pack, with a control set that starts to feel like a real film emulation plugin rather than a noise generator.
How it works
Under the hood it's a two-layer operation. The node builds a grain layer, computes a luminance mask from the image, and uses that mask to scale how much grain lands in each tone. Then it blends the grain layer into the image with a Photoshop-style blend mode - overlay by default, with add, screen, soft_light, and linear_dodge as alternatives. Because the grain is a separate layer with its own blend math, you get natural-looking texture rather than a random-value paste.
The luminance_response slider is the heart of it: 0.0 gives uniform grain, 1.0 gives the realistic film curve (more in shadows, less in highlights), 2.0 pushes it to extremes. grain_midtone and highlight_protection are the fine-tuning handles - think of them like the midtone and black-point sliders on a Levels node, but controlling where grain lives instead of where tones clip.
The inputs that matter
- image - input tensor.
- intensity - overall grain strength (0–1). 0.15 default is tasteful; go higher for a gritty look.
- grain_size - 0.3 to 3. Smaller is finer. Bigger reads as coarse, chunky grain.
- luminance_response - the shadow/highlight grain distribution described above.
- monochrome - on (default) gives clean grayscale grain; off gives chromatic color grain like expired color film.
- blend_mode -
overlayis your natural default;screenis softer;linear_dodgegets glowy. - seed - set this for reproducible grain, so the same frame with the same seed gets the same texture. Important for video.
It outputs two things: the grained image, and a grain_map MASK showing where grain was applied - handy if you want to composite or inspect the effect.
How to install it
Part of the RC Image Compositor pack:
cd ComfyUI/custom_nodes
git clone https://github.com/kj863257/ComfyUI_RC_Image_Compositor
cd ComfyUI_RC_Image_Compositor
pip install -r requirements.txt
Restart ComfyUI, or search "RC Image Compositor" in ComfyUI Manager. Dependencies are light: pillow, numpy, opencv-python.
Common issues
The typical failure is dialing intensity to 0.4+ and wondering why everything looks like static. Real film grain is faint; if you want it to read, strengthen the shadow-side grain with luminance_response and grain_midtone instead of hammering the global intensity.
If you're doing video, set a fixed seed or your grain will shimmer between frames - that dancing static is the single most obvious tell of an AI-processed clip. And if your target image already has a baked-in denoise smoothness, run this after your color grade, not before, or the grade will smear the grain you just added.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| intensity | FLOAT | 0.150–1 | Overall grain intensity (0=no grain, 1.0=heavy grain) |
| grain_size | FLOAT | 1.00.3–3 | Grain particle size (smaller = finer grain, larger = coarser grain) |
| luminance_response | FLOAT | 1.00–2 | Luminance-based grain variation: - 0.0: Uniform grain across all tones - 1.0: Realistic film (DARKER areas get MORE grain, BRIGHTER areas get LESS grain) - 2.0: Extreme film grain (maximum grain in shadows, minimal in highlights) |
| grain_midtone | FLOAT | 0.500–1 | Grain distribution midtone (similar to Levels midtone slider): - 0.5: Standard distribution - <0.5: Pull midtones darker (MORE areas get grain) - >0.5: Pull midtones brighter (FEWER areas get grain, protect highlights) |
| highlight_protection | FLOAT | 0.000–1 | Additional highlight protection (applies after midtone adjustment): - 0.0: No additional protection - 0.5: Moderate black compression (stronger highlight protection) - 1.0: Maximum black compression (only deepest shadows get grain) |
| grain_opacity | FLOAT | 1.000–1 | Grain layer opacity (final blend strength): - 0.0: No grain visible - 0.5: 50% grain blend - 1.0: Full grain effect |
| grain_blur | FLOAT | 0.00–5 | Blur applied to grain layer (soften grain): - 0.0: No blur (sharp grain) - 1.0: Slight softening - 3.0+: Very soft, subtle grain |
| monochrome | BOOLEAN | true | Monochrome grain (true for B&W film look, false for color film with chromatic grain) |
| blend_mode | COMBO | overlay | Grain blending mode: - add: Direct addition (strong, visible) - screen: Film-like brightening (soft, subtle) - overlay: Photoshop overlay (natural contrast) - soft_light: Photoshop soft light (gentle, smooth) - linear_dodge: Linear brightening (bright, glowy) |
| seed | INT | 00–18446744073709550000 | Random seed for reproducible grain patterns |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| grain_map | MASK | — |