# Picker

Class · category: Graphics

Source: https://github.com/playcanvas/engine/blob/f059dc005842f76e052cdf44d8370c8c7ec475ac/src/framework/graphics/picker.js#L72

Picker object used to select mesh instances from screen coordinates. It can also optionally
capture depth information to determine world positions of picked points.

The picker works by rendering mesh instances to an offscreen render target with unique IDs
encoded as colors. When queried, it reads back the pixel data to identify which mesh instance
was at the specified screen coordinates. If depth picking is enabled, it also captures depth
values to compute world positions.

**Main API methods:**
- [prepare](https://api.playcanvas.com/engine/classes/Picker.md#prepare) - Renders the pick buffer (call once per frame before picking)
- [getSelectionAsync](https://api.playcanvas.com/engine/classes/Picker.md#getselectionasync) - Get mesh instances in a screen area
- [getWorldPointAsync](https://api.playcanvas.com/engine/classes/Picker.md#getworldpointasync) - Get world position at screen coordinates (requires depth)

**Performance considerations:**
The picker resolution can be set lower than the screen resolution for better performance,
though this reduces picking precision and may miss small objects.

**Example**

```ts
// Create a picker with depth picking enabled at quarter resolution
const picker = new Picker(app, canvas.width * 0.25, canvas.height * 0.25, true);

// In your update loop, prepare the picker
picker.resize(canvas.width * 0.25, canvas.height * 0.25);
picker.prepare(camera, scene);

// Pick mesh instances in an area
picker.getSelectionAsync(x, y, width, height).then((meshInstances) => {
    meshInstances.forEach((meshInstance) => {
        console.log('Picked:', meshInstance.node.name);
    });
});

// Pick world position (requires depth enabled)
picker.getWorldPointAsync(x, y).then((worldPoint) => {
    if (worldPoint) {
        console.log(worldPoint);
    }
});
```

**See** - [Picker Example](http://playcanvas.github.io/#/graphics/area-picker|Area)
 - [Splatting Picking Example](https://playcanvas.github.io/#gaussian-splatting/picking|Gaussian)

## Constructors

### constructor

```ts
new Picker(app: AppBase, width: number, height: number, depth?: boolean)
```

Create a new Picker instance.

**Parameters**

- `app` ([`AppBase`](https://api.playcanvas.com/engine/classes/AppBase.md)): The application managing this picker instance.
- `width` (`number`): The width of the pick buffer in pixels.
- `height` (`number`): The height of the pick buffer in pixels.
- `depth` (`boolean`, optional, default `false`): Whether to enable depth picking. When enabled, depth
  information is captured alongside mesh IDs using MRT. Defaults to false.

## Properties

### height

```ts
height: number
```

### width

```ts
width: number
```

## Methods

### destroy

```ts
destroy(): void
```

Frees resources associated with this picker.

### getSelection

```ts
getSelection(x: number, y: number, width?: number, height?: number): (GSplatComponent | MeshInstance)[]
```

Return the list of mesh instances selected by the specified rectangle in the previously
prepared pick buffer. The rectangle using top-left coordinate system.

Note: This function is not supported on WebGPU. Use [getSelectionAsync](https://api.playcanvas.com/engine/classes/Picker.md#getselectionasync) instead.
Note: This function is blocks the main thread while reading pixels from GPU memory. It's
recommended to use [getSelectionAsync](https://api.playcanvas.com/engine/classes/Picker.md#getselectionasync) instead.

**Parameters**

- `x` (`number`): The left edge of the rectangle.
- `y` (`number`): The top edge of the rectangle.
- `width` (`number`, optional, default `1`): The width of the rectangle. Defaults to 1.
- `height` (`number`, optional, default `1`): The height of the rectangle. Defaults to 1.

**Returns** `(`[`GSplatComponent`](https://api.playcanvas.com/engine/classes/GSplatComponent.md) `|` [`MeshInstance`](https://api.playcanvas.com/engine/classes/MeshInstance.md)`)[]`: An array of mesh instances or gsplat components
that are in the selection.

**Example**

```ts
// Get the selection at the point (10,20)
const selection = picker.getSelection(10, 20);
```

**Example**

```ts
// Get all models in rectangle with corners at (10,20) and (20,40)
const selection = picker.getSelection(10, 20, 10, 20);
```

### getSelectionAsync

```ts
getSelectionAsync(x: number, y: number, width?: number, height?: number): Promise<(GSplatComponent | MeshInstance)[]>
```

Return the list of mesh instances selected by the specified rectangle in the previously
prepared pick buffer. The rectangle uses top-left coordinate system.

This method is asynchronous and does not block the execution.

**Parameters**

- `x` (`number`): The left edge of the rectangle.
- `y` (`number`): The top edge of the rectangle.
- `width` (`number`, optional, default `1`): The width of the rectangle. Defaults to 1.
- `height` (`number`, optional, default `1`): The height of the rectangle. Defaults to 1.

**Returns** `Promise<(`[`GSplatComponent`](https://api.playcanvas.com/engine/classes/GSplatComponent.md) `|` [`MeshInstance`](https://api.playcanvas.com/engine/classes/MeshInstance.md)`)[]>`: - Promise that resolves with an
array of mesh instances or gsplat components that are in the selection.

**Example**

```ts
// Get the mesh instances at the rectangle with start at (10,20) and size of (5,5)
picker.getSelectionAsync(10, 20, 5, 5).then((meshInstances) => {
   console.log(meshInstances);
});
```

### getWorldPointAsync

```ts
getWorldPointAsync(x: number, y: number): Promise<Vec3 | null>
```

Return the world position of the mesh instance picked at the specified screen coordinates.
The position is reconstructed at the center of the pixel containing the coordinates, which
is where its depth was rasterized.

**Parameters**

- `x` (`number`): The x coordinate of the pixel to pick.
- `y` (`number`): The y coordinate of the pixel to pick.

**Returns** `Promise<`[`Vec3`](https://api.playcanvas.com/engine/classes/Vec3.md) `| null>`: Promise that resolves with the world position of the picked point,
or null if no depth is available or nothing was picked.

**Example**

```ts
// Get the world position at screen coordinates (100, 50)
picker.getWorldPointAsync(100, 50).then((worldPoint) => {
    if (worldPoint) {
        console.log('World position:', worldPoint);
        // Use the world position
    } else {
        console.log('No object at this position');
    }
});
```

### prepare

```ts
prepare(camera: CameraComponent, scene: Scene, layers?: Layer[]): void
```

Primes the pick buffer with a rendering of the specified models from the point of view of
the supplied camera. Once the pick buffer has been prepared, [getSelection](https://api.playcanvas.com/engine/classes/Picker.md#getselection) can
be called multiple times on the same picker object. Therefore, if the models or camera do
not change in any way, [prepare](https://api.playcanvas.com/engine/classes/Picker.md#prepare) does not need to be called again.

**Parameters**

- `camera` ([`CameraComponent`](https://api.playcanvas.com/engine/classes/CameraComponent.md)): The camera component used to render the scene.
- `scene` ([`Scene`](https://api.playcanvas.com/engine/classes/Scene.md)): The scene containing the pickable mesh instances.
- `layers` ([`Layer`](https://api.playcanvas.com/engine/classes/Layer.md)`[]`, optional): Layers from which objects will be picked. If not supplied, all
  layers of the specified camera will be used.

### resize

```ts
resize(width: number, height: number): void
```

Sets the resolution of the pick buffer. The pick buffer resolution does not need to match
the resolution of the corresponding frame buffer use for general rendering of the 3D scene.
However, the lower the resolution of the pick buffer, the less accurate the selection
results returned by [getSelection](https://api.playcanvas.com/engine/classes/Picker.md#getselection). On the other hand, smaller pick buffers
will yield greater performance, so there is a trade off.

**Parameters**

- `width` (`number`): The width of the pick buffer in pixels.
- `height` (`number`): The height of the pick buffer in pixels.
