Skip to content

Commit 1bcdefa

Browse files
committed
Make depth texture management more robust
Related to #740
1 parent 14404f7 commit 1bcdefa

File tree

1 file changed

+57
-56
lines changed

1 file changed

+57
-56
lines changed

src/core/EffectComposer.js

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ClearMaskPass } from "../passes/ClearMaskPass.js";
1414
import { CopyPass } from "../passes/CopyPass.js";
1515
import { MaskPass } from "../passes/MaskPass.js";
1616
import { Pass } from "../passes/Pass.js";
17+
import { RenderPass } from "../passes/RenderPass.js";
1718
import { Timer } from "./Timer.js"; // TODO Replace with Timer from three, requires r179.
1819

1920
/**
@@ -96,15 +97,16 @@ export class EffectComposer {
9697
this.depthTexture = null;
9798

9899
/**
99-
* A render target that holds a stable copy of the scene depth. Scene depth is copied into here
100-
* to avoid feedback loops and undefined behavior that can happen when the same depth attachment is
101-
* used on both the input and output buffers.
100+
* A render target that holds a stable copy of the scene depth.
101+
*
102+
* The scene depth needs to be copied to avoid feedback loops and undefined behavior that can happen when the same
103+
* depth attachment is used on both the input and output buffers.
102104
*
103105
* @type {WebGLRenderTarget}
104106
* @private
105107
*/
106108

107-
this._stableDepthTarget = null;
109+
this.depthRenderTarget = null;
108110

