@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
98 lines (95 loc) • 3.96 kB
JavaScript
import { FILTER_NEAREST, ADDRESS_CLAMP_TO_EDGE, 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 _depthUniformNames = ['uSceneDepthMap', 'uDepthMap'];
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 == null ? void 0 : sourceTexture.width) || this.device.width;
const height = (sourceTexture == null ? void 0 : 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: _depthUniformNames[0],
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() {
var _camera$renderTarget, _camera$renderTarget$, _camera$renderTarget2, _camera$renderTarget3;
const camera = this.camera;
const device = this.device;
const destinationRt = (_camera$renderTarget = camera == null ? void 0 : camera.renderTarget) != null ? _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$ = (_camera$renderTarget2 = camera.renderTarget) == null ? void 0 : _camera$renderTarget2.depthBuffer) != null ? _camera$renderTarget$ : (_camera$renderTarget3 = camera.renderTarget) == null ? void 0 : _camera$renderTarget3.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;
_depthUniformNames.forEach(name => device.scope.resolve(name).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 };