Better Film Grain
Film grain that doesn't look like RGB static
- image
- IMAGE
Grain is one of the cheapest tricks in the photorealism toolbox - a clean AI image with a bit of noise on top reads as "captured," not "generated," the same instinct behind Amateur Photography LoRAs and "point-and-shoot film camera" prompt phrases. Most grain nodes fake it with per-pixel RGB noise, which looks like sensor static, not film. BetterFilmGrain, per the author, is "yet another film grain node, but this one looks better" - realistic grain structure, no pixel-perfect RGB glitter, a natural luminance response - and it's 10x faster than the previous best option in the ecosystem (ProPostFilmGrain).
The difference is that real film grain isn't uniform colored noise. It clumps, it's mostly a luminance effect rather than a per-channel color effect, and its visibility shifts with how bright or dark the underlying image is. This node models those properties instead of just adding noise and calling it done.
The controls, and what each one is actually doing
image(IMAGE) - required.scale(default 0.5, 0.25–2) - grain particle size. Think of it like film stock speed: smaller scale reads as fine-grained slower film, larger scale gives you the chunkier look of a fast/high-ISO stock.strength(default 0.5, 0–10) - how visible the grain is overall. The default is subtle on purpose; push it up for an obvious vintage look.saturation(default 0.7, 0–2) - how colored the grain is. Real film grain is mostly luminance noise, so a lower value here keeps it looking like grain instead of chroma static; push it toward 2 if you specifically want colored noise.toe(default 0, -0.2–0.5) - a photographic term for how a film stock rolls off in the shadows. Positive values lift the darkest tones instead of letting them crush to pure black, which is part of what makes real film shadows look softer than a digital sensor's.seed(INT) - controls the grain pattern. Same seed, same grain - lock it if you need a consistent grain look across a batch or an animation frame sequence.
One output: IMAGE.
How to install it
ComfyUI Manager: search "ComfyUI-Image-Filters", install, restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/spacepxl/ComfyUI-Image-Filters
restart ComfyUI. Dependency is OpenCV - opencv-contrib-python is all you need; if you hit a cv2 import error it's almost always another node pack's conflicting opencv install rather than this pack. The author's install.bat / import_error_install.bat handle that on Windows; manually it's uninstall the stray opencv variants and install opencv-contrib-python on its own. No models, no real VRAM cost.
Common issues & troubleshooting
Grain looks like noise, not film. Drop saturation - colored grain reads as sensor noise or compression artifacts, not film. Real film grain leans heavily luminance-only.
Shadows look too crushed / too flat for the vintage look you want. That's exactly what toe is for - nudge it positive to lift the blacks slightly, which is what gives scanned film its characteristic soft-shadow look instead of digital's harder black point.
Effect barely visible at default settings. That's deliberate - strength defaults to a subtle 0.5. It's a "make it pop" pass meant to be the last thing you do before saving, not something you'd want overpowering the image by default; turn it up as far as the look calls for.
Grain pattern is identical across a batch when you wanted variation. Vary seed per image if you're processing a batch and want each frame's grain to be independent rather than identical.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| scale | FLOAT | 0.500.25–2 | — |
| strength | FLOAT | 0.500–10 | — |
| saturation | FLOAT | 0.700–2 | — |
| toe | FLOAT | 0.000-0.2–0.5 | — |
| seed | INT | 00–18446744073709550000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |