playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
118 lines (117 loc) • 4.51 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 {Texture} */
__publicField(this, "linearDepthTexture");
/** @type {Color} */
__publicField(this, "linearDepthClearValue", new Color(0, 0, 0, 0));
/**
* The layerList indices of the sub-layers this prepass renders. Rebuilt each frame in
* frameUpdate (where culling is also requested) and consumed by execute.
*
* @type {number[]}
*/
__publicField(this, "_qualifiedLayerIndices", []);
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;
}
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 isTransparent = scene.layers.subLayerList;
for (const i of this._qualifiedLayerIndices) {
const layer = layers[i];
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, {
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);
const { renderer, scene } = this;
const cullCamera = this.camera.camera;
const composition = scene.layers;
const layerList = composition.layerList;
const qualified = this._qualifiedLayerIndices;
qualified.length = 0;
for (let i = 0; i < layerList.length; i++) {
if (layerList[i].id === LAYERID_DEPTH) break;
if (composition.isSubLayerRenderedByCamera(i, cullCamera)) {
qualified.push(i);
renderer.culler.requestMeshInstanceCull(cullCamera, layerList[i]);
}
}
}
}
export {
RenderPassPrepass
};