Three.js中EffectComposer混合场景闪烁问题求助
Three.js双场景混合频闪问题解决方案
嘿,我看了你的代码,发现问题出在多个EffectComposer共用了同一个WebGLRenderTarget上!当你用同一个renderTarget给不同的composer时,每次渲染都会覆盖这个目标的内容,导致第二个场景的纹理数据被后续的渲染操作冲掉,就出现了频闪的现象。
修复步骤:
为每个Composer创建独立的RenderTarget
不要只创建一个renderTarget,而是给每个composer单独生成自己的WebGLRenderTarget。修改initProcessingPasses函数里的代码:function initProcessingPasses () { // 定义RenderTarget参数 var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: true }; // 为每个Composer创建独立的RenderTarget var renderTargetScene1 = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); var renderTargetScene2 = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); var renderTargetBlending = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); var renderTargetFinal = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); var renderTargetDebug1 = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); var renderTargetDebug2 = new THREE.WebGLRenderTarget( canvasWidth, canvasHeight, parameters ); processing = { pass: {}, texture: {} }; processing.pass.clear = new THREE.ClearPass(); processing.pass.renderScene1 = new THREE.RenderPass( scene1, camera ); processing.pass.renderScene1.clear = true; processing.pass.renderScene1.renderToScreen = false; processing.pass.renderScene1.clearDepth = true; processing.pass.renderScene2 = new THREE.RenderPass( scene2, camera ); processing.pass.renderScene2.clear = true; processing.pass.renderScene2.renderToScreen = false; processing.pass.renderScene2.clearDepth = true; processing.pass.blending = new THREE.ShaderPass( THREE.Custom.AdditiveShader ); processing.pass.blending.clear = true; processing.pass.blending.renderToScreen = false; processing.pass.output = new THREE.ShaderPass( THREE.CopyShader ); processing.pass.output.renderToScreen = true; setPostProcessingPasses(renderTargetScene1, renderTargetScene2, renderTargetBlending, renderTargetFinal, renderTargetDebug1, renderTargetDebug2); }修改setPostProcessingPasses函数,接收独立的RenderTarget
更新这个函数,让每个composer使用专属的renderTarget:function setPostProcessingPasses(rtScene1, rtScene2, rtBlending, rtFinal, rtDebug1, rtDebug2) { console.log('setPostProcessingPasses'); composerScene1 = new THREE.EffectComposer( renderer, rtScene1 ); composerScene1.addPass( processing.pass.clear ); composerScene1.addPass( processing.pass.renderScene1 ); processing.texture.renderedScene1 = new THREE.TexturePass(composerScene1.renderTarget2.texture); composerScene2 = new THREE.EffectComposer( renderer, rtScene2 ); composerScene2.addPass( processing.pass.clear ); composerScene2.addPass( processing.pass.renderScene2 ); processing.texture.renderedScene2 = new THREE.TexturePass(composerScene2.renderTarget2.texture); composerBlending = new THREE.EffectComposer( renderer, rtBlending ); composerBlending.addPass( processing.pass.clear ); composerBlending.addPass( processing.texture.renderedScene1 ); processing.pass.blending.uniforms[ 'tAdd' ].value = composerScene2.renderTarget2.texture; composerBlending.addPass( processing.pass.blending ); processing.texture.renderedBlending = new THREE.TexturePass(composerBlending.renderTarget2.texture); composerFinal = new THREE.EffectComposer( renderer, rtFinal ); composerFinal.addPass( processing.pass.clear ); composerFinal.addPass( processing.texture.renderedBlending ); composerFinal.addPass( processing.pass.output ); composerDebugScene1 = new THREE.EffectComposer( renderer, rtDebug1 ); composerDebugScene1.addPass( processing.pass.clear ); composerDebugScene1.addPass( processing.texture.renderedScene1 ); composerDebugScene1.addPass( processing.pass.output ); composerDebugScene2 = new THREE.EffectComposer( renderer, rtDebug2 ); composerDebugScene2.addPass( processing.pass.clear ); composerDebugScene2.addPass( processing.texture.renderedScene2 ); composerDebugScene2.addPass( processing.pass.output ); }修复着色器的语法错误
你的AdditiveShader片段着色器里有个小错误:gl_FragColor = texel + add * fCoeff, 1.0;这行的逗号是错的,应该改成:gl_FragColor = vec4(texel.rgb + add.rgb * fCoeff, 1.0);这样才能正确输出RGBA颜色,避免可能的渲染异常。
额外优化建议:
- 窗口 resize 时,记得也要更新所有renderTarget的尺寸:在
onWindowResize函数里添加每个renderTarget的setSize调用,比如renderTargetScene1.setSize(canvasWidth, canvasHeight);,确保渲染结果适配窗口大小。
这样修改后,两个场景的渲染结果会被保存到各自独立的renderTarget里,混合着色器就能正确读取两个纹理,不会再出现频闪的问题啦!
内容的提问来源于stack exchange,提问作者noboss
相关产品推荐
相关产品推荐

