playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
142 lines (141 loc) • 7.17 kB
TypeScript
/**
* 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';