UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

97 lines (94 loc) 3.7 kB
import { ADDRESS_CLAMP_TO_EDGE, FILTER_NEAREST, PIXELFORMAT_DEPTHSTENCIL, PIXELFORMAT_DEPTH, PIXELFORMAT_R32F } from '../../platform/graphics/constants.js'; import { RenderPass } from '../../platform/graphics/render-pass.js'; import { RenderTarget } from '../../platform/graphics/render-target.js'; import { Texture } from '../../platform/graphics/texture.js'; const _depthUniformName = 'uSceneDepthMap'; class RenderPassDepthGrab extends RenderPass { constructor(device, camera){ super(device), this.depthRenderTarget = null, this.camera = null; 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 = new Texture(device, { name: _depthUniformName, format, width: sourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width, height: sourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height, mipmaps: false, minFilter: FILTER_NEAREST, magFilter: FILTER_NEAREST, addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE }); if (renderTarget) { renderTarget.destroyFrameBuffers(); if (isDepth) { renderTarget._depthBuffer = texture; } else { renderTarget._colorBuffer = texture; renderTarget._colorBuffers = [ texture ]; } } 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 { RenderPassDepthGrab };