Skip to content

Instantly share code, notes, and snippets.

@halldorel
Created June 19, 2019 20:35
Show Gist options
  • Save halldorel/2b9bee4dcd503ea4b6dd19e2c373033c to your computer and use it in GitHub Desktop.
Save halldorel/2b9bee4dcd503ea4b6dd19e2c373033c to your computer and use it in GitHub Desktop.
Inconvergent DOF effect implementation in JS
// Requires npm package canvas-sketch
// Credit: https://inconvergent.net/2019/depth-of-field/
const canvasSketch = require('canvas-sketch');
const settings = {
dimensions: [ 2000, 2000 ]
};
const points = [[[500, 500, 0], [1700, 700, 200]], [[1700, 700, 200], [900, 1000, 0]], ];
const camera = [0, 0, 0];
const focus = 1500;
const passes = 4000;
const m = 0.2; // DOF size
const e = 1; // distribution of samples inside sphere
const dst = (a, b) => {
return Math.sqrt(Math.pow(b[0] - a[0], 2)
+ Math.pow(b[1] - a[1], 2)
+ Math.pow(b[2] - a[2], 2));
};
const lerp = (a, b, s) => {
return [a[0] + s * (b[0] - a[0]),
a[1] + s * (b[1] - a[1]),
a[2] + s * (b[2] - a[2])];
}
const rnd = () => {
return Math.random();
}
const add = (a, b) => {
return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
}
const rndSphere = (r) => {
return [r*rnd(), r*rnd(), r*rnd()];
}
const to2D = (v) => {
return [v[0], v[1]];
}
const sketch = () => {
return ({ context, width, height }) => {
context.fillStyle = 'black';
context.fillRect(0, 0, width, height);
context.fillStyle = 'rgba(255, 255, 255, 0.2)';
for(var i = 0; i < points.length; i++) {
let line = points[i];
for(var j = 0; j < passes; j++) {
let v = lerp(line[0], line[1], rnd());
let d = dst(v, camera);
let sampleRadius = m * Math.pow(Math.abs(focus - d), e);
let w = add(v, rndSphere(sampleRadius));
let point = to2D(w);
context.fillRect(point[0], point[1], 3, 3);
}
}
};
};
canvasSketch(sketch, settings);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment