playcanvas
Version:
PlayCanvas WebGL game engine
94 lines (91 loc) • 4.32 kB
JavaScript
import { DebugGraphics } from '../../platform/graphics/debug-graphics.js';
import { BlendState } from '../../platform/graphics/blend-state.js';
import { RenderPass } from '../../platform/graphics/render-pass.js';
import { SHADER_PICK } from '../../scene/constants.js';
/**
* @import { BindGroup } from '../../platform/graphics/bind-group.js'
*/ var tempMeshInstances = [];
var lights = [
[],
[],
[]
];
/**
* A render pass implementing rendering of mesh instances into a pick buffer.
*
* @ignore
*/ class RenderPassPicker extends RenderPass {
destroy() {
this.viewBindGroups.forEach((bg)=>{
bg.defaultUniformBuffer.destroy();
bg.destroy();
});
this.viewBindGroups.length = 0;
}
update(camera, scene, layers, mapping) {
this.camera = camera;
this.scene = scene;
this.layers = layers;
this.mapping = mapping;
}
execute() {
var device = this.device;
var { renderer, camera, scene, layers, mapping, renderTarget } = this;
var srcLayers = scene.layers.layerList;
var subLayerEnabled = scene.layers.subLayerEnabled;
var isTransparent = scene.layers.subLayerList;
for(var i = 0; i < srcLayers.length; i++){
var srcLayer = srcLayers[i];
// skip the layer if it does not match the provided ones
if (layers && layers.indexOf(srcLayer) < 0) {
continue;
}
if (srcLayer.enabled && subLayerEnabled[i]) {
// if the layer is rendered by the camera
if (srcLayer.camerasSet.has(camera.camera)) {
var transparent = isTransparent[i];
DebugGraphics.pushGpuMarker(device, srcLayer.name + "(" + (transparent ? 'TRANSP' : 'OPAQUE') + ")");
// if the layer clears the depth
if (srcLayer._clearDepthBuffer) {
renderer.clear(camera.camera, false, true, false);
}
// Use mesh instances from the layer. Ideally we'd just pick culled instances for the camera,
// but we have no way of knowing if culling has been performed since changes to the layer.
// Disadvantage here is that we render all mesh instances, even those not visible by the camera.
var meshInstances = srcLayer.meshInstances;
// only need mesh instances with a pick flag
for(var j = 0; j < meshInstances.length; j++){
var meshInstance = meshInstances[j];
if (meshInstance.pick && meshInstance.transparent === transparent) {
tempMeshInstances.push(meshInstance);
// keep the index -> meshInstance index mapping
mapping.set(meshInstance.id, meshInstance);
}
}
if (tempMeshInstances.length > 0) {
// upload clustered lights uniforms
var clusteredLightingEnabled = scene.clusteredLightingEnabled;
if (clusteredLightingEnabled) {
var lightClusters = renderer.worldClustersAllocator.empty;
lightClusters.activate();
}
renderer.setCameraUniforms(camera.camera, renderTarget);
if (device.supportsUniformBuffers) {
renderer.setupViewUniformBuffers(this.viewBindGroups, renderer.viewUniformFormat, renderer.viewBindGroupFormat, 1);
}
renderer.renderForward(camera.camera, renderTarget, tempMeshInstances, lights, SHADER_PICK, (meshInstance)=>{
device.setBlendState(BlendState.NOBLEND);
});
tempMeshInstances.length = 0;
}
DebugGraphics.popGpuMarker(device);
}
}
}
}
constructor(device, renderer){
super(device), /** @type {BindGroup[]} */ this.viewBindGroups = [];
this.renderer = renderer;
}
}
export { RenderPassPicker };