/** * Depth-of-field post-process with bokeh shader */ THREE.BokehPass = function ( scene, camera, params ) { THREE.Pass.call( this ); this.scene = scene; this.camera = camera; var focus = ( params.focus !== undefined ) ? params.focus : 1.0; var aspect = ( params.aspect !== undefined ) ? params.aspect : camera.aspect; var aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025; var maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0; // render targets var width = params.width || window.innerWidth || 1; var height = params.height || window.innerHeight || 1; this.renderTargetColor = new THREE.WebGLRenderTarget( width, height, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat } ); this.renderTargetDepth = this.renderTargetColor.clone(); // depth material this.materialDepth = new THREE.MeshDepthMaterial(); // bokeh material if ( THREE.BokehShader === undefined ) { console.error( "THREE.BokehPass relies on THREE.BokehShader" ); } var bokehShader = THREE.BokehShader; var bokehUniforms = THREE.UniformsUtils.clone( bokehShader.uniforms ); bokehUniforms[ "tDepth" ].value = this.renderTargetDepth.texture; bokehUniforms[ "focus" ].value = focus; bokehUniforms[ "aspect" ].value = aspect; bokehUniforms[ "aperture" ].value = aperture; bokehUniforms[ "maxblur" ].value = maxblur; this.materialBokeh = new THREE.ShaderMaterial( { uniforms: bokehUniforms, vertexShader: bokehShader.vertexShader, fragmentShader: bokehShader.fragmentShader } ); this.uniforms = bokehUniforms; this.needsSwap = false; this.camera2 = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); this.scene2 = new THREE.Scene(); this.quad2 = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null ); this.quad2.frustumCulled = false; // Avoid getting clipped this.scene2.add( this.quad2 ); }; THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), { constructor: THREE.BokehPass, render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) { this.quad2.material = this.materialBokeh; // Render depth into texture this.scene.overrideMaterial = this.materialDepth; renderer.render( this.scene, this.camera, this.renderTargetDepth, true ); // Render bokeh composite this.uniforms[ "tColor" ].value = readBuffer.texture; if ( this.renderToScreen ) { renderer.render( this.scene2, this.camera2 ); } else { renderer.render( this.scene2, this.camera2, writeBuffer, this.clear ); } this.scene.overrideMaterial = null; } } );