Techniques / paper-grain
Paper grain overlay
A subtle, static noise layer multiplied over the whole frame so flat colors read as a physical surface.
Strength: subtle; somewhere around 0.1–0.25 opacity reads as paper without looking like film grain. Taste decides.
JS (DOM or canvas)
Generate the noise once and tile it. Don't animate it; moving grain reads as film, not paper.
export function paperGrain(strength = 0.18, size = 256) {
const c = document.createElement('canvas');
c.width = c.height = size;
const g = c.getContext('2d');
const img = g.createImageData(size, size);
for (let i = 0; i < img.data.length; i += 4) {
const v = 200 + Math.random() * 55;
img.data[i] = img.data[i + 1] = img.data[i + 2] = v;
img.data[i + 3] = 255;
}
g.putImageData(img, 0, 0);
const overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 9999,
backgroundImage: `url(${c.toDataURL()})`,
mixBlendMode: 'multiply',
opacity: strength,
});
document.body.appendChild(overlay);
}
Unity (URP)
- Make a 256×256 tileable grayscale noise texture (values ~0.78–1.0), import with Wrap: Repeat.
- Full-screen UI
RawImageon a top Screen Space Overlay canvas, raycast target off. - Material:
UI/Default, or a multiply-blend shader for accuracy. Alpha = the strength you chose. - Set
uvRectto(0, 0, Screen.width/256, Screen.height/256)so it tiles at 1:1 pixels.