Hi, I’m working with EffectComposer and multiple RenderPass in three.js, and I ran into a depth-buffer issue when combining a ShaderPass with additional scenes.
Here’s a minimal setup:
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.autoClear = true;
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
const mainScene = new THREE.Scene();
const overlayScene = new THREE.Scene(); // drawn on top of mainScene
// ... populate mainScene / overlayScene with generic meshes & materials ...
const composer = new EffectComposer(renderer);
const passMain = new RenderPass(mainScene, camera);
passMain.clear = true;
composer.addPass(passMain);
const passOverlay = new RenderPass(overlayScene, camera);
passOverlay.clear = false; // do not clear, draw over
composer.addPass(passOverlay);
// Generic ShaderPass (color-only)
const GenericShader = {
uniforms: {
tDiffuse: { value: null },
someParam: { value: 0.0 },
},
vertexShader: /* glsl */`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: /* glsl */`
uniform sampler2D tDiffuse;
uniform float someParam;
varying vec2 vUv;
void main() {
vec4 color = texture2D(tDiffuse, vUv);
// example color modification
color.rgb *= (1.0 + someParam);
gl_FragColor = color; // color-only; do not touch gl_FragDepth
}
`
};
const shaderPass = new ShaderPass(GenericShader);
composer.addPass(shaderPass);
// Later I want to render another scene AFTER the ShaderPass:
const extraScene = new THREE.Scene();
// ... populate extraScene ...
Goal
After the ShaderPass, I want to render extraScene that:
-
uses the depth buffer from the first two scenes for correct depth testing, and
-
is not affected by the ShaderPass color modification.
What I tried
-
Custom ShaderPass (color-only)
I kept the fragment shader color-only (nogl_FragDepthwrites). This avoids overwriting depth, but I still can’t make a laterRenderPassconsume the earlier depth reliably. -
Manual render after composer
composer.render(); renderer.autoClear = false; renderer.clearDepth(); // if I clear depth, extraScene renders on top renderer.render(extraScene, camera);This renders, but clearing depth defeats the purpose.
Question
What’s the recommended way in three.js to:
-
apply a color-only ShaderPass,
-
preserve the depth buffer from previous passes,
-
and then render another scene that uses that preserved depth (while not being color-modified)?
Is there an existing pattern in EffectComposer to keep and reuse the depth attachment, or do I need a custom multi-target FBO / manual MRT setup?