# Lights and environments

> Reference for AmbientLight, HemisphereLight, DirectionalLight, PointLight, SpotLight, Environment, defineEnvironment, the built-in studios, SoftBox and StudioOptions, Daylight with its DAY keys, and per-object shadow control.

```ts
import {
  AmbientLight, DAY, Daylight, defineEnvironment, DirectionalLight, Environment, HemisphereLight, PointLight, SpotLight,
} from "@apricot/react";
import type { DaylightKey, StudioOptions } from "@apricot/react";
```

Light components add to the scene's `look`. With `look="none"` they are the only lights. `intensity`, `position` and `target` accept plain or shared values, so lights can move and dim every frame at no cost. Every light takes a `ref` (its three.js light) and renders nothing itself.

## Lights

Common props:

| Prop | Type | Default |
| --- | --- | --- |
| `color` | colour | `"#ffffff"` |
| `intensity` | `number` or shared value | `1` |

| Component | Own props (default) | Light |
| --- | --- | --- |
| `AmbientLight` | | From everywhere, no shading: lifts shadows evenly |
| `HemisphereLight` | `sky` (`"#ffffff"`, replaces `color`), `ground` (`"#8a7a6a"`) | One colour from above, another bounced from below. Soft outdoor light |
| `DirectionalLight` | `position` (`[3, 5, 4]`), `target` (`[0, 0, 0]`), `castShadow` | Sunlight: parallel rays from `position` towards `target` |
| `PointLight` | `position` (`[0, 2, 0]`), `distance` (`0`: no limit, fades with distance) | A bulb: every direction from a point |
| `SpotLight` | `position` (`[0, 4, 2]`), `target` (`[0, 0, 0]`), `angle` half-angle in radians (`0.5`), `penumbra` edge softness 0–1 (`0.3`), `distance` (`0`) | A cone from `position` towards `target` |

In a scene with `shadows`, the brightest directional light casts them. `castShadow` on a `DirectionalLight` makes it the one that casts (`true`) or never casts (`false`).

## `Environment`

Sets what metals and glossy materials reflect, while mounted. Everything is live: switching fades between environments, and `rotation`, `intensity` and the boxes change every frame without rebuilding shaders.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | | `"studio"`, `"soft"`, `"sunset"`, `"night"`, or a name from `defineEnvironment` |
| `sky` | `[ceiling, horizon, floor]` colours | | Or describe one… |
| `boxes` | `SoftBox[]` | | …with soft boxes. Moving them is free |
| `intensity` | `number` or shared value | `1` | Brightness multiplier |
| `rotation` | `number` or shared value (radians) | `0` | Turns the studio around the vertical axis |
| `transition` | seconds | `0.6` | How long a change of `name`, `sky` or `boxes` fades. 0 is instant |

`<Scene environment="…">` sets the starting environment; `<Environment>` changes it later.

```tsx
<Environment name={night ? "night" : "studio"} rotation={swipeAngle} />
```

### `defineEnvironment(name, options: StudioOptions)`

Registers a studio by name.

| `StudioOptions` field | Type | Description |
| --- | --- | --- |
| `sky` | `[ceiling, horizon, floor]` colours | The gradient around the object |
| `boxes` | `SoftBox[]` | Soft boxes: the highlights. Six fit in the built-in slots; more cost a shader rebuild |
| `intensity` | number | Overall brightness (default 1) |

| `SoftBox` field | Type | Description |
| --- | --- | --- |
| `direction` | `[x, y, z]` | From the object towards the box, world space. +z is towards the default camera |
| `size` | `[halfWidth, halfHeight]` | In radians |
| `intensity` | number | Brightness; above 1 for highlights |
| `color` | colour | Default white |

Built-in environments:

| Name | Look |
| --- | --- |
| `studio` | Dark grey studio: key box above and in front, tall strips on both sides, a soft top light, a faint rim behind, a dim fill from the camera side |
| `soft` | Light and even: pale products, white phones, soft paint |
| `sunset` | A low warm sun behind and to the side, an orange horizon, a cool sky |
| `night` | Dark, with coloured neon strips on the sides and a thin light above |

## `Daylight`

Sun, sky light and background for a time of day. Use it with `look="none"`. Everything is a live value, so a day cycle driven by a slider costs nothing per frame. With an environment, reflections dim at night.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `time` | `number` or shared value | required | Hour, 0–24 (13.5 is half past one). Plain values animate; shared values are followed exactly |
| `transition` | seconds | `1.5` | How long a plain change of time takes |
| `background` | boolean | `true` | Sets the background and fog to the sky colour |
| `north` | radians | `0` | Turns the compass: where the sun rises (0: east is +x) |
| `keys` | `DaylightKey[]` | `DAY` | The day's colours. Replace them for another mood |
| `sunrise`, `sunset` | hours | `6`, `19` | When the sun comes up and goes down |

```tsx
<Scene look="none" environment="soft" fog shadows>
  <Daylight time={night ? 21 : 13} />
</Scene>
```

`DAY` has keys at 0, 5.5, 6.5, 9, 13, 17, 18.8 and 20 hours. A `DaylightKey`: `{ hour, sun, sunIntensity, sky, ground, fillIntensity, background, reflections }`, interpolated between keys.

## Shadows per object

With `<Scene shadows>`, meshes cast and receive, flat ones (floors) only receive, and see-through ones do neither. Override per object with `castShadow` and `receiveShadow` props on shapes, `Mesh`, `Model` and `Instances`. For three.js objects of your own, `setShadow(object, { cast, receive })` from `@apricot/core` does the same.

## Related

- [Lighting guide](https://matthiasbrandolin.dev/apricot/guides/lighting).
- [Scene reference](https://matthiasbrandolin.dev/apricot/reference/scene#shadows-shadowoptions).
