three.js 源码分析之EffectComposer

/**

 * @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.' );

 

    }

 

} );

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值