/**
* @author alteredq / http://alteredqualia.com/
*/
/**
* 后处理,效果组合器
* @param {WebGLRenderer} renderer 渲染器
* @param {WebGLRenderTarget} renderTarget 渲染目标
*/
THREE.EffectComposer = function ( renderer, renderTarget ) {
this.renderer = renderer;
//如果没有传入渲染目标,内部创建
if ( renderTarget === undefined ) {
var parameters = {
//线性滤波
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
//rgba四个通道
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';
}
//创建两张渲染目标,pingpong处理
this.renderTarget1 = renderTarget;
this.renderTarget2 = renderTarget.clone();
this.renderTarget2.texture.name = 'EffectComposer.rt2';
//设定读写缓冲
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
//pass列表
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' );
}
//拷贝pass,简单的渲染目标拷贝
this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
//时间
this._previousFrameTime = Date.now();
};
/**
* 定义EffectComposer的原型
*/
Object.assign( THREE.EffectComposer.prototype, {
/**
* 切换读、写渲染目标
*/
swapBuffers: function () {
var tmp = this.readBuffer;
this.readBuffer = this.writeBuffer;
this.writeBuffer = tmp;
},
/**
* 添加渲染过程
* @param {Pass} pass 渲染过程
*/
addPass: function ( pass ) {
//添加到渲染列表中
this.passes.push( pass );
//获取画布的大小,设置pass
var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
pass.setSize( size.width, size.height );
},
/**
* 插入渲染过程
* @param {Pass} pass 渲染过程
* @param {Int} index 渲染列表索引
*/
insertPass: function ( pass, index ) {
this.passes.splice( index, 0, pass );
},
/**
* 渲染场景
* @param {float} deltaTime 每一帧之间的时间间隔(秒)
*/
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.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
//下一个渲染过程到来时是否切换渲染目标
if ( pass.needsSwap ) {
//模板掩码是否激活
if ( maskActive ) {
//获取渲染上下文
var context = this.renderer.context;
//设置模板函数,不为1可以通过
context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
//拷贝读、写渲染目标
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
//设置模板函数,为1可以通过
context.stencilFunc( context.EQUAL, 1, 0xffffffff );
}
//切换缓冲
this.swapBuffers();
}
//如果引入了MaskPass类
if ( THREE.MaskPass !== undefined ) {
if ( pass instanceof THREE.MaskPass ) { //当前的pass是MaskPass
//激活
maskActive = true;
} else if ( pass instanceof THREE.ClearMaskPass ) { //当前的pass是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 );
}
}
} );
/**
* 渲染pass基类
*/
THREE.Pass = function () {
// if set to true, the pass is processed by the composer
// 是否启用pass
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.renderToScreen = false;
};
/**
* 定义Pass原型
*/
Object.assign( THREE.Pass.prototype, {
/**
* 设置画布的宽、高
* @param {Int} width
* @param {Int} height
*/
setSize: function ( width, height ) {},
/**
*
* @param {WebGLRenderer} renderer 渲染器
* @param {WebGLRenderTarget} writeBuffer 写渲染目标
* @param {WebGLRenderTarget} readBuffer 读渲染目标
* @param {float} deltaTime 时间间隔
* @param {boolean} maskActive 激活遮罩
*/
render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
}
} );