Skip to content
Shapemetry

@huukhanhnguyen/types / objects/light

objects/light

CylinderLight

CylinderLight = { length: number; radius: number; shape: "cylinder"; }

A tube: an emitter extruded along its own axis, which is the direction the carrying document states.

length

length: number

radius

radius: number

shape

shape: "cylinder"


DiskLight

DiskLight = { radius: number; shape: "disk"; }

A downlight: a flat round emitter. Being flat, it has a FRONT, so it needs a direction on the document that carries it.

radius

radius: number

shape

shape: "disk"


LightData

LightData = LightShape & { color?: string; coneAngle?: number; direction?: Vector; ies?: string; kelvin?: number; lumens: number; penumbra?: number; position: Point; }

Object-tier light datablock: ONE emitter — where it is, what shape emits, and what it radiates. There is no separate Light beside it, because there is only one shape and the law allows it only one name.

A light has no INTERNAL plurality, so it carries no Data-tier array (being an INDEPENDENT kind is a different question — point is independent yet its entries are a list). N is instances[]'s job — a rig of 12 identical bulbs is one LightData placed 12 times, never 12 entries in a list.

Photometric units, so an author states what a manufacturer prints on the box and a renderer converts to its own.


LightEntity

LightEntity = LightData & { gizmoSize?: number; target?: Point; }

A light's Entity tier: its emitting core (LightData) plus what only a VIEWPORT needs to draw and aim it. A light has no internal plurality, so this is exactly ONE Entity and not an array (unlike PointEntity, which is a point of a cloud); N lights is instances[].

The two fields here are exactly what the functional core cannot say: lumens does not become a gizmo by living on the same document, and a photometric field is not made display data by being read by a renderer.


LightInstance

LightInstance = BaseInstance & { }

A light has no surfaces; material is rejected on this kind.


LightObject

LightObject = BaseObject & { data: LightEntity; instances: LightInstance[]; type: "light"; }

An object whose data is lights and nothing else.

A light is an emitter, not a tessellatable body. Grouping emitters as their own kind gives a lighting consumer a DOMAIN instead of sniffing the stream for lumens. The housing is ordinary solid geometry on a different object.


LightShape

LightShape = PointLight | SphereLight | DiskLight | RectangleLight | CylinderLight

The emitting shape. A tagged union because these are genuinely different geometry — a disk has a radius and a rectangle has two sides — not because a renderer happens to have a class per kind.

There is no spot arm, and its absence is the point: a spot is any shape with a coneAngle set, so narrowing stays ORTHOGONAL to what emits, and a disk-with-a-cone (a real downlight) is expressible. three.js's SpotLight class fuses the two and cannot say it.


PointLight

PointLight = { shape: "point"; }

An emitter with no extent at all: the idealisation, and the right answer for a filament small against the room.

NOT the same subject as Point (geometry/core.ts), which is a bare [x, y, z] tuple — this is a light whose emitting shape is a single spot.

shape

shape: "point"


RectangleLight

RectangleLight = { height: number; shape: "rectangle"; width: number; }

A panel or a window: a flat rectangular emitter, width × height. Flat, so it needs a direction too.

height

height: number

shape

shape: "rectangle"

width

width: number


SphereLight

SphereLight = { radius: number; shape: "sphere"; }

A bulb: an emitter with volume, so its edge shadows are soft in proportion to radius.

radius

radius: number

shape

shape: "sphere"

Last updated: 📖 4 min readEdit on GitHub