Lighting
Back to the reference

Lighting

Directional, point, spot and ambient lights, and the two kinds of shadow the era affords.

14 symbols

MAX_LIGHTSvariablenacatamalon

MAX_LIGHTS: 8

How many lights shine on one frame.

Eight is not a number picked out of the air: it is what the hardware of this engine's era offered. The GameCube's GX had eight, each of them free to be a sun, a lamp or a torch; the N64 did seven and an ambient; the fixed pipeline the Dreamcast era was written against also stopped at eight. Past the eighth they are dropped in the order the scene made them, once, with a warning. Ambient lights do not count against it.

View source · light/types/t_light.ts:145

useAmbientLightfunctionhooknacatamalon

useAmbientLight(options: { color, intensity }) => TAmbientLight

The level everything is lit to before any lamp reaches it.

It has no place and no direction, so it shades nothing: it only decides how dark the dark side is. A scene with one of these and nothing else is lit flat, which is a look and not a mistake.

The light belongs to this object, so putting it inside something that moves means it moves with it: a lamp carried by a character, headlights on a car. One light per object; asking for a second one here replaces it, and says so.

A scene can hold as many as it has objects with one, up to eight at a time. Past that they are dropped in the order they were made, with a warning.

Parameters

options{ color, intensity }

Its colour, how strong it is, and where it points.

Example

const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    useAmbientLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
View source · hooks/light/use_ambient_light.ts:36

useBlobShadowfunctionhooknacatamalon

useBlobShadow(options: TBlobShadowOptions) => TMesh

Puts a soft dark disc on the ground under something and keeps it there.

This is the cheap shadow, the one the consoles this engine is aimed at actually used: not a shadow of the shape, a smudge under it. A game can afford fifty on hardware that could not afford one real one, because it is not a feature of the renderer at all. It is a disc wearing a shader that fades from the middle, drawn down the ordinary path with everything else: no extra pass, no texture, nothing reserved.

It takes nothing from the lamps in the scene, on purpose. A shadow that took the light would brighten as a lamp moved towards it, which is the opposite of what a shadow does.

It does not cast a real shadow of its own either, which matters the moment a scene has a light that casts one: a flat disc lying on the floor would otherwise be drawn into the shadow map and come back as a shadow of a shadow, a dark ring that nothing in the scene explains.

Call it in the scene body, next to the thing it goes under, and then forget it: it follows on its own. It reads that thing's own placement, so the two belong together (either both loose in the scene, or both inside the same group), which is what writing them next to each other already gives you.

Parameters

optionsTBlobShadowOptions

What it goes under, and how it looks.

Example

const Level = () => {
    useCamera3d({ projection: 'perspective', y: 3, z: 6, rotationX: -0.5 });
    createMesh({ geometry: usePlaneGeometry({ width: 12, depth: 12 }) });

    const hero = createMesh({ geometry: useCubeGeometry(), transform: { y: 0.5 } });
    useBlobShadow({ target: hero, radius: 0.75, followHeight: true });

    return createScene();
};
View source · hooks/light/use_blob_shadow.ts:119

useLightfunctionhooknacatamalon

useLight(options: TLightOptionsBase & { shadowArea, shadowDistance }) => TDirectionalLight

A light from far away, like the sun.

It has a direction and no place: everything is lit by it the same, however far away it is. This is the one a scene should start with, because it is the one that shows the shape of things.

It shines along its own facing, so it is aimed by turning it, the way a camera is.

The light belongs to this object, so putting it inside something that moves means it moves with it: a lamp carried by a character, headlights on a car. One light per object; asking for a second one here replaces it, and says so.

A scene can hold as many as it has objects with one, up to eight at a time. Past that they are dropped in the order they were made, with a warning.

Parameters

optionsTLightOptionsBase & { shadowArea, shadowDistance }

Its colour, how strong it is, and where it points.

Example

const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    useLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
View source · hooks/light/use_light.ts:38

usePointLightfunctionhooknacatamalon

usePointLight(options: TLightOptionsBase & { range }) => TPointLight

A lamp: it has a place, shines every way, and fades out with distance.

range is how far it reaches; past that it lights nothing. A torch on a wall, a fire, a bulb.

The light belongs to this object, so putting it inside something that moves means it moves with it: a lamp carried by a character, headlights on a car. One light per object; asking for a second one here replaces it, and says so.

A scene can hold as many as it has objects with one, up to eight at a time. Past that they are dropped in the order they were made, with a warning.

Parameters

optionsTLightOptionsBase & { range }

Its colour, how strong it is, and where it points.

Example

const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    usePointLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
View source · hooks/light/use_point_light.ts:36

useSpotLightfunctionhooknacatamalon

