@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
276 lines (275 loc) • 11.9 kB
TypeScript
import { ShaderLanguage } from "../Materials/shaderLanguage.js";
import { ShaderMaterial } from "../Materials/shaderMaterial.pure.js";
import { type IVector2Like } from "../Maths/math.like.js";
import { Vector3 } from "../Maths/math.vector.pure.js";
import { type AbstractMesh } from "../Meshes/abstractMesh.js";
import { type Nullable } from "../types.js";
/**
* Class used to store the result of a GPU picking operation
*/
export interface IGPUPickingInfo {
/**
* Picked mesh
*/
mesh: AbstractMesh;
/**
* Picked thin instance index
*/
thinInstanceIndex?: number;
/**
* Picked point in world space.
*
* Only available when enableDepthPicking is true and a valid depth value can be read.
* Custom picking materials or special material plugins that do not write the depth attachment may return undefined.
*/
pickedPoint?: Vector3;
/**
* Reconstructed normal in world space.
*
* Only available when enableDepthPicking is true and enough valid depth neighbors can be read.
* Custom picking materials or special material plugins that do not write the depth attachment may return undefined.
*/
normal?: Vector3;
}
/**
* Stores the result of a multi GPU picking operation
*/
export interface IGPUMultiPickingInfo {
/**
* Picked mesh
*/
meshes: Nullable<AbstractMesh>[];
/**
* Picked thin instance index
*/
thinInstanceIndexes?: number[];
/**
* Picked points in world space.
*
* Only available when enableDepthPicking is true and a valid depth value can be read.
* Custom picking materials or special material plugins that do not write the depth attachment may return null.
*/
pickedPoints?: Nullable<Vector3>[];
/**
* Reconstructed normals in world space.
*
* Only available when enableDepthPicking is true and enough valid depth neighbors can be read.
* Custom picking materials or special material plugins that do not write the depth attachment may return null.
*/
normals?: Nullable<Vector3>[];
}
/**
* Defines how multi pick texture readbacks should be performed.
*/
export declare enum GPUMultiPickReadbackStrategy {
/**
* Chooses between a single rectangle readback and small per-point readbacks using the thresholds in IGPUMultiPickOptions.
*/
Auto = 0,
/**
* Always reads the full bounding rectangle of the picked points. This minimizes readback calls and is best for dense point sets.
*/
Rectangle = 1,
/**
* Always reads each picked point independently. This minimizes transferred pixels for sparse point sets but can be slower when many points are picked.
*/
Individual = 2
}
/**
* Options used to tune multi GPU picking.
*/
export interface IGPUMultiPickOptions {
/**
* Defines how multi pick texture readbacks should be performed.
*
* Defaults to GPUMultiPickReadbackStrategy.Auto.
*/
readbackStrategy?: GPUMultiPickReadbackStrategy;
/**
* Maximum number of in-bounds points allowed for the automatic individual readback path.
* This value is ignored when readbackStrategy is set to GPUMultiPickReadbackStrategy.Rectangle or GPUMultiPickReadbackStrategy.Individual.
*
* Defaults to 32.
*/
maxIndividualReadbackCount?: number;
/**
* Minimum rectangle-area / individual-area ratio required before the automatic path uses individual readbacks.
* This value is ignored when readbackStrategy is set to GPUMultiPickReadbackStrategy.Rectangle or GPUMultiPickReadbackStrategy.Individual.
*
* Defaults to 16.
*/
individualReadbackAreaRatio?: number;
}
/**
* Class used to perform a picking operation using GPU
* GPUPicker can pick meshes, instances and thin instances
*/
export declare class GPUPicker {
private static readonly _AttributeName;
private static readonly _MaxPickingId;
private static readonly _DepthPixelRadius;
private static readonly _MaxMultiPickIndividualReadbackCount;
private static readonly _MultiPickIndividualReadbackAreaRatio;
private static readonly _DepthNeighborOffsets;
private _pickingTexture;
private readonly _idMap;
private readonly _thinIdMap;
private readonly _meshUniqueIdToPickerId;
private _idWarningIssued;
private _cachedScene;
private _engine;
private readonly _pickingMaterialCache;
private _pickableMeshes;
private readonly _meshMaterialMap;
private _readbuffer;
private _depthReadbuffer;
private _depthTextureType;
private _isDepthTexturePacked;
private _useDepthPicking;
private _isUsingDepthPickingRenderTarget;
private _meshRenderingCount;
private _renderWarningIssued;
private _renderPickingTexture;
private _sceneBeforeRenderObserver;
private _pickingTextureClearObserver;
private _pickingTextureAfterRenderObserver;
private _nextFreeId;
private readonly _gsPickingMaterials;
private readonly _gsCompoundRenderMeshes;
/** Shader language used by the generator */
protected _shaderLanguage: ShaderLanguage;
/**
* Gets the shader language used in this generator.
*/
get shaderLanguage(): ShaderLanguage;
private _pickingInProgress;
/**
* Gets a boolean indicating if the picking is in progress
*/
get pickingInProgress(): boolean;
/**
* Gets the default render materials used by the picker.
*
* index is Material filling mode
*/
get defaultRenderMaterials(): readonly Nullable<ShaderMaterial>[];
/**
* Gets or sets a boolean indicating if depth-based pickedPoint and normal reconstruction should be enabled.
*
* When disabled, GPUPicker uses the original single-color render target and shader path. When enabled, GPUPicker
* switches to a MultiRenderTarget and compiles the default picking shader with GPUPICKER_DEPTH to output both the
* picking id and the depth required to reconstruct the picked point and normal.
*
* Custom picking materials and special picking material plugins should also write the depth attachment. If they do
* not, GPUPicker will still try to reconstruct pickedPoint and normal from the depth target, but the returned values
* may be missing or incorrect.
*/
get enableDepthPicking(): boolean;
set enableDepthPicking(value: boolean);
private _getColorIdFromReadBuffer;
private _getReadBufferOffset;
private _createColorPickingRenderTarget;
private _createRenderTarget;
private _clearPickingMaterials;
private _getPickingMaterial;
private _materialBindCallback;
/**
* Set the list of meshes to pick from
* Set that value to null to clear the list (and avoid leaks)
* The module will read and delete from the array provided by reference. Disposing the module or setting the value to null will clear the array.
* @param list defines the list of meshes to pick from
*/
setPickingList(list: Nullable<Array<AbstractMesh | {
mesh: AbstractMesh;
material: ShaderMaterial;
}>>): void;
/**
* Clear the current picking list and free resources
*/
clearPickingList(): void;
/**
* Add array of meshes to the current picking list
* @param list defines the array of meshes to add to the current picking list
*/
addPickingList(list: Array<AbstractMesh | {
mesh: AbstractMesh;
material: ShaderMaterial;
}>): void;
/**
* Execute a picking operation
* @param x defines the X coordinates where to run the pick
* @param y defines the Y coordinates where to run the pick
* @param disposeWhenDone defines a boolean indicating we do not want to keep resources alive (false by default)
* @returns A promise with the picking results
*/
pickAsync(x: number, y: number, disposeWhenDone?: boolean): Promise<Nullable<IGPUPickingInfo>>;
/**
* Execute a picking operation on multiple coordinates
* @param xy defines the X,Y coordinates where to run the pick
* @param disposeWhenDone defines a boolean indicating we do not want to keep resources alive (false by default)
* @param options defines options used to tune the multi pick readback strategy
* @returns A promise with the picking results. Always returns an array with the same length as the number of coordinates. The mesh or null at the index where no mesh was picked.
*/
multiPickAsync(xy: IVector2Like[], disposeWhenDone?: boolean, options?: IGPUMultiPickOptions): Promise<Nullable<IGPUMultiPickingInfo>>;
/**
* Execute a picking operation on box defined by two screen coordinates
* @param x1 defines the X coordinate of the first corner of the box where to run the pick
* @param y1 defines the Y coordinate of the first corner of the box where to run the pick
* @param x2 defines the X coordinate of the opposite corner of the box where to run the pick
* @param y2 defines the Y coordinate of the opposite corner of the box where to run the pick
* @param disposeWhenDone defines a boolean indicating we do not want to keep resources alive (false by default)
* @returns A promise with the picking results. Contains one entry for each picked pixel in the box.
*/
boxPickAsync(x1: number, y1: number, x2: number, y2: number, disposeWhenDone?: boolean): Promise<Nullable<IGPUMultiPickingInfo>>;
private _getRenderInfo;
private _prepareForPicking;
private _getPickingRenderRegion;
private _shouldUseIndividualMultiPickReadback;
private _preparePickingBuffer;
private _addPickingTextureToRenderTargets;
private _removePickingTextureFromRenderTargets;
private _executePickingAsync;
private _executeMultiPickingAsync;
private _executeBoxPickingAsync;
private _enableScissor;
private _disableScissor;
/**
* @returns true if rendering if the picking texture has finished, otherwise false
*/
private _checkRenderStatus;
/**
* Polls the picking material variant for every mesh in the render list until every
* variant is ready. Picking materials use parallel shader compilation, and a single
* ShaderMaterial may produce different effect variants per mesh (instances, thin
* instances, vertex colors, ...). If we render the picking texture before all variants
* are compiled, the renderer silently skips meshes whose effect is not yet ready, which
* can leave the click pixel cleared (0,0,0,0) and cause pickAsync to incorrectly return
* null. Once compiled, effects are cached by define string in the engine, so this
* polling only blocks on the very first pick (or whenever the render list changes to
* include meshes with new define combinations).
*/
private _waitForPickingMaterialsReadyAsync;
private _getMeshFromMultiplePoints;
private _getMeshFromReadBuffer;
/**
* Updates the render list with the current pickable meshes.
*/
private _updateRenderList;
/**
* Creates a GaussianSplattingMaterial configured for GPU picking by attaching
* a GaussianSplattingGpuPickingMaterialPlugin. The plugin injects picking ID
* encoding into the existing Gaussian Splatting shaders via material plugin hooks.
* @param scene The scene
* @param gsMesh The Gaussian Splatting mesh (used to set the source mesh on the material)
* @returns A GaussianSplattingMaterial with the picking plugin attached
*/
private _createGaussianSplattingPickingMaterial;
private _readTexturePixelsAsync;
private _readDepthTexturePixelsAsync;
private _getDepthPickingInfoAsync;
private _getDepthPickingInfoFromBuffer;
private _getDepthPointFromBufferToRef;
private _getDepthFromBuffer;
/** Release the resources */
dispose(): void;
}