UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

94 lines (91 loc) 4.32 kB
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 };