简体   繁体   中英

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,

  • copyTexImage2D seem to not support copying from the depth buffer.
  • using a shader to pack the depth buffer after the first pass into an RGBA8 texture would require every pass to "unpack" the float again
  • render all objects again using a shader that output the depth to the color buffer? Would require packing or precision loss again.

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.

Three.js doesn't call them FB's, it calls them RenderTarget s. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM