import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js'; import {RenderPass} from 'three/addons/postprocessing/RenderPass.js'; import {SSAOPass} from 'three/addons/postprocessing/SSAOPass.js'; import {OutputPass} from 'three/addons/postprocessing/OutputPass.js'; import {ShaderPass} from 'three/addons/postprocessing/ShaderPass.js'; import {FXAAShader} from 'three/addons/shaders/FXAAShader.js'; export function createRenderEffects(renderer,scene,camera,width,height){ const composer=new EffectComposer(renderer),base=new RenderPass(scene,camera),ao=new SSAOPass(scene,camera,width,height,16),output=new OutputPass(),aa=new ShaderPass(FXAAShader); composer.addPass(base);composer.addPass(ao);composer.addPass(output);composer.addPass(aa); ao.kernelRadius=8;ao.minDistance=.001;ao.maxDistance=.035; const state={revision:27,quality:'standard',enabled:true,aoActive:false,antialias:'FXAA'}; let widthNow=width,heightNow=height;function resize(w,h){widthNow=w;heightNow=h;const d=renderer.getPixelRatio();composer.setPixelRatio(d);composer.setSize(w,h);ao.setSize(Math.max(1,Math.round(w*d*(state.quality==='standard'?.5:1))),Math.max(1,Math.round(h*d*(state.quality==='standard'?.5:1))));aa.material.uniforms.resolution.value.set(1/(w*d),1/(h*d));} resize(width,height); return {state,resize,setQuality(value){if(!['standard','high'].includes(value))throw Error('未知画质');state.quality=value;renderer.setPixelRatio(Math.min(devicePixelRatio,value==='standard'?1:2));renderer.setSize(widthNow,heightNow);resize(widthNow,heightNow);},setEnabled(value){state.enabled=!!value;},render(mode){ // Transparent architectural context and broad plans retain the clean network renderer. ao.enabled=state.enabled&&['hydraulic','pump','meters'].includes(mode); state.aoActive=ao.enabled;base.enabled=true;ao.ssaoMaterial.uniforms.cameraProjectionMatrix.value.copy(camera.projectionMatrix);ao.ssaoMaterial.uniforms.cameraInverseProjectionMatrix.value.copy(camera.projectionMatrixInverse);ao.ssaoMaterial.uniforms.cameraNear.value=camera.near;ao.ssaoMaterial.uniforms.cameraFar.value=camera.far; if(state.enabled)composer.render();else renderer.render(scene,camera); },dispose(){for(const p of [ao,output,aa])p.dispose();composer.dispose();}}; }