---
title: "environment"
description: "The environment namespace — the engine's Luau API reference for environment."
section: "API Reference"
slug: "api-environment"
canonical: "https://origozero.ai/docs/api-environment"
updated: "2026-09-05T23:13:46.433449531+00:00"
tags: ["api", "reference"]
---

# environment

The `environment` namespace — 31 functions.

## globals/environment/capture {#globals-environment-capture}

```lua
environment.capture(x: number, y: number, z: number) -> boolean
```

Bake the scene into the environment from `(x, y, z)` as the single global
reflection (slot 0 + one full-coverage probe). Every PBR surface reflects it.
Queued — takes effect on the next frame. For multiple proximity-blended
probes use the reflectionProbe system instead.

**Parameters**

- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `boolean` — True — the capture was queued.

```lua
environment.capture(0, 2, 0)
```

## globals/environment/captureSky {#globals-environment-capturesky}

```lua
environment.captureSky(x: number?, y: number?, z: number?) -> boolean
```

Render the SKY alone into the environment's sky slot from `(x, y, z)` and
arm the sky fallback. A reflective surface no probe covers then reflects the
sky rather than black, and a partially covered one blends the shortfall
against it. The capture holds whatever the scene's sky draws — a gradient, a
physical atmosphere, a skybox material — with no geometry in it, so it stays
correct wherever the camera goes. Once captured, the slot follows the sky
the scene draws: a sky that changes is recaptured from the same position.
Queued — takes effect on the next frame.

**Parameters**

- `x` `number` _(optional)_ — World X of the capture position. Defaults to 0.
- `y` `number` _(optional)_ — World Y of the capture position — the altitude a height-dependent
atmosphere is sampled at. Defaults to 0.
- `z` `number` _(optional)_ — World Z of the capture position. Defaults to 0.

**Returns** `boolean` — True — the sky capture was queued.

```lua
environment.captureSky()
```

## globals/environment/captureSlot {#globals-environment-captureslot}

```lua
environment.captureSlot(slot: number, x: number, y: number, z: number) -> boolean
```

Bake the scene into reflection-probe `slot` from `(x, y, z)`.
Renders the FULL scene (geometry + sky) six times from that
point into that slot. Register the probe's position+radius via `setProbes`
so surfaces blend it by proximity. Queued — takes effect next frame.

**Parameters**

- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `boolean` — True — the capture was queued.

```lua
environment.captureSlot(0, 0, 2, 0)
```

## globals/environment/captureSlotToAsset {#globals-environment-captureslottoasset}

```lua
environment.captureSlotToAsset(name: string, slot: number, x: number, y: number, z: number, timeoutFrames: number?) -> (string?, string?)
```

Bake the scene into reflection-probe `slot` from `(x, y, z)` AND persist
the 6 rendered faces into a `faces6` `.texture` cubemap asset at
`/source/<name>.texture/` (px/nx/py/ny/pz/nz PNGs + a `cube.yaml` sidecar).
Survives an engine restart and syncs like any other texture. Yields a few
frames while the bake + GPU readback complete; must be called from a
task/coroutine context (component hook, `task.spawn`, or `execute`). NATIVE
only — the wasm async-readback path is a tracked follow-up.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.
- `timeoutFrames` `number` _(optional)_ — Optional max frames to wait for the readback (default 180).

**Returns** `(string?, string?)` — The asset path on success, or `(nil, errorMessage)` on failure.

```lua
environment.captureSlotToAsset("probe_lobby", 0, 0, 2, 0)
```

## globals/environment/captureToAsset {#globals-environment-capturetoasset}

```lua
environment.captureToAsset(name: string, x: number, y: number, z: number) -> (string?, string?)
```

Bake the single global reflection AND persist it to a `faces6` `.texture`
asset (slot 0). Yields a few frames; call from a task/coroutine context.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `(string?, string?)` — The asset path on success, or `(nil, errorMessage)` on failure.

```lua
environment.captureToAsset("env_main", 0, 2, 0)
```

## globals/environment/ensureSkyFallback {#globals-environment-ensureskyfallback}

```lua
environment.ensureSkyFallback() -> boolean
```

Ensure the scene's sky is in the environment's sky slot: a reflective
surface no probe covers then reflects the sky rather than black, and a
partially covered one blends the shortfall against it. Queues a capture
when the sky slot holds none, and re-arms the fallback when a capture is
there but switched off. The engine's own state answers both questions, so
everything that stands a sky up can call this and one capture is shared
between them. Once captured, the slot follows the sky the scene draws on
its own.

