You prompt 35mm film photograph of a coffee shop and the output is suspiciously clean — perfectly smooth gradients, zero grain, dead pixels of pure color in shadows. It reads as a CG render of a photo rather than an actual photo. This is a model-defaults problem: SDXL, Flux, and Midjourney v6+ all bias toward smooth rendering because their training data is heavy on cleaned-up stock photos and digital images. Real grain — the random luminance noise from silver halide crystals or high-ISO sensors — has to be explicitly summoned.
The fix is to anchor to a specific film stock, weight the grain term, and if the result still looks too clean, add grain in img2img at low denoise or in post-processing.
Common causes
Ordered by hit rate, highest first.
1. Generic “film” or “analog” word without a stock
film photo, analog, vintage photograph are too vague. The model averages across both clean digital scans of old photos and actually-grainy negatives, and the clean average usually wins.
How to spot it: prompt says film but no film-stock name (Kodak Portra, Fuji Pro, etc.) is present.
2. Render resolution too low
At 768x768 or below, grain detail is lost in the latent compression. The model “rounds away” the noise pattern because it cannot represent it cleanly.
How to spot it: same prompt at 1024x1024 has visible grain, but 768x768 does not.
3. Wrong sampler / too many steps
DPM++ 2M Karras at 50 steps produces very clean output by construction — the denoiser fully removes noise. For grain, you actually want a slightly under-denoised result.
How to spot it: 50+ steps with a high-quality sampler. Try 25 steps and see if grain returns.
4. Post-pipeline upscaler smooths grain
ESRGAN, 4x-UltraSharp, and especially SwinIR_4x aggressively smooth grain when upscaling. They were trained on clean datasets and treat grain as noise to remove.
How to spot it: pre-upscale image has grain, post-upscale does not.
5. JPEG export at low quality
Saving as JPEG at quality 75 or below quantizes grain into blocky artifacts that the eye reads as “no texture.”
How to spot it: check file size — if a 1024x1024 photo JPEG is under 200KB, quality is too aggressive.
Shortest path to fix
Step 1: Use a specific film stock name
The training data has strong associations for specific stocks. Replace film photo with one of:
Kodak Portra 400 (warm skin, soft grain, classic editorial)
Kodak Tri-X 400 (classic black-and-white, punchy grain)
Fujifilm Pro 400H (cool tones, fine grain, wedding favorite)
Fujifilm Velvia 50 (saturated, very fine grain, landscape)
Cinestill 800T (tungsten balance, dreamy halation, neon nights)
Ilford HP5 (black-and-white, gritty, photojournalism)
Kodak Gold 200 (warm, slight grain, vacation snapshot)
These all carry distinct grain characteristics in the training set.
Step 2: Weight grain explicitly
Add to prompt:
(film grain:0.8), (visible grain:0.7), (analog noise:0.6),
35mm film, slight noise in shadows, organic grain pattern, ISO 800
The weight values 0.6-0.8 are loud enough to be noticed without dominating composition. Above 1.0 the grain becomes a visual artifact rather than a texture.
Step 3: Negative-prompt the clean look (SD-family)
digital, clean, smooth, noise-free, CGI, 3d render, ultra clean,
no grain, perfect smooth gradient, plastic, oversharpened
This actively repels the smooth-render bias.
Step 4: Skip aggressive upscalers
Replace ESRGAN or SwinIR with grain-friendly upscalers:
4x_NMKD-Siax (preserves grain better)
4x_RealisticRescaler (designed for photo realism, keeps texture)
4x_foolhardy_Remacri (mild, preserves micro-detail)
Or upscale via img2img at low denoise (0.2-0.3) with the same prompt — this re-generates the upscale through the diffusion model, which can re-introduce grain rather than averaging it out.
Step 5: Add grain in post if still missing
When all else fails, fake the grain in post:
Photoshop: Filter > Camera Raw > Effects > Grain. Amount 25, Size 25, Roughness 50
Lightroom: Effects > Grain. Amount 25, Size 25, Roughness 50
Affinity: Filters > Noise > Add Noise, 2.5% Gaussian, Monochromatic
DaVinci Resolve (for video): Effects > Film Grain > 35mm Kodak
Or use the free Gimp HSV Noise filter at 5% value-only noise. Post-grain is preferable to a fully clean render shipping as a “film photo.”
Prevention
- Maintain a list of 5 favorite film stocks and rotate through them by mood
- Default film grain weight in your portrait preset:
(film grain:0.7) - Never upscale with ESRGAN for grainy looks — use NMKD or Remacri instead
- Render at 1024x1024 minimum for any photo prompt; never lower
- Save final JPEGs at quality 92+ or use PNG for grainy renders to preserve texture