playcanvas
Version:
PlayCanvas WebGL game engine
126 lines (123 loc) • 5.66 kB
JavaScript
import { PIXELFORMAT_R32F, PIXELFORMAT_RGBA8, ADDRESS_CLAMP_TO_EDGE, FILTER_NEAREST } 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';
/**
* @import { BindGroup } from '../../platform/graphics/bind-group.js'
*/ var tempMeshInstances = [];
// uniform name of the depth texture
var DEPTH_UNIFORM_NAME = 'uSceneDepthMap';
/**
* A render pass which typically executes before the rendering of the main scene, and renders data
* that is required for the main rendering pass (and also in following passes) into separate render
* targets. This can include depth, normals, velocity, etc, used by TAA, motion blur, SSAO, etc.
*
* @category Graphics
* @ignore
*/ class RenderPassPrepass extends RenderPass {
destroy() {
var _this_renderTarget, _this_linearDepthTexture;
super.destroy();
(_this_renderTarget = this.renderTarget) == null ? void 0 : _this_renderTarget.destroy();
this.renderTarget = null;
(_this_linearDepthTexture = this.linearDepthTexture) == null ? void 0 : _this_linearDepthTexture.destroy();
this.linearDepthTexture = null;
this.viewBindGroups.forEach((bg)=>{
bg.defaultUniformBuffer.destroy();
bg.destroy();
});
this.viewBindGroups.length = 0;
}
setupRenderTarget(options) {
var { device } = this;
this.linearDepthFormat = device.textureFloatRenderable ? PIXELFORMAT_R32F : PIXELFORMAT_RGBA8;
this.linearDepthTexture = new Texture(device, {
name: 'SceneLinearDepthTexture',
width: 1,
height: 1,
format: this.linearDepthFormat,
mipmaps: false,
minFilter: FILTER_NEAREST,
magFilter: FILTER_NEAREST,
addressU: ADDRESS_CLAMP_TO_EDGE,
addressV: ADDRESS_CLAMP_TO_EDGE
});
var 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
});
// scene depth will be linear
this.camera.shaderParams.sceneDepthMapLinear = true;
this.init(renderTarget, options);
}
after() {
// Assign the lienar depth texture to the uniform
this.device.scope.resolve(DEPTH_UNIFORM_NAME).setValue(this.linearDepthTexture);
}
execute() {
var { renderer, scene, renderTarget } = this;
var camera = this.camera.camera;
var layers = scene.layers.layerList;
var subLayerEnabled = scene.layers.subLayerEnabled;
var isTransparent = scene.layers.subLayerList;
for(var i = 0; i < layers.length; i++){
var layer = layers[i];
// only render the layers before the depth layer
if (layer.id === LAYERID_DEPTH) {
break;
}
if (layer.enabled && subLayerEnabled[i]) {
// if the layer is rendered by the camera
if (layer.camerasSet.has(camera)) {
var culledInstances = layer.getCulledInstances(camera);
var meshInstances = isTransparent[i] ? culledInstances.transparent : culledInstances.opaque;
for(var j = 0; j < meshInstances.length; j++){
var _meshInstance_material;
var meshInstance = meshInstances[j];
// only collect meshes that update the depth
if ((_meshInstance_material = meshInstance.material) == null ? void 0 : _meshInstance_material.depthWrite) {
tempMeshInstances.push(meshInstance);
}
}
renderer.renderForwardLayer(camera, renderTarget, null, undefined, SHADER_PREPASS, this.viewBindGroups, {
meshInstances: tempMeshInstances
});
tempMeshInstances.length = 0;
}
}
}
}
frameUpdate() {
super.frameUpdate();
// depth clear value set up each frame
var { camera } = this;
this.setClearDepth(camera.clearDepthBuffer ? 1 : undefined);
// linear depth clear value set up each frame, or undefined to disable clearing
var clearValue;
if (camera.clearDepthBuffer) {
var farClip = camera.farClip - Number.MIN_VALUE;
clearValue = this.linearDepthClearValue;
if (this.linearDepthFormat === PIXELFORMAT_R32F) {
clearValue.r = farClip; // only R is used
} else {
FloatPacking.float2RGBA8(farClip, clearValue);
}
}
this.setClearColor(clearValue);
}
constructor(device, scene, renderer, camera, options){
super(device), /** @type {BindGroup[]} */ this.viewBindGroups = [], /** @type {Color} */ this.linearDepthClearValue = new Color(0, 0, 0, 0);
this.scene = scene;
this.renderer = renderer;
this.camera = camera;
this.setupRenderTarget(options);
}
}
export { RenderPassPrepass };