Skip to content

Commit

Permalink
Add workaround for pmndrs postprocessing depth texture issue
Browse files Browse the repository at this point in the history
 * Copy depth texture to intermediate buffer to prevent binding depth texture to both input and output buffers in compositor shader
 * See pmndrs/postprocessing#225, pmndrs/postprocessing#416 for additional context
  • Loading branch information
Ameobea committed Aug 29, 2023
1 parent 9b295d1 commit 294cc26
Showing 1 changed file with 40 additions and 1 deletion.
41 changes: 40 additions & 1 deletion src/compositorPass.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Pass, Resizable } from 'postprocessing';
import { CopyPass, Pass, Resizable } from 'postprocessing';
import * as THREE from 'three';
import type { PerspectiveCamera } from 'three';

Expand Down Expand Up @@ -67,6 +67,9 @@ export class GodraysCompositorMaterial extends THREE.ShaderMaterial implements R

export class GodraysCompositorPass extends Pass {
sceneCamera: PerspectiveCamera;
private depthCopyRenderTexture: THREE.WebGLRenderTarget | null = null;
private depthTextureCopyPass: CopyPass | null = null;

constructor(props: GodraysCompositorMaterialProps) {
super('GodraysCompositorPass');
this.fullscreenMaterial = new GodraysCompositorMaterial(props);
Expand All @@ -92,8 +95,44 @@ export class GodraysCompositorPass extends Pass {
): void {
(this.fullscreenMaterial as GodraysCompositorMaterial).uniforms.sceneDiffuse.value =
inputBuffer.texture;

// There is a limitation in the pmndrs postprocessing library that causes rendering issues when
// the depth texture provided to the effect is the same as the one bound to the output buffer.
//
// To work around this, we copy the depth texture to a new render target and use that instead
// if it's found to be the same.
const sceneDepth = (this.fullscreenMaterial as GodraysCompositorMaterial).uniforms.sceneDepth
.value;
if (sceneDepth && outputBuffer && sceneDepth === outputBuffer.depthTexture) {
if (!this.depthCopyRenderTexture) {
this.depthCopyRenderTexture = new THREE.WebGLRenderTarget(
outputBuffer.depthTexture.image.width,
outputBuffer.depthTexture.image.height,
{
minFilter: outputBuffer.depthTexture.minFilter,
magFilter: outputBuffer.depthTexture.magFilter,
format: outputBuffer.depthTexture.format,
generateMipmaps: outputBuffer.depthTexture.generateMipmaps,
}
);
}
if (!this.depthTextureCopyPass) {
this.depthTextureCopyPass = new CopyPass();
}

this.depthTextureCopyPass.render(
renderer,
(this.fullscreenMaterial as GodraysCompositorMaterial).uniforms.sceneDepth.value,
this.depthCopyRenderTexture
);
(this.fullscreenMaterial as GodraysCompositorMaterial).uniforms.sceneDepth.value =
this.depthCopyRenderTexture.texture;
}

renderer.setRenderTarget(outputBuffer);
renderer.render(this.scene, this.camera);

(this.fullscreenMaterial as GodraysCompositorMaterial).uniforms.sceneDepth.value = sceneDepth;
}

override setDepthTexture(
Expand Down

0 comments on commit 294cc26

Please sign in to comment.