How to render two scenes using effectcomposer

hello everyone!
I want to use the effectcomposer to render two scenes, just like using the webgl renderer to achieve the same function, like this

renderer.render(scene, camera)
renderer.autoClear = false;
renderer.render(scene2, camera);
renderer.autoClear = true;

What should I do?

autoClear is a flag that you normally set just once after creating the renderer. Why are you using it in this way?


It is used when rendering two scenes in the editor source code. If I want to render two scenes, what should be the correct method

Set it just once and use this pattern:

const renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;

function animate() {

    requestAnimationFrame( animate );

    renderer.clear(); // manual clear

    renderer.render(scene, camera);
    renderer.render(scene2, camera);

In context of post processing you normally don’t need two render calls. Have you considered to use two instances of RenderPass?

If one scene needs to use post and the other scene does not need to use post, how should we render two scenes at the same time. :thinking:It doesn’t work

const renderScene = new RenderPass(scene, camera);

      const bloomPass = new UnrealBloomPass(
        new THREE.Vector2(dom.offsetWidth, dom.offsetHeight),
        1.5,
        0.4,
        0.85
      );

composer = new EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(bloomPass);
renderer.autoClear = false;
function animate() {

    requestAnimationFrame( animate );

    renderer.clear(); 

    composer.render();
    renderer.render(scene2, camera);
}

@Qiumeng12
Are you looking for something like selective bloom? three.js examples

I saw this demo, but all object3d in it are in one scene. I need two scenes to distinguish. Is there any other solution besides this demo?One scene stores my objects and the other stores helpers.

I think the use of layers might be what you’re really after? Instead of rendering two scenes, add two groups or object3d instances to your scene where one contains your meshes and the other your helpers. Using layers you can simply turn a layer on or off depending on what you want to render.

2 Likes

Use renderer_1 and renderer_2

If the scene where I store objects needs post-processing, can the use of that group help me solve the problem? :thinking:

I don’t quite understand what you mean. Can you be more detailed?

Sure, you don’t need 2 renderers. Just render the first layer first and store that result in a render target. Then you switch the layers and render the second one and do your post processing. Then as a final post processing pass, you simply blend the final results of both layers together

OK, I try to use this method to achieve it. I really feel your patient reply. :laughing:

    const renderScene = new RenderPass(scene, camera);
    const renderScene2 = new RenderPass(scene2, camera);

    const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
    bloomPass.threshold = params.bloomThreshold;
    bloomPass.strength = params.bloomStrength;
    bloomPass.radius = params.bloomRadius;

    const pixelRatio = renderer.getPixelRatio();

    const fxaaPass = new ShaderPass(FXAAShader);
    fxaaPass.material.uniforms['resolution'].value.x = 1 / (window.innerWidth * pixelRatio);
    fxaaPass.material.uniforms['resolution'].value.y = 1 / (window.innerHeight * pixelRatio);

    const bloomComposer = new EffectComposer(renderer);
    bloomComposer.renderToScreen = false;
    bloomComposer.addPass(renderScene);
    bloomComposer.addPass(bloomPass);

    const bloomComposer2 = new EffectComposer(renderer);
    bloomComposer2.renderToScreen = false;
    bloomComposer2.addPass(renderScene2);
    bloomComposer2.addPass(fxaaPass);

    const finalPass = new ShaderPass(
      new THREE.ShaderMaterial({
        uniforms: {
          baseTexture: { value: null },
          bloomTexture: { value: bloomComposer.renderTarget2.texture }
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        defines: {}
      }), "baseTexture"
    );
    finalPass.needsSwap = true;

    const finalPass2 = new ShaderPass(
      new THREE.ShaderMaterial({
        uniforms: {
          baseTexture: { value: null },
          bloomTexture: { value: bloomComposer2.renderTarget2.texture }
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        defines: {}
      }), "baseTexture"
    );
    finalPass2.needsSwap = true;

    const finalComposer = new EffectComposer(renderer);
    finalComposer.addPass(renderScene)
    finalComposer.addPass(finalPass);
    finalComposer.addPass(finalPass2);
    finalComposer.addPass(fxaaPass);

I’m not sure if my approach is reasonable, but it does help me render things in two scenes. What do you think? @Mugen87 @prisoner849 @Harold

const renderScene = new RenderPass(scene, camera);

let target = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
renderer.clear()
renderer.setRenderTarget(target);
renderer.render(scene2, camera);
renderer.setRenderTarget(null)

bloomComposer.render()//This is the scene that needs post-processing for rendering

const finalPass = new ShaderPass(
      new THREE.ShaderMaterial({
        uniforms: {
          baseTexture: { value: null },
          bloomTexture: { value: bloomComposer.renderTarget2.texture }
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        defines: {}
      }), "baseTexture"
    );
    finalPass.needsSwap = true;
const finalPass2 = new ShaderPass(
      new THREE.ShaderMaterial({
        uniforms: {
          baseTexture: { value: null },
          bloomTexture: { value: target.texture }
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        defines: {}
      }), "baseTexture2"
    );
    finalPass2.needsSwap = true;

const finalComposer = new EffectComposer(renderer);
finalComposer.addPass(renderScene)
finalComposer.addPass(finalPass);
finalComposer.addPass(finalPass2);

finalComposer.render()

What I want to know is whether you want to add finalpass and finalpass2 to effectcomposer by mixing the rendering results of two scenes.

How do I mix the final results of two layers? :sob:

You could use the blend shader for that and use the result of one pass as input. You should be able to find some examples that do the same thing. I know the SSAO pass does this, just to point you in the right direction.

I can find too few cases about this :sob: