three.jsssao

Rendering multiple scenes, with only 1 using SSAO [Three.js]


In my continued experimentation with Three.js, I've hit another wall that I can't seem to climb over.

I'm trying to have a background scene (that has a floor in it) rendered below a foreground scene which has an SSAO post-process effect. The background scene should not have any post-processing applied.

I've tried multiple approaches (using masks, etc) and I just can't seem to crack this. The main problem I'm seeing is that the background of the SSAO scene is non-transparent so the background scene isn't showing. I'm still not convinced that even if that transparency issue is solved that things will work as expected.

This is how things should look without SSAO post-processing: http://jsfiddle.net/uJbPe/1/

And this is how things currently look with the SSAO post-processing enabled: http://jsfiddle.net/7hfdC/6/

Any idea what I'm doing wrong?


Solution

  • You can use a masking pass to make this happen. I believe it's the right way to approach the problem. Your original code is going to need some additions to make this possible.

    First you'll need to create a render target that has a stencil buffer enabled to pass in to the effect composer to use. The information in the stencil buffer allows for masking to take place.

    renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: true };
    renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
    composer = new THREE.EffectComposer( renderer, renderTarget );
    

    Next, I'd recommend having your background and foreground passes both be in the composer. It makes the rendering stack cleaner. When you render the foreground scene make sure its clear property is set to false so that the stencil buffer data is preserved for the masking pass.

    Then a mask pass, the ssao pass, a clear mask path, and a final shader pass to render it all to the screen. You could use a simple pass through shader or fxaa here. There may be another way to render to screen as well that I'm not aware of, but you can not assign the ssao pass to render to screen and have it work when the clear mask pass follows it.

    here's a link to a fiddle with this approach implemented http://jsfiddle.net/xqLdz/3/