**Returns** `boolean` — True if a capture was queued, false if the sky slot already holds one.

```lua
environment.ensureSkyFallback()
```

## globals/environment/loadFromAsset {#globals-environment-loadfromasset}

```lua
environment.loadFromAsset(name: string) -> (boolean, string?)
```

Load a persisted global reflection asset into slot 0 and make it the
active single reflection (one full-coverage probe).

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).

**Returns** `(boolean, string?)` — True on success, or `(false, errorMessage)` on failure.

```lua
environment.loadFromAsset("env_main")
```

## globals/environment/loadSlotFromAsset {#globals-environment-loadslotfromasset}

```lua
environment.loadSlotFromAsset(name: string, slot: number) -> (boolean, string?)
```

Load a persisted `faces6` `.texture` cubemap (written by
`captureSlotToAsset`) into reflection-probe `slot` WITHOUT re-rendering the
scene. Reads the 6 face PNGs from `/source/<name>.texture/` and uploads them
into the slot's cube layers. How a persisted probe restores its baked
environment on reload.

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).

**Returns** `(boolean, string?)` — True on success, or `(false, errorMessage)` on failure.

```lua
environment.loadSlotFromAsset("probe_lobby", 0)
```

## globals/environment/setProbes {#globals-environment-setprobes}

```lua
environment.setProbes(probes: { any }) -> boolean
```

Set the active reflection probes' blend data. `probes` is an array of
`{ x, y, z, radius }` (or `{ position = {x,y,z}, radius = r }`); index i is
probe slot i. Surfaces blend the probe slots by proximity to these
positions, gathering the highest `priority` first — each rank takes the
coverage the ranks above it left, so a small interior probe ranked above a
large exterior one wins outright wherever it reaches full weight. Coverage
left over reflects the sky once `captureSky` has run. Queued for next frame.

**Parameters**

- `probes` `{ any }` — Array of `{ x, y, z, radius, priority? }`, one per active probe
slot. `priority` defaults to 0.

**Returns** `boolean` — True — the probe data was queued.

```lua
environment.setProbes({ { x = 0, y = 2, z = 0, radius = 12 } })
```

## globals/environment/setSkyFallback {#globals-environment-setskyfallback}

```lua
environment.setSkyFallback(active: boolean) -> boolean
```

Arm or disarm the sky fallback against the sky already captured, with no
recapture. Disarmed, reflections come from the probes alone. Arming is
refused while the sky slot holds no capture (`captureSky` fills it), since
an uncaptured slot reflects black; `renderer.reflectionEnvironment()`
reports whether the fallback ended up armed.

**Parameters**

- `active` `boolean` — Whether reflections fall back to the captured sky.

**Returns** `boolean` — True — the change was queued.

```lua
environment.setSkyFallback(false)
```

## modules/environment/README {#modules-environment-readme}

```lua
require("@builtin/modules/api/engine/environment") -- environment (also available as global 'environment')
```

Environment / reflection capture — bake the scene into reflection-probe cube slots from world positions, persist them as `faces6` `.texture` assets, and set per-probe blend data so surfaces reflect the nearest probe(s). Public Luau surface over the `__environment` Internal FFI namespace. The generic "render the scene into a cubemap from a point" capability the reflection probe system is built on.

Usage: local environment = require("@builtin/modules/api/engine/environment")
Also available as global: environment

## modules/environment/capture {#modules-environment-capture}

```lua
capture(x: number, y: number, z: number): boolean
```

Bake the scene into the environment from `(x, y, z)` as the single global
reflection (slot 0 + one full-coverage probe). Every PBR surface reflects it.
Queued — takes effect on the next frame. For multiple proximity-blended
probes use the reflectionProbe system instead.

**Parameters**

- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

```lua
environment.capture(0, 2, 0)
```

## modules/environment/captureSky {#modules-environment-capturesky}

```lua
captureSky(x: number?, y: number?, z: number?): boolean
```

Render the SKY alone into the environment's sky slot from `(x, y, z)` and
arm the sky fallback. A reflective surface no probe covers then reflects the
sky rather than black, and a partially covered one blends the shortfall
against it. The capture holds whatever the scene's sky draws — a gradient, a
physical atmosphere, a skybox material — with no geometry in it, so it stays
correct wherever the camera goes. Once captured, the slot follows the sky
the scene draws: a sky that changes is recaptured from the same position.
Queued — takes effect on the next frame.