109111
/**
110112
* The passes.
@@ -181,7 +183,6 @@ export class EffectComposer {
181183
value
182184
);
183185

184-
this.inputBuffer.depthTexture = this.depthTexture;
185186
this.outputBuffer = this.inputBuffer.clone();
186187

187188
}
@@ -295,15 +296,14 @@ export class EffectComposer {
295296
* @private
296297
* @return {DepthTexture} The stable depth texture distributed to passes.
297298
*/
298-
createDepthTexture() {
299299

300-
const depthTexture = this.depthTexture = new DepthTexture();
300+
createDepthTexture() {
301301

302-
// Hack: Make sure the input buffer uses the depth texture.
303-
this.inputBuffer.depthTexture = depthTexture;
304-
this.inputBuffer.dispose();
302+
const inputBuffer = this.inputBuffer;
303+
const depthTexture = new DepthTexture();
304+
this.depthTexture = depthTexture;
305305

306-
if(this.inputBuffer.stencilBuffer) {
306+
if(inputBuffer.stencilBuffer) {
307307

308308
depthTexture.format = DepthStencilFormat;
309309
depthTexture.type = UnsignedInt248Type;
@@ -314,14 +314,12 @@ export class EffectComposer {
314314

315315
}
316316

317-
const stableDepthTexture = new DepthTexture();
318-
stableDepthTexture.format = depthTexture.format;
319-
stableDepthTexture.type = depthTexture.type;
317+
const stableDepthTexture = depthTexture.clone();
320318
stableDepthTexture.name = "EffectComposer.StableDepth";
321319

322-
this._stableDepthTarget = new WebGLRenderTarget(this.inputBuffer.width, this.inputBuffer.height, {
320+
this.depthRenderTarget = new WebGLRenderTarget(inputBuffer.width, inputBuffer.height, {
323321
depthBuffer: true,
324-
stencilBuffer: this.inputBuffer.stencilBuffer,
322+
stencilBuffer: inputBuffer.stencilBuffer,
325323
depthTexture: stableDepthTexture
326324
});
327325

@@ -333,33 +331,36 @@ export class EffectComposer {
333331
* Copies the depth buffer from the src render target into the stable depth target.
334332
*
335333
* @private
336-
* @param {WebGLRenderTarget} srcTarget - The render target whose depth buffer should be copied.
334+
* @param {WebGLRenderTarget} renderTarget - The render target whose depth buffer should be copied.
337335
*/
338336

339-
blitDepthBuffer(srcTarget) {
337+
blitDepthBuffer(renderTarget) {
340338

341339
const renderer = this.renderer;
340+
const depthRenderTarget = this.depthRenderTarget;
341+
const props = renderer.properties;
342342
const gl = renderer.getContext();
343343

344-
renderer.setRenderTarget(this._stableDepthTarget);
344+
renderer.setRenderTarget(depthRenderTarget);
345345

346-
const props = renderer.properties;
347346
// eslint-disable-next-line no-underscore-dangle
348-
const srcFBO = props.get(srcTarget).__webglFramebuffer;
347+
const srcFBO = props.get(renderTarget).__webglFramebuffer;
349348
// eslint-disable-next-line no-underscore-dangle
350-
const dstFBO = props.get(this._stableDepthTarget).__webglFramebuffer;
349+
const dstFBO = props.get(depthRenderTarget).__webglFramebuffer;
351350

352-
const blitMask = srcTarget.stencilBuffer
353-
? (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
354-
: gl.DEPTH_BUFFER_BIT;
351+
const blitMask = renderTarget.stencilBuffer ?
352+
(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) :
353+
gl.DEPTH_BUFFER_BIT;
355354

356355
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFBO);
357356
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFBO);
357+
358358
gl.blitFramebuffer(
359-
0, 0, srcTarget.width, srcTarget.height,
360-
0, 0, this._stableDepthTarget.width, this._stableDepthTarget.height,
359+
0, 0, renderTarget.width, renderTarget.height,
360+
0, 0, depthRenderTarget.width, depthRenderTarget.height,
361361
blitMask, gl.NEAREST
362362
);
363+
363364
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
364365
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
365366

@@ -379,17 +380,11 @@ export class EffectComposer {
379380

380381
this.depthTexture.dispose();
381382
this.depthTexture = null;
383+
this.depthRenderTarget.dispose();
384+
this.depthRenderTarget = null;
382385

383-
// Update the input buffer.
384386
this.inputBuffer.depthTexture = null;
385-
this.inputBuffer.dispose();
386-
387-
if(this._stableDepthTarget !== null) {
388-
389-
this._stableDepthTarget.dispose();
390-
this._stableDepthTarget = null;
391-
392-
}
387+
this.outputBuffer.depthTexture = null;
393388

394389
for(const pass of this.passes) {
395390

@@ -494,7 +489,7 @@ export class EffectComposer {
494489
const alpha = renderer.getContext().getContextAttributes().alpha;
495490
const frameBufferType = this.inputBuffer.texture.type;
496491

497-
pass.setRenderer(renderer);
492+
pass.renderer = renderer;
498493
pass.setSize(drawingBufferSize.width, drawingBufferSize.height);
499494
pass.initialize(renderer, alpha, frameBufferType);
500495

@@ -534,17 +529,18 @@ export class EffectComposer {
534529

535530
if(this.depthTexture === null) {
536531

537-
const depthTexture = this.createDepthTexture();
532+
const stableDepthTexture = this.createDepthTexture();
538533

539534
for(pass of passes) {
540535

541-
pass.setDepthTexture(depthTexture);
536+
pass.setDepthTexture(stableDepthTexture);
542537

543538
}
544539

545540
} else {
546541

547-
pass.setDepthTexture(this._stableDepthTarget.depthTexture);
542+
const stableDepthTexture = this.depthRenderTarget.depthTexture;
543+
pass.setDepthTexture(stableDepthTexture);
548544

549545
}
550546

@@ -575,11 +571,10 @@ export class EffectComposer {
575571

576572
if(!depthTextureRequired) {
577573

578-
const composerDepth = this._stableDepthTarget !== null
579-
? this._stableDepthTarget.depthTexture
580-
: this.depthTexture;
574+
const stableDepthTexture = this.depthRenderTarget.depthTexture;
581575

582-
if(pass.getDepthTexture() === composerDepth) {
576+
// Don't remove foreign depth textures.
577+
if(pass.getDepthTexture() === stableDepthTexture) {
583578

584579
pass.setDepthTexture(null);
585580

@@ -649,10 +644,9 @@ export class EffectComposer {
649644

650645
let inputBuffer = this.inputBuffer;
651646
let outputBuffer = this.outputBuffer;
647+
let buffer;
652648

653649
let stencilTest = false;
654-
let depthBlitted = false;
655-
let context, stencil, buffer;
656650

657651
if(deltaTime === undefined) {
658652

@@ -669,23 +663,30 @@ export class EffectComposer {
669663

670664
}
671665

672-
// Copy the depth buffer to the stable depth target just before the first pass that swaps buffers
673-
if(!depthBlitted && this._stableDepthTarget !== null && pass.needsSwap) {
666+
// Setup the depth texture (RenderPass renders into the inputBuffer).
667+
inputBuffer.depthTexture = this.depthTexture;
668+
outputBuffer.depthTexture = null;
674669

675-
this.blitDepthBuffer(this.inputBuffer);
676-
depthBlitted = true;
670+
pass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
677671

678-
}
672+
if(pass instanceof RenderPass) {
679673

680-
pass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
674+
// Copy depth to the stable depth texture.
675+
if(this.depthRenderTarget !== null) {
676+
677+
this.blitDepthBuffer(inputBuffer);
678+
679+
}
680+
681+
}
681682

682683
if(pass.needsSwap) {
683684

684685
if(stencilTest) {
685686

686687
copyPass.renderToScreen = pass.renderToScreen;
687-
context = renderer.getContext();
688-
stencil = renderer.state.buffers.stencil;
688+
const context = renderer.getContext();
689+
const stencil = renderer.state.buffers.stencil;
689690

690691
// Preserve the unaffected pixels.
691692
stencil.setFunc(context.NOTEQUAL, 1, 0xffffffff);
@@ -746,9 +747,9 @@ export class EffectComposer {
746747
this.inputBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
747748
this.outputBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
748749

749-
if(this._stableDepthTarget !== null) {
750+
if(this.depthRenderTarget !== null) {
750751

751-
this._stableDepthTarget.setSize(drawingBufferSize.width, drawingBufferSize.height);
752+
this.depthRenderTarget.setSize(drawingBufferSize.width, drawingBufferSize.height);
752753

753754
}
754755

0 commit comments

Comments
 (0)