playcanvas
Version:
PlayCanvas WebGL game engine
97 lines (94 loc) • 3.7 kB
JavaScript
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 };