Three.js post-processing:如何保持多遍的深度纹理?
Three.js post-processing: How to keep depth texture for multiple passes?
我正在使用 three.js 渲染一个需要多个 post 处理通道的场景。这些步骤中的大多数都需要深度缓冲区。我的计划是首先渲染所有可见对象以获得颜色和深度,然后使用 2 个交替读取和写入帧缓冲区的帧缓冲区渲染所有 post 处理过程。通行证只是示例:
- 渲染对象 -> FB0
- DistortionPass,以FB0为输入-> FB1
- GodrayPass,以FB1为输入-> FB0
- SSAOPass,以FB0为输入->筛选
GodrayPass 需要读取第一个渲染通道的深度,所以我需要绑定深度纹理,它不应该是绑定到 FB0 的,否则会导致反馈循环,因为那个着色器是写入 FB0.
我认为在渲染对象之后将深度复制到一个单独的纹理中是有意义的,这样我就可以在一个过程中需要的时候绑定这个纹理,而不用担心反馈循环。
然而,
- copyTexImage2D 似乎不支持从深度缓冲区复制。
- 在第一次传递到 RGBA8 纹理后使用着色器打包深度缓冲区将需要每次传递都再次“解包”浮点数
- 使用将深度输出到颜色缓冲区的着色器再次渲染所有对象?将需要再次打包或精度损失。
此处的最佳做法是什么?我走的路对吗?
我可以使用 WebGL 2.0 (OpenGL ES 3.0),但想避免使用不受欢迎的扩展。
Three.js 不称他们为 FB,而是称他们为 RenderTarget
。对于 webgl,它们是 WebGLRenderTarget
https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget
This example 显示使用渲染目标设置深度纹理
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;
和 this article shows rendering to render targets. And this article 显示渲染到渲染目标,以便使用 EffectComposer
和 Pass
three.js 对象进行 post 处理。
所以,只需制作 3 个渲染目标
RT0 = color + depth
RT1 = color
RT2 = color
然后设置 Pass
个对象使得
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
我正在使用 three.js 渲染一个需要多个 post 处理通道的场景。这些步骤中的大多数都需要深度缓冲区。我的计划是首先渲染所有可见对象以获得颜色和深度,然后使用 2 个交替读取和写入帧缓冲区的帧缓冲区渲染所有 post 处理过程。通行证只是示例:
- 渲染对象 -> FB0
- DistortionPass,以FB0为输入-> FB1
- GodrayPass,以FB1为输入-> FB0
- SSAOPass,以FB0为输入->筛选
GodrayPass 需要读取第一个渲染通道的深度,所以我需要绑定深度纹理,它不应该是绑定到 FB0 的,否则会导致反馈循环,因为那个着色器是写入 FB0.
我认为在渲染对象之后将深度复制到一个单独的纹理中是有意义的,这样我就可以在一个过程中需要的时候绑定这个纹理,而不用担心反馈循环。
然而,
- copyTexImage2D 似乎不支持从深度缓冲区复制。
- 在第一次传递到 RGBA8 纹理后使用着色器打包深度缓冲区将需要每次传递都再次“解包”浮点数
- 使用将深度输出到颜色缓冲区的着色器再次渲染所有对象?将需要再次打包或精度损失。
此处的最佳做法是什么?我走的路对吗?
我可以使用 WebGL 2.0 (OpenGL ES 3.0),但想避免使用不受欢迎的扩展。
Three.js 不称他们为 FB,而是称他们为 RenderTarget
。对于 webgl,它们是 WebGLRenderTarget
https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget
This example 显示使用渲染目标设置深度纹理
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;
和 this article shows rendering to render targets. And this article 显示渲染到渲染目标,以便使用 EffectComposer
和 Pass
three.js 对象进行 post 处理。
所以,只需制作 3 个渲染目标
RT0 = color + depth
RT1 = color
RT2 = color
然后设置 Pass
个对象使得
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