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 }; |