UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

94 lines (93 loc) 3.31 kB
import { PIXELFORMAT_DEPTH, PIXELFORMAT_DEPTHSTENCIL, PIXELFORMAT_R32F } from "../../platform/graphics/constants.js"; import { FramePass } from "../../platform/graphics/frame-pass.js"; import { RenderTarget } from "../../platform/graphics/render-target.js"; import { Texture } from "../../platform/graphics/texture.js"; const _depthUniformName = "uSceneDepthMap"; class FramePassDepthGrab extends FramePass { depthRenderTarget = null; camera = null; constructor(device, camera) { super(device); this.camera = camera; } destroy() { super.destroy(); this.releaseRenderTarget(this.depthRenderTarget); } shouldReallocate(targetRT, sourceTexture) { const width = sourceTexture?.width || this.device.width; const height = sourceTexture?.height || this.device.height; return !targetRT || width !== targetRT.width || height !== targetRT.height; } allocateRenderTarget(renderTarget, sourceRenderTarget, device, format, isDepth) { const texture = Texture.createDataTexture2D( device, _depthUniformName, sourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width, sourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height, format ); if (renderTarget) { renderTarget.destroyFrameBuffers(); if (isDepth) { renderTarget._depthBuffer = texture; } else { renderTarget._colorBuffer = texture; renderTarget._colorBuffers = [texture]; } renderTarget.evaluateDimensions(); } else { renderTarget = new RenderTarget({ name: "DepthGrabRT", colorBuffer: isDepth ? null : texture, depthBuffer: isDepth ? texture : null, depth: !isDepth, stencil: device.supportsStencil, autoResolve: false }); } return renderTarget; } releaseRenderTarget(rt) { if (rt) { rt.destroyTextureBuffers(); rt.destroy(); } } before() { const camera = this.camera; const device = this.device; const destinationRt = camera?.renderTarget ?? device.backBuffer; let useDepthBuffer = true; let format = destinationRt.stencil ? PIXELFORMAT_DEPTHSTENCIL : PIXELFORMAT_DEPTH; if (device.isWebGPU) { const numSamples = destinationRt.samples; if (numSamples > 1) { format = PIXELFORMAT_R32F; useDepthBuffer = false; } } const sourceTexture = camera.renderTarget?.depthBuffer ?? camera.renderTarget?.colorBuffer; if (this.shouldReallocate(this.depthRenderTarget, sourceTexture)) { this.releaseRenderTarget(this.depthRenderTarget); this.depthRenderTarget = this.allocateRenderTarget(this.depthRenderTarget, camera.renderTarget, device, format, useDepthBuffer); } const colorBuffer = useDepthBuffer ? this.depthRenderTarget.depthBuffer : this.depthRenderTarget.colorBuffer; device.scope.resolve(_depthUniformName).setValue(colorBuffer); } execute() { const device = this.device; if (device.isWebGL2 && device.renderTarget.samples > 1) { const src = device.renderTarget.impl._glFrameBuffer; const dest = this.depthRenderTarget; device.renderTarget = dest; device.updateBegin(); this.depthRenderTarget.impl.internalResolve(device, src, dest.impl._glFrameBuffer, this.depthRenderTarget, device.gl.DEPTH_BUFFER_BIT); } else { device.copyRenderTarget(device.renderTarget, this.depthRenderTarget, false, true); } } } export { FramePassDepthGrab };