Spaces:
Running
Running
import { | |
Clock, | |
HalfFloatType, | |
NoBlending, | |
Vector2, | |
WebGLRenderTarget | |
} from 'three'; | |
import { CopyShader } from '../shaders/CopyShader.js'; | |
import { ShaderPass } from './ShaderPass.js'; | |
import { ClearMaskPass, MaskPass } from './MaskPass.js'; | |
class EffectComposer { | |
constructor( renderer, renderTarget ) { | |
this.renderer = renderer; | |
this._pixelRatio = renderer.getPixelRatio(); | |
if ( renderTarget === undefined ) { | |
const size = renderer.getSize( new Vector2() ); | |
this._width = size.width; | |
this._height = size.height; | |
renderTarget = new WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType } ); | |
renderTarget.texture.name = 'EffectComposer.rt1'; | |
} else { | |
this._width = renderTarget.width; | |
this._height = renderTarget.height; | |
} | |
this.renderTarget1 = renderTarget; | |
this.renderTarget2 = renderTarget.clone(); | |
this.renderTarget2.texture.name = 'EffectComposer.rt2'; | |
this.writeBuffer = this.renderTarget1; | |
this.readBuffer = this.renderTarget2; | |
this.renderToScreen = true; | |
this.passes = []; | |
this.copyPass = new ShaderPass( CopyShader ); | |
this.copyPass.material.blending = NoBlending; | |
this.clock = new Clock(); | |
} | |
swapBuffers() { | |
const tmp = this.readBuffer; | |
this.readBuffer = this.writeBuffer; | |
this.writeBuffer = tmp; | |
} | |
addPass( pass ) { | |
this.passes.push( pass ); | |
pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); | |
} | |
insertPass( pass, index ) { | |
this.passes.splice( index, 0, pass ); | |
pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); | |
} | |
removePass( pass ) { | |
const index = this.passes.indexOf( pass ); | |
if ( index !== - 1 ) { | |
this.passes.splice( index, 1 ); | |
} | |
} | |
isLastEnabledPass( passIndex ) { | |
for ( let i = passIndex + 1; i < this.passes.length; i ++ ) { | |
if ( this.passes[ i ].enabled ) { | |
return false; | |
} | |
} | |
return true; | |
} | |
render( deltaTime ) { | |
// deltaTime value is in seconds | |
if ( deltaTime === undefined ) { | |
deltaTime = this.clock.getDelta(); | |
} | |
const currentRenderTarget = this.renderer.getRenderTarget(); | |
let maskActive = false; | |
for ( let i = 0, il = this.passes.length; i < il; i ++ ) { | |
const pass = this.passes[ i ]; | |
if ( pass.enabled === false ) continue; | |
pass.renderToScreen = ( this.renderToScreen && this.isLastEnabledPass( i ) ); | |
pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive ); | |
if ( pass.needsSwap ) { | |
if ( maskActive ) { | |
const context = this.renderer.getContext(); | |
const stencil = this.renderer.state.buffers.stencil; | |
//context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); | |
stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff ); | |
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime ); | |
//context.stencilFunc( context.EQUAL, 1, 0xffffffff ); | |
stencil.setFunc( context.EQUAL, 1, 0xffffffff ); | |
} | |
this.swapBuffers(); | |
} | |
if ( MaskPass !== undefined ) { | |
if ( pass instanceof MaskPass ) { | |
maskActive = true; | |
} else if ( pass instanceof ClearMaskPass ) { | |
maskActive = false; | |
} | |
} | |
} | |
this.renderer.setRenderTarget( currentRenderTarget ); | |
} | |
reset( renderTarget ) { | |
if ( renderTarget === undefined ) { | |
const size = this.renderer.getSize( new Vector2() ); | |
this._pixelRatio = this.renderer.getPixelRatio(); | |
this._width = size.width; | |
this._height = size.height; | |
renderTarget = this.renderTarget1.clone(); | |
renderTarget.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); | |
} | |
this.renderTarget1.dispose(); | |
this.renderTarget2.dispose(); | |
this.renderTarget1 = renderTarget; | |
this.renderTarget2 = renderTarget.clone(); | |
this.writeBuffer = this.renderTarget1; | |
this.readBuffer = this.renderTarget2; | |
} | |
setSize( width, height ) { | |
this._width = width; | |
this._height = height; | |
const effectiveWidth = this._width * this._pixelRatio; | |
const effectiveHeight = this._height * this._pixelRatio; | |
this.renderTarget1.setSize( effectiveWidth, effectiveHeight ); | |
this.renderTarget2.setSize( effectiveWidth, effectiveHeight ); | |
for ( let i = 0; i < this.passes.length; i ++ ) { | |
this.passes[ i ].setSize( effectiveWidth, effectiveHeight ); | |
} | |
} | |
setPixelRatio( pixelRatio ) { | |
this._pixelRatio = pixelRatio; | |
this.setSize( this._width, this._height ); | |
} | |
dispose() { | |
this.renderTarget1.dispose(); | |
this.renderTarget2.dispose(); | |
this.copyPass.dispose(); | |
} | |
} | |
export { EffectComposer }; | |