natural looking film grain using noise functions
Clone or download
Latest commit 4eea024 Mar 11, 2016
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
shaders update code and samples Jan 26, 2015
.gitignore adding film grain effects Jan 26, 2015
.npmignore update code and samples Jan 26, 2015
LICENSE.md adding film grain effects Jan 26, 2015
README.md version bump Jan 26, 2015
demo.js update code and samples Jan 26, 2015
index.glsl fix division by zero error on some windows devices Mar 11, 2016
index.html adding index Jan 26, 2015
package.json 1.0.4 Mar 11, 2016

README.md

glsl-film-grain

stable

img

(click for demo)

Natural looking film grain using 3D noise functions. Inspired by Martins Upitis.

This is a fairly expensive technique to achieve film grain, but it looks more realistic than a hash function and also produces better motion.

Simplest example:

#pragma glslify: grain = require(glsl-film-grain)

void main() {
    float grainSize = 2.0;
    float g = grain(texCoord, resolution / grainSize);
    vec3 color = vec3(g);
    gl_FragColor = vec4(color, 1.0);
}

Results in:

grain

See blending tips and the demo source for details.

Usage

NPM

f = grain(texCoord, resolution[, frame[, q]])

Returns a float for the monochromatic grain with the given options:

  • texCoord the UV coordinates of your scene
  • resolution the resolution of your scene in pixels, optionally scaled to adjust the grain size
  • frame the animation frame, which is an offset into the Z of the 3D noise
  • q is a coefficient for the offset calculation, and may evoke subtly different motion. Defaults to 2.5

blending tips

There are a lot of ways to blend the noise onto the 3D scene or image. The solution used in the demo uses glsl-blend-soft-light and glsl-luma.

    vec3 g = vec3(grain(texCoord, p));
  
    //blend the noise over the background, 
    //i.e. overlay, soft light, additive
    vec3 color = blend(backgroundColor, g);
    
    //get the luminance of the background
    float luminance = luma(backgroundColor);
    
    //reduce the noise based on some 
    //threshold of the background luminance
    float response = smoothstep(0.05, 0.5, luminance);
    color = mix(color, backgroundColor, pow(response, 2.0));
    
    //final color
    gl_FragColor = vec4(color, 1.0);

License

MIT, see LICENSE.md for details.