**Parameters**

- `x` `number?` _(optional)_ — World X of the capture position. Defaults to 0.
- `y` `number?` _(optional)_ — World Y of the capture position — the altitude a height-dependent
atmosphere is sampled at. Defaults to 0.
- `z` `number?` _(optional)_ — World Z of the capture position. Defaults to 0.

```lua
environment.captureSky()
```

## modules/environment/captureSlot {#modules-environment-captureslot}

```lua
captureSlot(slot: number, x: number, y: number, z: number): boolean
```

Bake the scene into reflection-probe `slot` from `(x, y, z)`.
Renders the FULL scene (geometry + sky) six times from that
point into that slot. Register the probe's position+radius via `setProbes`
so surfaces blend it by proximity. Queued — takes effect next frame.

**Parameters**

- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

```lua
environment.captureSlot(0, 0, 2, 0)
```

## modules/environment/captureSlotToAsset {#modules-environment-captureslottoasset}

```lua
captureSlotToAsset(name: string, slot: number, x: number, y: number, z: number, timeoutFrames: number?): (string?, string?)
```

Bake the scene into reflection-probe `slot` from `(x, y, z)` AND persist
the 6 rendered faces into a `faces6` `.texture` cubemap asset at
`/source/<name>.texture/` (px/nx/py/ny/pz/nz PNGs + a `cube.yaml` sidecar).
Survives an engine restart and syncs like any other texture. Yields a few
frames while the bake + GPU readback complete; must be called from a
task/coroutine context (component hook, `task.spawn`, or `execute`). NATIVE
only — the wasm async-readback path is a tracked follow-up.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.
- `timeoutFrames` `number?` _(optional)_ — Optional max frames to wait for the readback (default 180).

```lua
environment.captureSlotToAsset("probe_lobby", 0, 0, 2, 0)
```

## modules/environment/captureToAsset {#modules-environment-capturetoasset}

```lua
captureToAsset(name: string, x: number, y: number, z: number): (string?, string?)
```

Bake the single global reflection AND persist it to a `faces6` `.texture`
asset (slot 0). Yields a few frames; call from a task/coroutine context.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

```lua
environment.captureToAsset("env_main", 0, 2, 0)
```

## modules/environment/ensureSkyFallback {#modules-environment-ensureskyfallback}

```lua
ensureSkyFallback(): boolean
```

Ensure the scene's sky is in the environment's sky slot: a reflective
surface no probe covers then reflects the sky rather than black, and a
partially covered one blends the shortfall against it. Queues a capture
when the sky slot holds none, and re-arms the fallback when a capture is
there but switched off. The engine's own state answers both questions, so
everything that stands a sky up can call this and one capture is shared
between them. Once captured, the slot follows the sky the scene draws on
its own.

```lua
environment.ensureSkyFallback()
```

## modules/environment/loadFromAsset {#modules-environment-loadfromasset}

```lua
loadFromAsset(name: string): (boolean, string?)
```

Load a persisted global reflection asset into slot 0 and make it the
active single reflection (one full-coverage probe).

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).

```lua
environment.loadFromAsset("env_main")
```

## modules/environment/loadSlotFromAsset {#modules-environment-loadslotfromasset}

```lua
loadSlotFromAsset(name: string, slot: number): (boolean, string?)
```

Load a persisted `faces6` `.texture` cubemap (written by
`captureSlotToAsset`) into reflection-probe `slot` WITHOUT re-rendering the
scene. Reads the 6 face PNGs from `/source/<name>.texture/` and uploads them
into the slot's cube layers. How a persisted probe restores its baked
environment on reload.

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).

```lua
environment.loadSlotFromAsset("probe_lobby", 0)
```

## modules/environment/setProbes {#modules-environment-setprobes}

```lua
setProbes(probes: { any }): boolean
```

Set the active reflection probes' blend data. `probes` is an array of
`{ x, y, z, radius }` (or `{ position = {x,y,z}, radius = r }`); index i is
probe slot i. Surfaces blend the probe slots by proximity to these
positions, gathering the highest `priority` first — each rank takes the
coverage the ranks above it left, so a small interior probe ranked above a
large exterior one wins outright wherever it reaches full weight. Coverage
left over reflects the sky once `captureSky` has run. Queued for next frame.

**Parameters**

