3.6 KiB
Add lights to a 3D scene
Add a Light component to a scene entity. The entity's transform places a point or spot light; its rotation aims a spot light along local negative Z. A directional light uses the entity's orientation. Light colors and intensity contribute to the mesh's linear PBR illumination before tone mapping. Sprites and UI retain their unlit tint.
The version-1 faset.light component has three kind values:
| Kind | Position and direction | Useful fields |
|---|---|---|
directional |
Direction from the entity transform | color, intensity, casts_shadow |
point |
Position from the entity transform; illuminates every direction | color, intensity, range |
spot |
Position and local negative-Z direction | color, intensity, range, inner_angle, outer_angle |
Angles are radians. A spot's inner angle must not exceed its outer angle. Intensity
must be nonnegative and range positive. enabled: false keeps the component in the
scene without contributing light. The shadow_priority integer is reserved for the
bounded local-shadow scheduler; it does not change brightness.
In the current rendering checkpoint, one enabled directional light can cast the existing single-map shadow. Point and spot lights illuminate meshes but do not yet cast shadows. The P3 lighting plan tracks cascades and the bounded local-shadow atlas. A scene with no Light component keeps the legacy white sun so older projects retain their appearance. Adding any Light component, even a disabled one, turns off that compatibility fallback. If several directionals are enabled, Faset chooses the one with the smallest stable entity ID and reports a diagnostic for the others.
Author a point light through MCP
Use faset_schema to inspect the current field IDs, then send a faset_scene_edit
batch with the document ID, current revision, and target entity ID. For example:
{
"document": "REPLACE_WITH_DOCUMENT_ID",
"revision": 4,
"idempotency_key": "add-red-point-light",
"operations": [{
"op": "component.add",
"entity": "REPLACE_WITH_ENTITY_ID",
"type": "faset.light",
"fields": {
"kind": "point",
"color": [1, 0.15, 0.1, 1],
"intensity": 8,
"range": 6
}
}]
}
Move the entity with its Transform component. component.add fills any omitted
light fields from the version-1 schema; use component.set for later edits. See
MCP and command line for revision and retry handling.
Supply lights directly from C++
When building a faset::render::Snapshot yourself, set
authored_lights_present to suppress the compatibility sun in a local-only scene.
Provide a stable ID for each light so future shadow scheduling remains independent
of submission order.
faset::render::Snapshot snapshot;
snapshot.authored_lights_present = true;
faset::render::LocalLight point;
point.kind = faset::render::LocalLight::Kind::Point;
point.stable_id = "level/torch";
point.position = {-2, 1.5f, 0};
point.color = {1, 0.3f, 0.1f, 1};
point.intensity = 8;
point.range = 6;
snapshot.local_lights.push_back(point);
faset::render::LocalLight spot;
spot.kind = faset::render::LocalLight::Kind::Spot;
spot.stable_id = "level/lamp";
spot.position = {2, 3, 0};
spot.direction = {0, -1, 0};
spot.inner_angle = 0.25f;
spot.outer_angle = 0.55f;
spot.intensity = 5;
spot.range = 9;
snapshot.local_lights.push_back(spot);
The renderer submits at most 128 local lights per frame in stable-ID order. Later P3 work adds explicit overflow diagnostics and measured light-list optimization.