Home Reference Source

src/materials/BokehMaterial.js

import { ShaderMaterial, Uniform } from "three";

import fragment from "./glsl/bokeh/shader.frag";
import vertex from "./glsl/bokeh/shader.vert";

/**
 * Depth of Field shader (Bokeh).
 *
 * Original shader code by Martins Upitis:
 *  http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html
 */

export class BokehMaterial extends ShaderMaterial {

	/**
	 * Constructs a new bokeh material.
	 *
	 * @param {PerspectiveCamera} [camera] - A camera.
	 * @param {Object} [options] - The options.
	 * @param {Number} [options.focus=1.0] - The focus distance, corresponds directly with the scene depth.
	 * @param {Number} [options.dof=0.02] - Depth of field. An area in front of and behind the focus point that still appears sharp.
	 * @param {Number} [options.aperture=0.025] - Camera aperture scale. Bigger values for stronger blur and shallower depth of field.
	 * @param {Number} [options.maxBlur=1.0] - Maximum blur strength.
	 */

	constructor(camera, options = {}) {

		const settings = Object.assign({
			focus: 1.0,
			dof: 0.02,
			aperture: 0.025,
			maxBlur: 1.0
		}, options);

		super({

			type: "BokehMaterial",

			uniforms: {

				cameraNear: new Uniform(0.1),
				cameraFar: new Uniform(2000),
				aspect: new Uniform(1.0),

				tDiffuse: new Uniform(null),
				tDepth: new Uniform(null),

				focus: new Uniform(settings.focus),
				dof: new Uniform(settings.dof),
				aperture: new Uniform(settings.aperture),
				maxBlur: new Uniform(settings.maxBlur)

			},

			fragmentShader: fragment,
			vertexShader: vertex,

			depthWrite: false,
			depthTest: false

		});

		this.adoptCameraSettings(camera);

	}

	/**
	 * Adopts the settings of the given camera.
	 *
	 * @param {PerspectiveCamera} [camera=null] - A camera.
	 */

	adoptCameraSettings(camera = null) {

		if(camera !== null) {

			this.uniforms.cameraNear.value = camera.near;
			this.uniforms.cameraFar.value = camera.far;
			this.uniforms.aspect.value = camera.aspect;

		}

	}

}