- `probes` `{ any }` — Array of `{ x, y, z, radius, priority? }`, one per active probe
slot. `priority` defaults to 0.

```lua
environment.setProbes({ { x = 0, y = 2, z = 0, radius = 12 } })
```

## modules/environment/setSkyFallback {#modules-environment-setskyfallback}

```lua
setSkyFallback(active: boolean): boolean
```

Arm or disarm the sky fallback against the sky already captured, with no
recapture. Disarmed, reflections come from the probes alone. Arming is
refused while the sky slot holds no capture (`captureSky` fills it), since
an uncaptured slot reflects black; `renderer.reflectionEnvironment()`
reports whether the fallback ended up armed.

**Parameters**

- `active` `boolean` — Whether reflections fall back to the captured sky.

```lua
environment.setSkyFallback(false)
```

## typed/builtin//modules/api/engine/environment/environment/capture {#typed-builtin-modules-api-engine-environment-environment-capture}

```lua
environment.capture(x: number, y: number, z: number) -> boolean
```

Bake the scene into the environment from `(x, y, z)` as the single global
reflection (slot 0 + one full-coverage probe). Every PBR surface reflects it.
Queued — takes effect on the next frame. For multiple proximity-blended
probes use the reflectionProbe system instead.

**Parameters**

- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `boolean` — True — the capture was queued.

```lua
environment.capture(0, 2, 0)
```

## typed/builtin//modules/api/engine/environment/environment/captureSky {#typed-builtin-modules-api-engine-environment-environment-capturesky}

```lua
environment.captureSky(x: number?, y: number?, z: number?) -> boolean
```

Render the SKY alone into the environment's sky slot from `(x, y, z)` and
arm the sky fallback. A reflective surface no probe covers then reflects the
sky rather than black, and a partially covered one blends the shortfall
against it. The capture holds whatever the scene's sky draws — a gradient, a
physical atmosphere, a skybox material — with no geometry in it, so it stays
correct wherever the camera goes. Once captured, the slot follows the sky
the scene draws: a sky that changes is recaptured from the same position.
Queued — takes effect on the next frame.

**Parameters**

- `x` `number` _(optional)_ — World X of the capture position. Defaults to 0.
- `y` `number` _(optional)_ — World Y of the capture position — the altitude a height-dependent
atmosphere is sampled at. Defaults to 0.
- `z` `number` _(optional)_ — World Z of the capture position. Defaults to 0.

**Returns** `boolean` — True — the sky capture was queued.

```lua
environment.captureSky()
```

## typed/builtin//modules/api/engine/environment/environment/captureSlot {#typed-builtin-modules-api-engine-environment-environment-captureslot}

```lua
environment.captureSlot(slot: number, x: number, y: number, z: number) -> boolean
```

Bake the scene into reflection-probe `slot` from `(x, y, z)`.
Renders the FULL scene (geometry + sky) six times from that
point into that slot. Register the probe's position+radius via `setProbes`
so surfaces blend it by proximity. Queued — takes effect next frame.

**Parameters**

- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `boolean` — True — the capture was queued.

```lua
environment.captureSlot(0, 0, 2, 0)
```

## typed/builtin//modules/api/engine/environment/environment/captureSlotToAsset {#typed-builtin-modules-api-engine-environment-environment-captureslottoasset}

```lua
environment.captureSlotToAsset(name: string, slot: number, x: number, y: number, z: number, timeoutFrames: number?) -> (string?, string?)
```

Bake the scene into reflection-probe `slot` from `(x, y, z)` AND persist
the 6 rendered faces into a `faces6` `.texture` cubemap asset at
`/source/<name>.texture/` (px/nx/py/ny/pz/nz PNGs + a `cube.yaml` sidecar).
Survives an engine restart and syncs like any other texture. Yields a few
frames while the bake + GPU readback complete; must be called from a
task/coroutine context (component hook, `task.spawn`, or `execute`). NATIVE
only — the wasm async-readback path is a tracked follow-up.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.
- `timeoutFrames` `number` _(optional)_ — Optional max frames to wait for the readback (default 180).

**Returns** `(string?, string?)` — The asset path on success, or `(nil, errorMessage)` on failure.

```lua
environment.captureSlotToAsset("probe_lobby", 0, 0, 2, 0)
```

## typed/builtin//modules/api/engine/environment/environment/captureToAsset {#typed-builtin-modules-api-engine-environment-environment-capturetoasset}

```lua
environment.captureToAsset(name: string, x: number, y: number, z: number) -> (string?, string?)
```

