Spaces:
Running
Running
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 }; | |