I ran into this problem myself, then figured out the cause after some digging. I’ve never posted to a programming forum before and I know this post is old, but I figured I might help save someone else some trouble.
EffectComposer keeps a stack of passes, and it’s important for the last pass to render to the canvas. However, disabling passes doesn’t alert EffectComposer, and it doesn’t check if the last pass is enabled.
As a quick fix, you can set the renderToScreen properties of the passes that will be last to true.
const effectPass = new EffectPass(camera, effects[0]);
composer.addPass(effectPass);
const effectPassSSAO = new EffectPass(camera, ...effects);
effectPassSSAO.setEnabled(false);
composer.addPass(effectPassSSAO);
// Both are last, because only one will be enabled at a time.
effectPass.renderToScreen = true;
effectPassSSAO.renderToScreen = true;
This must be done after all passes are added, because EffectComposer flags only the last pass without considering if it is enabled.
For a more permanent solution, you can edit your library files to correctly figure the last enabled pass to render to the screen. I added this method to EffectComposer.js:
figureLastPass() {
for(let i = this.passes.length - 1, found = false; i >= 0; i--) {
if(!found && this.passes[i].enabled) {
this.passes[i].renderToScreen = true;
found = true;
} else {
this.passes[i].renderToScreen = false;
}
}
}
Changed the addPass() method in EffectComposer.js:
addPass(pass, index) {
const passes = this.passes;
const renderer = this.renderer;
const drawingBufferSize = renderer.getDrawingBufferSize(new Vector2());
const alpha = renderer.getContext().getContextAttributes().alpha;
const frameBufferType = this.inputBuffer.texture.type;
pass.setRenderer(renderer);
pass.setSize(drawingBufferSize.width, drawingBufferSize.height);
pass.initialize(renderer, alpha, frameBufferType);
pass.composer = this; // Add this line.
// Remove these lines.
/*if(this.autoRenderToScreen) {
if(passes.length > 0) {
passes[passes.length - 1].renderToScreen = false;
}
if(pass.renderToScreen) {
this.autoRenderToScreen = false;
}
}*/
if(index !== undefined) {
passes.splice(index, 0, pass);
} else {
passes.push(pass);
}
if(this.autoRenderToScreen) {
// Remove this line.
//passes[passes.length - 1].renderToScreen = true;
this.figureLastPass(); // Add this line.
}
// ...
Changed setEnabled() in Pass.js to notify EffectComposer an update is needed:
setEnabled(value) {
this.enabled = value;
if(this.composer) this.composer.figureLastPass();
}
With that, you should be able to enable and disable passes as you wish. Be sure to only enable/disable with setEnabled(). If you’d rather not have the pass hold a reference to the composer, you could leave out the change to Pass.js and manually call figureLastPass() after every time you enable/disable.
This uses v6.36.7 of pmndrs/postprocessing on GitHub.