Bake the single global reflection AND persist it to a `faces6` `.texture`
asset (slot 0). Yields a few frames; call from a task/coroutine context.

**Parameters**

- `name` `string` — Destination asset identity (writes `/source/<name>.texture/`).
- `x` `number` — World X of the capture position.
- `y` `number` — World Y of the capture position.
- `z` `number` — World Z of the capture position.

**Returns** `(string?, string?)` — The asset path on success, or `(nil, errorMessage)` on failure.

```lua
environment.captureToAsset("env_main", 0, 2, 0)
```

## typed/builtin//modules/api/engine/environment/environment/ensureSkyFallback {#typed-builtin-modules-api-engine-environment-environment-ensureskyfallback}

```lua
environment.ensureSkyFallback() -> boolean
```

Ensure the scene's sky is in the environment's sky slot: a reflective
surface no probe covers then reflects the sky rather than black, and a
partially covered one blends the shortfall against it. Queues a capture
when the sky slot holds none, and re-arms the fallback when a capture is
there but switched off. The engine's own state answers both questions, so
everything that stands a sky up can call this and one capture is shared
between them. Once captured, the slot follows the sky the scene draws on
its own.

**Returns** `boolean` — True if a capture was queued, false if the sky slot already holds one.

```lua
environment.ensureSkyFallback()
```

## typed/builtin//modules/api/engine/environment/environment/loadFromAsset {#typed-builtin-modules-api-engine-environment-environment-loadfromasset}

```lua
environment.loadFromAsset(name: string) -> (boolean, string?)
```

Load a persisted global reflection asset into slot 0 and make it the
active single reflection (one full-coverage probe).

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).

**Returns** `(boolean, string?)` — True on success, or `(false, errorMessage)` on failure.

```lua
environment.loadFromAsset("env_main")
```

## typed/builtin//modules/api/engine/environment/environment/loadSlotFromAsset {#typed-builtin-modules-api-engine-environment-environment-loadslotfromasset}

```lua
environment.loadSlotFromAsset(name: string, slot: number) -> (boolean, string?)
```

Load a persisted `faces6` `.texture` cubemap (written by
`captureSlotToAsset`) into reflection-probe `slot` WITHOUT re-rendering the
scene. Reads the 6 face PNGs from `/source/<name>.texture/` and uploads them
into the slot's cube layers. How a persisted probe restores its baked
environment on reload.

**Parameters**

- `name` `string` — Source asset identity (reads `/source/<name>.texture/`).
- `slot` `number` — Reflection-probe slot (0-based).

**Returns** `(boolean, string?)` — True on success, or `(false, errorMessage)` on failure.

```lua
environment.loadSlotFromAsset("probe_lobby", 0)
```

## typed/builtin//modules/api/engine/environment/environment/setProbes {#typed-builtin-modules-api-engine-environment-environment-setprobes}

```lua
environment.setProbes(probes: { any }) -> boolean
```

Set the active reflection probes' blend data. `probes` is an array of
`{ x, y, z, radius }` (or `{ position = {x,y,z}, radius = r }`); index i is
probe slot i. Surfaces blend the probe slots by proximity to these
positions, gathering the highest `priority` first — each rank takes the
coverage the ranks above it left, so a small interior probe ranked above a
large exterior one wins outright wherever it reaches full weight. Coverage
left over reflects the sky once `captureSky` has run. Queued for next frame.

**Parameters**

- `probes` `{ any }` — Array of `{ x, y, z, radius, priority? }`, one per active probe
slot. `priority` defaults to 0.

**Returns** `boolean` — True — the probe data was queued.

```lua
environment.setProbes({ { x = 0, y = 2, z = 0, radius = 12 } })
```

## typed/builtin//modules/api/engine/environment/environment/setSkyFallback {#typed-builtin-modules-api-engine-environment-environment-setskyfallback}

```lua
environment.setSkyFallback(active: boolean) -> boolean
```

Arm or disarm the sky fallback against the sky already captured, with no
recapture. Disarmed, reflections come from the probes alone. Arming is
refused while the sky slot holds no capture (`captureSky` fills it), since
an uncaptured slot reflects black; `renderer.reflectionEnvironment()`
reports whether the fallback ended up armed.

**Parameters**

- `active` `boolean` — Whether reflections fall back to the captured sky.

**Returns** `boolean` — True — the change was queued.

```lua
environment.setSkyFallback(false)
```
