Bastian Born
Bastian Born

Reputation: 166

Three.js post-processing: How to keep depth texture for multiple passes?

I am rendering a scene using three.js that needs multiple post-processing passes. Most of those steps need the depth buffer. My plan was to first render all visible objects to obtain the color and depth and then render all post-processing passes using 2 framebuffers which are alternating read and write framebuffers. The passes are just examples:

  1. Render Objects -> FB0
  2. DistortionPass, taking FB0 as input -> FB1
  3. GodrayPass, taking FB1 as input -> FB0
  4. SSAOPass, taking FB0 as input -> screen

The GodrayPass needs to read the depth of the first render pass, therefore I need to bind the depth texture and it should not be the one bound to FB0, otherwise it would lead to a feedback loop, since that shader is writing to FB0.

I think it would make sense to copy the depth into a separate texture after rendering the objects, so I can bind this texture whenever needed in a pass without worrying about a feedback loop.

However,

What is the best practice here? Am I on the right path?

I can make use of WebGL 2.0 (OpenGL ES 3.0), but would like to avoid using unpopular extensions.

Upvotes: 1

Views: 2224

Answers (1)

user128511
user128511

Reputation:

Three.js doesn't call them FB's, it calls them RenderTargets. For webgl they are WebGLRenderTarget

https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget

This example show setting up a depth texture with a render target

target = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
target.texture.format = THREE.RGBFormat;
target.texture.minFilter = THREE.NearestFilter;
target.texture.magFilter = THREE.NearestFilter;
target.texture.generateMipmaps = false;
target.stencilBuffer = false;
target.depthBuffer = true;
target.depthTexture = new THREE.DepthTexture();
target.depthTexture.format = THREE.DepthFormat;
target.depthTexture.type = THREE.UnsignedShortType;

And this article shows rendering to render targets. And this article shows rendering to render targets for the purposes of post processing using EffectComposer and Pass three.js objects.

So, just make 3 render targets

RT0 = color + depth
RT1 = color
RT2 = color

Then setup Pass objects such that

Render Objects -> RT0(color+depth)
DistortionPass, taking RT0(color) as input -> RT1(color)
GodrayPass, taking RT1(color) + RT0(depth) as input -> RT2(color)
SSAOPass, taking RT2(color as input -> screen

Upvotes: 5

Related Questions