142 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import {
 | |
| 	Color,
 | |
| 	HalfFloatType,
 | |
| 	MeshDepthMaterial,
 | |
| 	NearestFilter,
 | |
| 	NoBlending,
 | |
| 	RGBADepthPacking,
 | |
| 	ShaderMaterial,
 | |
| 	UniformsUtils,
 | |
| 	WebGLRenderTarget
 | |
| } from 'three';
 | |
| import { Pass, FullScreenQuad } from './Pass.js';
 | |
| import { BokehShader } from '../shaders/BokehShader.js';
 | |
| 
 | |
| /**
 | |
|  * Depth-of-field post-process with bokeh shader
 | |
|  */
 | |
| 
 | |
| class BokehPass extends Pass {
 | |
| 
 | |
| 	constructor( scene, camera, params ) {
 | |
| 
 | |
| 		super();
 | |
| 
 | |
| 		this.scene = scene;
 | |
| 		this.camera = camera;
 | |
| 
 | |
| 		const focus = ( params.focus !== undefined ) ? params.focus : 1.0;
 | |
| 		const aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025;
 | |
| 		const maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0;
 | |
| 
 | |
| 		// render targets
 | |
| 
 | |
| 		this.renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later
 | |
| 			minFilter: NearestFilter,
 | |
| 			magFilter: NearestFilter,
 | |
| 			type: HalfFloatType
 | |
| 		} );
 | |
| 
 | |
| 		this.renderTargetDepth.texture.name = 'BokehPass.depth';
 | |
| 
 | |
| 		// depth material
 | |
| 
 | |
| 		this.materialDepth = new MeshDepthMaterial();
 | |
| 		this.materialDepth.depthPacking = RGBADepthPacking;
 | |
| 		this.materialDepth.blending = NoBlending;
 | |
| 
 | |
| 		// bokeh material
 | |
| 
 | |
| 		const bokehShader = BokehShader;
 | |
| 		const bokehUniforms = UniformsUtils.clone( bokehShader.uniforms );
 | |
| 
 | |
| 		bokehUniforms[ 'tDepth' ].value = this.renderTargetDepth.texture;
 | |
| 
 | |
| 		bokehUniforms[ 'focus' ].value = focus;
 | |
| 		bokehUniforms[ 'aspect' ].value = camera.aspect;
 | |
| 		bokehUniforms[ 'aperture' ].value = aperture;
 | |
| 		bokehUniforms[ 'maxblur' ].value = maxblur;
 | |
| 		bokehUniforms[ 'nearClip' ].value = camera.near;
 | |
| 		bokehUniforms[ 'farClip' ].value = camera.far;
 | |
| 
 | |
| 		this.materialBokeh = new ShaderMaterial( {
 | |
| 			defines: Object.assign( {}, bokehShader.defines ),
 | |
| 			uniforms: bokehUniforms,
 | |
| 			vertexShader: bokehShader.vertexShader,
 | |
| 			fragmentShader: bokehShader.fragmentShader
 | |
| 		} );
 | |
| 
 | |
| 		this.uniforms = bokehUniforms;
 | |
| 
 | |
| 		this.fsQuad = new FullScreenQuad( this.materialBokeh );
 | |
| 
 | |
| 		this._oldClearColor = new Color();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {
 | |
| 
 | |
| 		// Render depth into texture
 | |
| 
 | |
| 		this.scene.overrideMaterial = this.materialDepth;
 | |
| 
 | |
| 		renderer.getClearColor( this._oldClearColor );
 | |
| 		const oldClearAlpha = renderer.getClearAlpha();
 | |
| 		const oldAutoClear = renderer.autoClear;
 | |
| 		renderer.autoClear = false;
 | |
| 
 | |
| 		renderer.setClearColor( 0xffffff );
 | |
| 		renderer.setClearAlpha( 1.0 );
 | |
| 		renderer.setRenderTarget( this.renderTargetDepth );
 | |
| 		renderer.clear();
 | |
| 		renderer.render( this.scene, this.camera );
 | |
| 
 | |
| 		// Render bokeh composite
 | |
| 
 | |
| 		this.uniforms[ 'tColor' ].value = readBuffer.texture;
 | |
| 		this.uniforms[ 'nearClip' ].value = this.camera.near;
 | |
| 		this.uniforms[ 'farClip' ].value = this.camera.far;
 | |
| 
 | |
| 		if ( this.renderToScreen ) {
 | |
| 
 | |
| 			renderer.setRenderTarget( null );
 | |
| 			this.fsQuad.render( renderer );
 | |
| 
 | |
| 		} else {
 | |
| 
 | |
| 			renderer.setRenderTarget( writeBuffer );
 | |
| 			renderer.clear();
 | |
| 			this.fsQuad.render( renderer );
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		this.scene.overrideMaterial = null;
 | |
| 		renderer.setClearColor( this._oldClearColor );
 | |
| 		renderer.setClearAlpha( oldClearAlpha );
 | |
| 		renderer.autoClear = oldAutoClear;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	setSize( width, height ) {
 | |
| 
 | |
| 		this.materialBokeh.uniforms[ 'aspect' ].value = width / height;
 | |
| 
 | |
| 		this.renderTargetDepth.setSize( width, height );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	dispose() {
 | |
| 
 | |
| 		this.renderTargetDepth.dispose();
 | |
| 
 | |
| 		this.materialDepth.dispose();
 | |
| 		this.materialBokeh.dispose();
 | |
| 
 | |
| 		this.fsQuad.dispose();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| export { BokehPass };
 |