playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
113 lines (112 loc) • 4.23 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import {
PIXELFORMAT_R32F,
PIXELFORMAT_RGBA8
} from "../../platform/graphics/constants.js";
import { Texture } from "../../platform/graphics/texture.js";
import { RenderPass } from "../../platform/graphics/render-pass.js";
import { RenderTarget } from "../../platform/graphics/render-target.js";
import {
LAYERID_DEPTH,
SHADER_PREPASS
} from "../../scene/constants.js";
import { Color } from "../../core/math/color.js";
import { FloatPacking } from "../../core/math/float-packing.js";
const tempMeshInstances = [];
const DEPTH_UNIFORM_NAME = "uSceneDepthMap";
class RenderPassPrepass extends RenderPass {
constructor(device, scene, renderer, camera, options) {
super(device);
/** @type {BindGroup[]} */
__publicField(this, "viewBindGroups", []);
/** @type {Texture} */
__publicField(this, "linearDepthTexture");
/** @type {Color} */
__publicField(this, "linearDepthClearValue", new Color(0, 0, 0, 0));
this.scene = scene;
this.renderer = renderer;
this.camera = camera;
this.setupRenderTarget(options);
}
destroy() {
super.destroy();
this.camera.shaderParams.sceneDepthMapLinear = false;
this.renderTarget?.destroy();
this.renderTarget = null;
this.linearDepthTexture?.destroy();
this.linearDepthTexture = null;
this.viewBindGroups.forEach((bg) => {
bg.defaultUniformBuffer.destroy();
bg.destroy();
});
this.viewBindGroups.length = 0;
}
setupRenderTarget(options) {
const { device } = this;
this.linearDepthFormat = device.textureFloatRenderable ? PIXELFORMAT_R32F : PIXELFORMAT_RGBA8;
this.linearDepthTexture = Texture.createDataTexture2D(device, "SceneLinearDepthTexture", 1, 1, this.linearDepthFormat);
const renderTarget = new RenderTarget({
name: "PrepassRT",
colorBuffer: this.linearDepthTexture,
// use depth buffer, but this can be discarded after the prepass as the depth is stored in the linearDepthTexture
depth: true,
// always single sampled
samples: 1
});
this.camera.shaderParams.sceneDepthMapLinear = true;
this.init(renderTarget, options);
}
after() {
this.device.scope.resolve(DEPTH_UNIFORM_NAME).setValue(this.linearDepthTexture);
}
execute() {
const { renderer, scene, renderTarget } = this;
const camera = this.camera.camera;
const layers = scene.layers.layerList;
const subLayerEnabled = scene.layers.subLayerEnabled;
const isTransparent = scene.layers.subLayerList;
for (let i = 0; i < layers.length; i++) {
const layer = layers[i];
if (layer.id === LAYERID_DEPTH) {
break;
}
if (layer.enabled && subLayerEnabled[i]) {
if (layer.camerasSet.has(camera)) {
const culledInstances = layer.getCulledInstances(camera);
const meshInstances = isTransparent[i] ? culledInstances.transparent : culledInstances.opaque;
for (let j = 0; j < meshInstances.length; j++) {
const meshInstance = meshInstances[j];
if (meshInstance.material?.depthWrite) {
tempMeshInstances.push(meshInstance);
}
}
renderer.renderForwardLayer(camera, renderTarget, null, void 0, SHADER_PREPASS, this.viewBindGroups, {
meshInstances: tempMeshInstances
});
tempMeshInstances.length = 0;
}
}
}
}
frameUpdate() {
super.frameUpdate();
const { camera } = this;
this.setClearDepth(camera.clearDepthBuffer ? 1 : void 0);
let clearValue;
if (camera.clearDepthBuffer) {
const farClip = camera.farClip - Number.MIN_VALUE;
clearValue = this.linearDepthClearValue;
if (this.linearDepthFormat === PIXELFORMAT_R32F) {
clearValue.r = farClip;
} else {
FloatPacking.float2RGBA8(farClip, clearValue);
}
}
this.setClearColor(clearValue);
}
}
export {
RenderPassPrepass
};