/** * @author alteredq / http://alteredqualia.com/ */ import * as THREE from "../../../../libs/three.js/build/three.module.js"; import CopyShader from './CopyShader' import {ShaderPass} from './ShaderPass' import { MaskPass, ClearMaskPass } from './MaskPass.js'; var 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.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 ShaderPass( CopyShader ); viewer.addEventListener('resize',(e)=>{ //readTarget的话是渲染一整张的,暂时无法一个个viewport渲染所以不用 this.readTarget || this.setSize(e.viewport.resolution2.x,e.viewport.resolution2.y) //暂时假设composer渲染的viewer的viewports.length == 1 }) }; Object.assign( 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 ); }, removePass: function(pass){ //add let index = this.passes.indexOf(pass); index > -1 && this.passes.splice(index,1) }, insertPass: function ( pass, index ) { this.passes.splice( index, 0, pass ); }, render: function ( scene, camera, viewports, renderFun ) { var maskActive = false; let passes = this.passes.filter(e=>e.enabled) var pass, i, il = passes.length; let oldTarget = this.renderer.getRenderTarget(); if(this.readTarget && oldTarget){ //add 使用当前renderTarget中的像素 this.setSize(oldTarget.width, oldTarget.height)//所有viewports一起渲染,整个画面 因暂时没办法一个个copy oldTarget.viewport.set(0, 0, oldTarget.width, oldTarget.height); oldTarget.scissorTest = false this.copyPass.render( scene, camera,viewports, this.renderer, this.readBuffer, oldTarget ); } for ( i = 0; i < il; i ++ ) { pass = passes[ i ]; //if(i == il-1)pass.renderToScreen = true// pass.render( scene, camera, viewports, this.renderer, this.writeBuffer, this.readBuffer, maskActive, renderFun ); if ( pass.needsSwap ) { if ( maskActive ) { var context = this.renderer.context; context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); this.copyPass.render(null,null, viewports, this.renderer, this.writeBuffer, this.readBuffer );// delta context.stencilFunc( 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(oldTarget); //add if(!pass.renderToScreen){ //最后一个如果没有绘制到屏幕or target上 this.copyPass.renderToScreen = true this.copyPass.render(null,null, viewports,this.renderer, this.writeBuffer, this.readBuffer) } }, 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, scaleRatio ) { scaleRatio = scaleRatio || this.scaleRatio || 1; //console.log('setSize', width * scaleRatio, height * scaleRatio) let maxTexWidth = 4096 let w = width * scaleRatio let h = height * scaleRatio if(w > maxTexWidth || h > maxTexWidth){ //超出会崩溃 if(w>h){ scaleRatio = maxTexWidth / width }else{ scaleRatio = maxTexWidth / height } } w = width * scaleRatio h = height * scaleRatio this.renderTarget1.setSize( w, h ); this.renderTarget2.setSize( w, h ); for ( var i = 0; i < this.passes.length; i ++ ) { this.passes[ i ].setSize( w, h ); } } } ); export default EffectComposer