Spaces:
Running
Running
/** | |
* @author alteredq / http://alteredqualia.com/ | |
*/ | |
THREE.EffectComposer = function ( renderer, renderTarget ) { | |
this.renderer = renderer; | |
if ( renderTarget === undefined ) { | |
var parameters = { | |
minFilter: THREE.LinearFilter, | |
magFilter: THREE.LinearFilter, | |
format: THREE.RGBAFormat, | |
stencilBuffer: false | |
}; | |
var size = renderer.getDrawingBufferSize( new THREE.Vector2() ); | |
renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters ); | |
renderTarget.texture.name = 'EffectComposer.rt1'; | |
} | |
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 = []; | |
// dependencies | |
if ( THREE.CopyShader === undefined ) { | |
console.error( 'THREE.EffectComposer relies on THREE.CopyShader' ); | |
} | |
if ( THREE.ShaderPass === undefined ) { | |
console.error( 'THREE.EffectComposer relies on THREE.ShaderPass' ); | |
} | |
this.copyPass = new THREE.ShaderPass( THREE.CopyShader ); | |
this._previousFrameTime = Date.now(); | |
}; | |
Object.assign( THREE.EffectComposer.prototype, { | |
swapBuffers: function () { | |
var tmp = this.readBuffer; | |
this.readBuffer = this.writeBuffer; | |
this.writeBuffer = tmp; | |
}, | |
addPass: function ( pass ) { | |
this.passes.push( pass ); | |
var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() ); | |
pass.setSize( size.width, size.height ); | |
}, | |
insertPass: function ( pass, index ) { | |
this.passes.splice( index, 0, pass ); | |
}, | |
isLastEnabledPass: function ( passIndex ) { | |
for ( var i = passIndex + 1; i < this.passes.length; i ++ ) { | |
if ( this.passes[ i ].enabled ) { | |
return false; | |
} | |
} | |
return true; | |
}, | |
render: function ( deltaTime ) { | |
// deltaTime value is in seconds | |
if ( deltaTime === undefined ) { | |
deltaTime = ( Date.now() - this._previousFrameTime ) * 0.001; | |
} | |
this._previousFrameTime = Date.now(); | |
var currentRenderTarget = this.renderer.getRenderTarget(); | |
var maskActive = false; | |
var pass, i, il = this.passes.length; | |
for ( i = 0; i < il; i ++ ) { | |
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 ) { | |
var context = this.renderer.context; | |
context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); | |
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime ); | |
context.stencilFunc( context.EQUAL, 1, 0xffffffff ); | |
} | |
this.swapBuffers(); | |
} | |
if ( THREE.MaskPass !== undefined ) { | |
if ( pass instanceof THREE.MaskPass ) { | |
maskActive = true; | |
} else if ( pass instanceof THREE.ClearMaskPass ) { | |
maskActive = false; | |
} | |
} | |
} | |
this.renderer.setRenderTarget( currentRenderTarget ); | |
}, | |
reset: function ( renderTarget ) { | |
if ( renderTarget === undefined ) { | |
var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() ); | |
renderTarget = this.renderTarget1.clone(); | |
renderTarget.setSize( size.width, size.height ); | |
} | |
this.renderTarget1.dispose(); | |
this.renderTarget2.dispose(); | |
this.renderTarget1 = renderTarget; | |
this.renderTarget2 = renderTarget.clone(); | |
this.writeBuffer = this.renderTarget1; | |
this.readBuffer = this.renderTarget2; | |
}, | |
setSize: function ( width, height ) { | |
this.renderTarget1.setSize( width, height ); | |
this.renderTarget2.setSize( width, height ); | |
for ( var i = 0; i < this.passes.length; i ++ ) { | |
this.passes[ i ].setSize( width, height ); | |
} | |
} | |
} ); | |
THREE.Pass = function () { | |
// if set to true, the pass is processed by the composer | |
this.enabled = true; | |
// if set to true, the pass indicates to swap read and write buffer after rendering | |
this.needsSwap = true; | |
// if set to true, the pass clears its buffer before rendering | |
this.clear = false; | |
// if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | |
this.renderToScreen = false; | |
}; | |
Object.assign( THREE.Pass.prototype, { | |
setSize: function ( width, height ) {}, | |
render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { | |
console.error( 'THREE.Pass: .render() must be implemented in derived pass.' ); | |
} | |
} ); | |
// Helper for passes that need to fill the viewport with a single quad. | |
THREE.Pass.FullScreenQuad = ( function () { | |
var camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | |
var geometry = new THREE.PlaneBufferGeometry( 2, 2 ); | |
var FullScreenQuad = function ( material ) { | |
this._mesh = new THREE.Mesh( geometry, material ); | |
}; | |
Object.defineProperty( FullScreenQuad.prototype, 'material', { | |
get: function () { | |
return this._mesh.material; | |
}, | |
set: function ( value ) { | |
this._mesh.material = value; | |
} | |
} ); | |
Object.assign( FullScreenQuad.prototype, { | |
render: function ( renderer ) { | |
renderer.render( this._mesh, camera ); | |
} | |
} ); | |
return FullScreenQuad; | |
} )(); | |