useSpotLight(options: TLightOptionsBase & { range, angle, penumbra }) => TSpotLight

A torch: a lamp that only shines inside a cone.

angle is half the width of the cone and penumbra is how soft its edge is, from a hard rim at 0 to a beam that fades all the way in at 1. Like a sun it is aimed by turning it.

The light belongs to this object, so putting it inside something that moves means it moves with it: a lamp carried by a character, headlights on a car. One light per object; asking for a second one here replaces it, and says so.

A scene can hold as many as it has objects with one, up to eight at a time. Past that they are dropped in the order they were made, with a warning.

Parameters

optionsTLightOptionsBase & { range, angle, penumbra }

Its colour, how strong it is, and where it points.

Example

const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    useSpotLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
View source · hooks/light/use_spot_light.ts:36

TAmbientLighttypenacatamalon

Light with no source: the level everything is lit to before any lamp reaches it.

It has no place and no direction, so it never shades anything: it only decides how dark the dark side is. A scene with one of these and nothing else is flat, which is a look and not a mistake.

Properties

type'ambient'
idstring
colorTColor
intensitynumber
View source · light/types/t_light.ts:111

TBlobShadowOptionstypenacatamalon

What useBlobShadow can be asked for. Only the thing it goes under is needed.

Properties

targetTMesh

What it goes under. Every frame it moves to wherever that is.

groundYoptionalnumber

The height of the ground it lies on. Default 0.

radiusoptionalnumber

How wide it is, in the same units as everything else in the scene. Default 0.5.

coloroptionalTColor

What colour it is. Default black: a shadow is darkness, faded by opacity and not tinted.

opacityoptionalnumber

How dark it is in the middle, 0 to 1. Default 0.5.

softnessoptionalnumber

How soft the rim is, from a cut edge at 0 to a fade that starts at the centre at 1. Default 0.4.

followHeightoptionalboolean

Whether it grows and fades as the thing above it rises. Default false, which is a shadow of a fixed size.

It is the oldest way of telling a player that a character has left the ground, and it works because the two readings of a sprite going up (jumping, or walking away from the camera) are told apart by what happens underneath.

zIndexoptionalnumber

Draw order within the scene. Default 0.

View source · hooks/light/use_blob_shadow.ts:38

TDirectionalLighttypenacatamalon

TDirectionalLight: TLightBase & { type, shadowArea, shadowDistance }

A light from far away, like the sun: it has a direction and no position, and it reaches everything with the same strength.

View source · light/types/t_light.ts:55

TLightBasetypenacatamalon

What every light has: a colour, how strong it is, and how much of it reaches the parts it does not shine on directly.

ambient is that last one: light bounces off everything in a real room, so a surface facing away from the lamp is dim and not black. Without it a scene looks like it is in space.

Properties

idstring
colorTColor
intensitynumber
ambientnumber
transformTTransform3d

Where it is and which way it faces. Lights shine along their own -Z.

castShadowoptionalboolean

Whether this is the light that casts shadows. Default false.

One light casts, and it is the first one that asks. That is not a budget picked at random: a shadow map is a whole extra pass over everything that casts, and the hardware this engine is aimed at had one of them. A second light asking is warned about rather than ignored, because being quietly overruled is the sort of thing you lose an afternoon to.

shadowBiasoptionalnumber

How far the shadow test is pushed away from the surface, so a surface does not shadow itself. Default 0.002.

Too little and a lit surface stripes itself. Too much and the shadow detaches from whatever cast it, which reads as the thing hovering.

shadowStrengthoptionalnumber

How dark it goes, 0 to 1. Default 1. Lower leaves the caster's light partly on.

View source · light/types/t_light.ts:15

TLightOptionsBasetypenacatamalon

Options every light with a place in the world shares.

Properties

coloroptionalTColor
intensityoptionalnumber

How strong it is. Default 1.

ambientoptionalnumber

How much of it reaches what it does not shine on. Default 0.35.

xoptionalnumber

Where it is.

yoptionalnumber
zoptionalnumber
rotationXoptionalnumber

Which way it faces, in radians. A light shines along its own -Z.

rotationYoptionalnumber
castShadowoptionalboolean

Whether this is the one light that casts shadows. Default false. See TLight.

shadowBiasoptionalnumber

How far the shadow test is pushed off the surface. Default 0.002.

shadowStrengthoptionalnumber

How dark it goes, 0 to 1. Default 1.

View source · light/create_light.ts:13

TSpotLighttypenacatamalon

TSpotLight: TLightBase & { type, range, angle, penumbra }

A torch: a lamp that only shines inside a cone.

angle is half the width of that cone and penumbra is how soft its edge is, from a hard rim at 0 to a beam that fades all the way to the middle at 1.

View source · light/types/t_light.ts:99