UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

142 lines (141 loc) 7.17 kB
/** * Performs the visibility culling for a {@link Renderer}: per-camera light visibility, * mesh-instance culling (request/execute) and shadow-caster culling. It holds the per-frame * culling state and operates on the renderer's shared state (lights, shadow renderers, light * atlas, stats) through a back-reference to the renderer. * * @ignore */ export class Culler { /** * @param {Renderer} renderer - The renderer that owns this culler. */ constructor(renderer: Renderer); /** * A set of visible mesh instances which need further processing before being rendered, e.g. * skinning or morphing. Extracted during culling. * * @type {Set<MeshInstance>} */ processingMeshInstances: Set<MeshInstance>; /** * The distinct cameras with mesh-instance cull requests registered for the current frame, in * registration order. Populated by {@link Culler#requestMeshInstanceCull} and drained by * {@link Culler#executeMeshInstanceCull}. Reused across frames to avoid per-frame allocation. * * @type {Camera[]} * @private */ private _cullCameras; /** * A list of unique directional shadow casting lights for each enabled camera. This is generated * each frame during light culling. * * @type {Map<Camera, Array<Light>>} */ cameraDirShadowLights: Map<Camera, Array<Light>>; /** * A mapping of a directional light to a camera, for which the shadow is currently valid. This * is cleared each frame, and updated each time a directional light shadow is rendered for a * camera, and allows us to manually schedule shadow passes when a new camera needs a shadow. * * @type {Map<Light, Camera>} */ dirLightShadows: Map<Light, Camera>; /** @type {Renderer} */ renderer: Renderer; /** * @param {Camera} camera - The camera used for culling. * @param {MeshInstance[]} drawCalls - Draw calls to cull. * @param {CulledInstances} culledInstances - Stores culled instances. */ cullMeshInstances(camera: Camera, drawCalls: MeshInstance[], culledInstances: CulledInstances): void; /** * Culls a set of lights against a camera's frustum, marking the visible ones (and updating their * max screen size and physical-units flag). Directional lights are marked visible at the start * of the frame and are skipped here, so only local (omni / spot) lights are frustum tested. In * non-clustered lighting, a shadow-casting light with no shadow map allocated yet is also marked * visible so its shadow map gets allocated. * * @param {Camera} camera - The camera whose frustum the lights are culled against. * @param {Light[]} lights - The lights to cull (typically a layer's lights). */ cullLights(camera: Camera, lights: Light[]): void; /** * Shadow map culling for directional and visible local lights visible meshInstances are * collected into light._renderData, and are marked as visible for directional lights also * shadow camera matrix is set up. * * @param {LayerComposition} comp - The layer composition. */ cullShadowmaps(comp: LayerComposition): void; /** * After the frame graph is built and shadow casters are culled, account for shadow-map updates * and consume one-shot ({@link SHADOWUPDATE_THISFRAME}) requests for lights whose shadow * actually rendered this frame, reverting them to {@link SHADOWUPDATE_NONE}. A light that did * not render this frame (for example an off-screen local light) keeps its request, so the * shadow updates the next frame the light is rendered. Must run after both the frame graph build * and shadow-caster culling, so that `needsShadowRendering` (a pure predicate) reports the same * result to both before the update mode is changed here. */ consumeOneShotShadows(): void; /** * Collects the set of shadow-casting directional lights for each camera into * {@link Culler#cameraDirShadowLights}, and ensures each such light has a shadow map allocated. * This is independent of mesh culling and camera frusta (it uses only the composition's cameras * and the layers' directional lights), so it can run before the frame graph is built. The * actual shadow-caster culling is done separately. * * @param {LayerComposition} comp - The layer composition. */ collectDirectionalShadowLights(comp: LayerComposition): void; /** * Per-camera light visibility culling, light-atlas allocation and directional-shadow-light * collection. This is independent of mesh culling and the frame graph, so it runs before the * frame graph is built. The mesh and shadow-caster culling that depends on it is done later in * {@link Culler#cullComposition}. * * @param {LayerComposition} comp - The layer composition. */ updateLightVisibility(comp: LayerComposition): void; /** * Registers a request to cull a layer's mesh instances for a camera in the current frame. The * culling itself is performed later, in a single batch, by * {@link Culler#executeMeshInstanceCull}. Requests are de-duplicated per (camera, layer), so * requesting the same pair more than once (e.g. for its opaque and transparent sub-layers) is * harmless. * * This lets the frame graph drive culling - each pass requests the (camera, layer) pairs it * will actually render - instead of culling every camera/layer combination in the composition. * * @param {Camera} camera - The camera to cull for. * @param {Layer} layer - The layer whose mesh instances should be culled. */ requestMeshInstanceCull(camera: Camera, layer: Layer): void; /** * Performs all mesh-instance culling requested via {@link Culler#requestMeshInstanceCull} this * frame, then clears the request list. For each requested camera the precull event is fired * (before the frustum is refreshed, so a listener may still adjust the camera), the camera * frustum is updated, each requested layer is culled, and the postcull event is fired. * * The events are passed the owning camera component for a framework camera, or null for an * internal camera (shadow / reflection / picker), matching the documented precull/postcull * contract. */ executeMeshInstanceCull(): void; /** * Visibility culling of meshInstances and shadow casters. Light visibility, the light atlas and * the directional-shadow-light collection are done earlier in * {@link Culler#updateLightVisibility}. * * @param {LayerComposition} comp - The layer composition. */ cullComposition(comp: LayerComposition): void; } import type { MeshInstance } from '../mesh-instance.js'; import type { Camera } from '../camera.js'; import type { Light } from '../light.js'; import type { Renderer } from './renderer.js'; import type { CulledInstances } from '../layer.js'; import type { LayerComposition } from '../composition/layer-composition.js'; import type { Layer } from '../layer.js';