# GSplatComponentSystem

Class · extends [`ComponentSystem`](https://api.playcanvas.com/engine/classes/ComponentSystem.md) · category: Graphics

Source: https://github.com/playcanvas/engine/blob/970d89f6d3bc6667f4e1f88153abd6e7e82ed52c/src/framework/components/gsplat/system.js#L65

Manages the [GSplatComponent](https://api.playcanvas.com/engine/classes/GSplatComponent.md)s of an application. Reach it through `app.systems.gsplat`;
components are created with [Entity#addComponent](https://api.playcanvas.com/engine/classes/Entity.md#addcomponent), never by calling the system directly.

## Methods

### getMaterial

```ts
getMaterial(camera: Camera, layer: Layer): ShaderMaterial | null
```

Gets the GSplat material for the given camera and layer.

Returns null if the material hasn't been created yet. Materials are created during the first
frame update when the GSplat is rendered. To be notified immediately when materials are
created, listen to the 'material:created' event on GSplatComponentSystem:

**Parameters**

- `camera` (`Camera`): The camera instance.
- `layer` ([`Layer`](https://api.playcanvas.com/engine/classes/Layer.md)): The layer instance.

**Returns** [`ShaderMaterial`](https://api.playcanvas.com/engine/classes/ShaderMaterial.md) `| null`: The material, or null if not created yet.

**Example**

```ts
app.systems.gsplat.on('material:created', (material, camera, layer) => {
    // Material is now available
    material.setParameter('myParam', value);
});
```

## Events

### EVENT_FRAMEREADY

```ts
static EVENT_FRAMEREADY: string = 'frame:ready'
```

Fired every frame for each camera and layer combination rendering GSplats.
The handler is passed the [CameraComponent](https://api.playcanvas.com/engine/classes/CameraComponent.md), the [Layer](https://api.playcanvas.com/engine/classes/Layer.md), a boolean indicating
if the current frame has up-to-date sorting, and a number indicating how many resources are
loading.

The `ready` parameter indicates whether the current frame reflects all recent changes (camera
movement, splat transforms, lod updates, etc.) with the latest sorting applied. The `loadingCount`
parameter reports the total number of octree LOD resources currently loading or queued to load.

This event is useful for video capture or other workflows that need to wait for frames
to be fully ready. Only capture frames and move camera to next position when both
`ready === true` and `loadingCount === 0`. Note that `loadingCount` can be used as a boolean
in conditionals (0 is falsy, non-zero is truthy) for backward compatibility.

**Example**

```ts
// Wait for frame to be ready before capturing
app.systems.gsplat.on('frame:ready', (camera, layer, ready, loadingCount) => {
    if (ready && !loadingCount) {
        console.log(`Frame ready to capture for camera ${camera.entity.name}`);
        // Capture frame here
    }
});
```

**Example**

```ts
// Track loading progress (0..1)
let maxLoadingCount = 0;
app.systems.gsplat.on('frame:ready', (camera, layer, ready, loadingCount) => {
    maxLoadingCount = Math.max(maxLoadingCount, loadingCount);
    const progress = maxLoadingCount > 0 ? (maxLoadingCount - loadingCount) / maxLoadingCount : 1;
    console.log(`Loading progress: ${(progress * 100).toFixed(1)}%`);
});
```

### EVENT_FRAMEREQUEST

```ts
static EVENT_FRAMEREQUEST: string = 'frame:request'
```

Fired once per frame, after the component/script updates and before rendering, when GSplat
streaming has produced new data that a render would show (newly streamed octree LOD) or a CPU
sort result is ready to be applied. This drives on-demand rendering for apps that run with
[AppBase#autoRender](https://api.playcanvas.com/engine/classes/AppBase.md#autorender) set to false: a typical handler sets [AppBase#renderNextFrame](https://api.playcanvas.com/engine/classes/AppBase.md#rendernextframe)
so the new data is shown.

Streaming (LOD evaluation, file loading) runs every frame regardless of `autoRender`, so the
scene keeps loading in the background; this event tells you when it's worth rendering.

Note: this event covers streaming changes only. Changes you make yourself — moving the camera,
modifying the scene, or adding, removing, or changing properties of gsplat components — should
trigger a render yourself.

**Example**

```ts
app.autoRender = false;
app.systems.gsplat.on('frame:request', () => {
    app.renderNextFrame = true;
});
```

### EVENT_MATERIALCREATED

```ts
static EVENT_MATERIALCREATED: string = 'material:created'
```

Fired when a GSplat material is created for a camera and layer combination. Materials are
created during the first frame update when the GSplat is rendered. The handler is passed
the [ShaderMaterial](https://api.playcanvas.com/engine/classes/ShaderMaterial.md), the [CameraComponent](https://api.playcanvas.com/engine/classes/CameraComponent.md), and the [Layer](https://api.playcanvas.com/engine/classes/Layer.md).

This event is useful for setting up custom material chunks and parameters before the
first render.

**Example**

```ts
app.systems.gsplat.on('material:created', (material, camera, layer) => {
    console.log(`Material created for camera ${camera.entity.name} on layer ${layer.name}`);
    // Set custom material parameters before first render
    material.setParameter('myParam', value);
});
```

## Inherited from [ComponentSystem](https://api.playcanvas.com/engine/classes/ComponentSystem.md)

- `fire(name: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any, arg6?: any, arg7?: any, arg8?: any): EventHandler`
- `hasEvent(name: string): boolean`
- `off(name?: string, callback?: HandleEventCallback, scope?: any): EventHandler`
- `on(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
- `once(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
