API reference

Every public class, method, and event in @codexo/exojs. Generated from source.

C

classLighting

@codexo/exojs-lighting / lighting / stable

What a lighting system does with lights, materials and occluders, whichever renderer turns them into pixels. ```ts const lighting = new LightmapLighting(app, { ambient: new Color(11, 16, 32) }); scene.systems.add(lighting); lighting.add(player.addChild(new PointLight({ radius: 260 }))); lighting.occludeFrom(new PhysicsOccluder(world)); ``` Construct one of ForwardLighting, LightmapLighting or RadianceLighting. They are alternatives rather than layers, and a frame is shaded by exactly one of them. This class is what they share: the registries, the collection of occluders, and the update and destroy contracts. It links no renderer of its own, which is what keeps a project using one of them from carrying the others. # What it owns The renderer and its GPU resources. Lights are scene nodes owned by the tree they hang in - registering one does not transfer ownership, and destroying a registered light unregisters it. Occluder sources, filters passed as `post`, and the host are the caller's too. # Ordering Register it with the registry that ticks AFTER the code moving the lights, so the frame it shades is the frame that was drawn. `app.systems` runs its update phase before the active scene's, so a system registered there sees lights the scene has not moved yet; `scene.systems` is usually what you want.

11
props
11
methods
0
events
Import
import { Lighting } from '@codexo/exojs-lighting'

What a lighting system does with lights, materials and occluders, whichever renderer turns them into pixels.

```ts const lighting = new LightmapLighting(app, { ambient: new Color(11, 16, 32) });

scene.systems.add(lighting); lighting.add(player.addChild(new PointLight({ radius: 260 }))); lighting.occludeFrom(new PhysicsOccluder(world)); ```

Construct one of ForwardLighting, LightmapLighting or RadianceLighting. They are alternatives rather than layers, and a frame is shaded by exactly one of them. This class is what they share: the registries, the collection of occluders, and the update and destroy contracts. It links no renderer of its own, which is what keeps a project using one of them from carrying the others.

# What it owns

The renderer and its GPU resources. Lights are scene nodes owned by the tree they hang in - registering one does not transfer ownership, and destroying a registered light unregisters it. Occluder sources, filters passed as `post`, and the host are the caller's too.

# Ordering

Register it with the registry that ticks AFTER the code moving the lights, so the frame it shades is the frame that was drawn. `app.systems` runs its update phase before the active scene's, so a system registered there sees lights the scene has not moved yet; `scene.systems` is usually what you want.

Constructors1
backend is built by the concrete system and belongs to this one from here on; host is the caller's and is never destroyed.
Methods11
add(light: T): T
Register a light and return it, so it can be created, parented and registered in one expression. Registering the same light twice shades it twice; the second registration is ignored instead.
clear(): this
Unregister every light.
clearOccluders(): this
Unregister every occluder source.
clearSurfaces(): this
Unregister every normal surface.
destroy(): void
Release the renderer's resources. Registered lights and sources are unregistered, not destroyed.
Give a drawable surface normals, and return it so it can be created, parented and registered in one expression. ts lighting.normalsFrom(crate, new NormalMap(crateNormals)); Only lightmap reads these. forward shades inside the sprite stage and takes its normals from LitMaterial instead, and radiance gathers each probe's rays into one arriving colour, which leaves no incident direction at a fragment for a normal to be measured against - under both, registering a surface is recorded and ignored, and activeSurfaceCount stays at zero. Nothing is required of a drawable that is not registered: it is lit as a plane, which is what the renderer already assumed of everything. The drawable and the source are the caller's; the system only reads them. Registering the same drawable twice replaces its source rather than describing the surface twice.
occludeFrom(source: T): T
Register something that blocks light, and return it so it can be built and registered in one expression. Only a renderer with shadows reads them - forward has no light field to darken, and skips collecting entirely. ts lighting.occludeFrom(new PhysicsOccluder(world)); The source is asked, once per frame, for the edges in the region the visible lights jointly reach. It is the caller's; the system only reads it. Registering the same source twice collects it twice, so the second registration is ignored instead.
update(): void
System update phase: publish this frame's lights, occluders and surfaces to the renderer.
Properties11
activeLightCount: number
Lights the last frame actually shaded with. Lower than lights when some are disabled, have no intensity, or fall beyond what the renderer in use can carry.
activeSurfaceCount: number
Surfaces the last frame actually took normals from. Lower than surfaces when some are hidden or carry no texture, and zero under every renderer but lightmap. See normalsFrom.
debugExposure: number
Scale applied to the shaded output, 1 by default. It moves the exposure only: the lights, the transport and the bounce history are all untouched, so raising it shows what a light field holds above 1.0 without changing what any of it computed. That is what makes it the right knob for looking at an overbright scene - turning a light down instead would change the scene being looked at. Under forward, where nothing is composited, it does nothing. It is not a tone map: values still clip, one stop further along.
hdr: boolean
Whether light accumulates with headroom above 1.0, so that overlapping lights add up instead of saturating to white and a filter over the frame has something above the clipping point to work with. false under forward, which shades straight into the frame, and under lightmap on a WebGL2 context without EXT_color_buffer_float. The picture is still correct there - it clips earlier, and a bloom keyed on a threshold near 1.0 finds little to bloom.
Registered normal surfaces, in registration order.
Source