The pack
sky3d
function sky3d(opts: Sky3dOptions = {}): Pack<{ sky: Sky3dApi }>
The sky-3d pack: a procedural sky drawn per pixel before the meshes, a day/night cycle that drives the
scene's own sun, ambient and fog, and an env map baked from the same palette for anything that reflects.
Requires a 3D world and supports WebGPU and WebGL2.
Helpers
bakeEnv
function bakeEnv(s: SkyState, o: EnvBakeOptions): EnvLevel[]
Bake the sky to an equirect field, mip chain included. u = atan2(x, z) / 2π + 0.5 and
v = 0.5 − asin(y) / π, which is the convention every sampler here uses.
The gradient is the same one the dome shader draws — horizon to zenith on a 0.55 power, the sun-weighted glow band, and the fog floor below the horizon — so a reflection and the sky it reflects agree.
constellationDirs
function constellationDirs(): Array<{ x: number; y: number; z: number; b: number }>
The constellation stars as unit directions with a brightness each. Pure; baked once at module load.
ENV_SIZE
const ENV_SIZE: { width: number; height: number; mips: number; }
How many mip levels bakeEnv returns, and the size of level 0.
resolveSunPath
function resolveSunPath(path: SunPath = {}): Required<SunPath>
A sun path with every field filled in, or a thrown error naming what is out of range.
SKY_KEYS
const SKY_KEYS: readonly SkyKey[]
The default palette: ten hand-tuned keys across an Earth-like day, interpolated linearly in rgb, which is good enough at these saturations.
The palette CLOCK must agree with the sun GEOMETRY (with SUN_PATH the sun's elevation is 0 at exactly
6:00 and 18:00): the golden hour sits just BEFORE 18:00 and dusk just after. A "sunset" palette while the sun
is already 20° under the horizon lights the world from below and the land goes black, so a palette written
for another sun path moves its keys with it.
skyState
function skyState(hour: number, opts: SkyStateOptions = {}): SkyState
The day/night core: an hour 0..24 in (it wraps), the full palette and the sun's geometry out.
With the defaults the sun rises toward +x at 6:00 and sets toward −x at 18:00, standing about 78° high at
noon with a lean toward −z so noon shadows are never degenerate, and it keeps sweeping below the horizon at night with the
moon on the antipode. opts.palette and opts.sun replace the keyframes and the path; the palette is not
validated here (it runs every step), so check an authored one once with validatePalette.
SUN_PATH
const SUN_PATH: Readonly<Required<SunPath>>
The default sun path: up at 6:00, down at 18:00, a 65° arc with a 0.45 lean (the noon sun at about 78°).
validatePalette
function validatePalette(palette: readonly SkyKey[]): void
Throw unless a palette can be interpolated: at least one key, hours in 0..24 in strictly ascending order, finite numbers and css colours. The message names the key and the field.
Types
Env3dBag
interface Env3dBag
What sky-3d publishes each frame under ctx.backend['env3d']: the sky, baked, for anything reflective.
view: GPUTextureView— The equirect env map, mipped.u = atan2(x, z) / 2π + 0.5,v = 0.5 − asin(y) / π.sampler: GPUSampler— A linear, mipped, u-repeating sampler for it.strength: number— How much of it a reflection should take, 0..1 — it falls with the storm dial.mips: number— How many mip levels it carries, so a rough reflection can pick one.
EnvBakeOptions
interface EnvBakeOptions
What the bake needs beyond the day's palette.
coverage: number— Cloud sky-fraction 0..1 — a covered sky reflects flatter and brighter.density: number— Cloud opacity 0..1.storm: number— Storm dial 0..1 — darkens everything.clouds: boolean— Are the clouds drawn at all.
EnvLevel
interface EnvLevel
One baked level of the env map.
w: number— Texel width.h: number— Texel height.data: Uint8Array— rgba8, row major.
Rgb
type Rgb = [number, number, number]
A colour as linear-ish rgb, 0..1.
Sky3dApi
interface Sky3dApi
game.sky. Every field is live.
enabled: boolean— Draw the sky and its environment map. Lighting control remains independently governed by driveLighting.time: number— Time of day, 0..1: 0 midnight, 0.25 sunrise, 0.5 noon, 0.75 sunset. Wraps.hour: number— The same clock in hours, 0..24. Setting either moves the other.daySeconds: number— Seconds a full day takes; 0 stops the clock. Default 0.northOffset: number— Which way the sun rises from, degrees. Default 90.brightness: number— Overall brightness. Default 1.haze: number— How hazy the horizon is, 0..1. Default 0.35.stars: number— Star and moon brightness at night, 0..1; 0 is an empty sky. Default 1.clouds: number— Cloud cover, 0..1; 0 is clear and skips the cloud work entirely. Default 0.45.cloudDensity: number— Cloud opacity, 0..1. Default 0.65.cloudSpeed: number— How fast the clouds drift, on their own clock. Default 1.wind: { x: number; z: number }— Which way they drift. Default a gentle westerly.storm: number— The storm dial, 0..1: more cloud, darker cloud, dimmer sun. Default 0.driveLighting: boolean— Driverender3d.lighting— sun, ambient and fog — from the sky. Default true.palette: readonly SkyKey[]— The day's keyframes,SKY_KEYSby default. Assign a new array to restyle the whole day (an alien sky, a stylised one); it is validated and copied, and reading returns the live copy. Throws on a palettevalidatePaletterefuses.sunPath: SunPath— The sun's path: rise and set hours, peak and depth elevations, lean. Assign to change it; reading gives every field. Throws on a path out of range.cloudScale: number— Cloud pattern scale: higher is smaller, busier clouds. Default 0.85.cycle(seconds: number): void— Set the clock running: one full day everyseconds. 0 stops it.readonly state: SkyState— The whole palette and sun geometry for right now.readonly sunDirection: { x: number; y: number; z: number }— The direction the light TRAVELS, normalised: from the sun toward the ground by day (soyis negative), and the moon's light, down from the antipode, at deep night. It is whatrender3d.lighting.sunis set to.skymax'ssunDirection()points the other way, toward the sun: usesunPositionfor that.readonly sunPosition: { x: number; y: number; z: number }— The unit vector TOWARD the sun, compass turn included: what a lens flare or a sun-facing sprite wants. Below the horizon at night.readonly sunHeight: number— How high the sun is, theyofsunPosition: −1 straight down to 1 straight up (about 0.98 at the default noon).
Sky3dOptions
interface Sky3dOptions
Manifest options — the same fields as the API, all optional.
time?: number— Starting time of day, 0..1. Default 0.3.hour?: number— Starting time in hours, 0..24. Overridestime.daySeconds?: number— Seconds a full day takes; 0 holds it still. Default 0.northOffset?: number— Which way the sun rises from, degrees. Default 90.brightness?: number— Overall brightness. Default 1.haze?: number— Horizon haze, 0..1. Default 0.35.stars?: number— Star brightness, 0..1. Default 1.clouds?: number— Cloud cover, 0..1. Default 0.45.cloudDensity?: number— Cloud opacity, 0..1. Default 0.65.cloudSpeed?: number— Cloud drift speed. Default 1.wind?: { x: number; z: number }— Cloud drift direction. Default{ x: 1, z: 0.35 }.storm?: number— Storm dial, 0..1. Default 0.driveLighting?: boolean— Drive the scene lighting from the sky. Default true.palette?: SkyKey[]— The day's keyframes, by hour. DefaultSKY_KEYS, an Earth-like day.sunPath?: SunPath— The sun's path. DefaultSUN_PATH: up at 6:00, down at 18:00, 65° at noon.cloudScale?: number— Cloud pattern scale: higher is smaller, busier clouds. Default 0.85.
SkyKey
interface SkyKey
One keyframe of the day's palette, at an hour. skyState interpolates linearly between the two keys
either side of the hour, wrapping from the last key round to the first. Colours are css strings.
t: number— The hour this key sits at, 0 (inclusive) to 24 (exclusive). Keys run in ascending order.zenith: string— The sky colour straight up.horizon: string— The sky colour at the horizon.glow: string— The glow band around the sun near the horizon.sun: string— The colour of the direct light.sunI: number— Direct light strength, about 1 at noon and near 0 at night.ambient: number— Ambient strength.ambSky: string— Ambient arriving from above.ambGround: string— Ambient bouncing from below.fog: string— The fog colour.stars: number— Star opacity, 0 by day to 1 at night.moon: number— Moon opacity, 0..1.
SkyState
interface SkyState
The whole sky for one moment of the day. Returned by skyState.
sunPos: Rgb— Unit vector pointing TOWARD the sun. Below the horizon at night.sunDir: Rgb— The direction the light TRAVELS — what a renderer'ssunwants:−sunPosby day, and the moon's light (down from the antipode) at deep night.sunColor: Rgb— The colour of the direct sunlight.sunI: number— Direct sun strength: about 1 at noon, near 0 at night.zenith: Rgb— The sky colour straight up.horizon: Rgb— The sky colour at the horizon.glow: Rgb— The glow around the sun near the horizon.ambient: number— Ambient strength.ambSky: Rgb— Ambient arriving from above.ambGround: Rgb— Ambient bouncing from below.fog: Rgb— The fog colour for this hour.stars: number— Star opacity — 0 by day.moon: number— Moon opacity.
SkyStateOptions
interface SkyStateOptions
What skyState reads beyond the hour: the palette and the sun's path.
palette?: readonly SkyKey[]— The day's keyframes. DefaultSKY_KEYS.sun?: SunPath— The sun's path. DefaultSUN_PATH; unset fields take its values.
SunPath
interface SunPath
The sun's daily path. The sun rises at rise, climbs to its highest halfway to set, sets at set, and
keeps sweeping below the horizon through the night to its lowest halfway to the next rise, with the moon on
the antipode. Before the compass turn (northOffset) it rises toward +x and sets toward −x, leaning toward −z.
peak and lean shape the arc together: the sun climbs as if to peak, and the lean tips the path toward
−z, which raises the mid-day sun to atan(tan(peak) / lean) (about 78° with the defaults, 65° and 0.45).
A small peak with a large lean is a low winter sun; lean 0 passes straight overhead.
rise?: number— The hour the sun rises, 0 (inclusive) to 24 (exclusive). Default 6.set?: number— The hour it sets: afterrise, and less than a day after it (it may pass midnight). Default 18.peak?: number— How high the arc climbs by day, radians, before the lean tips it; above 0, at most π/2. Default 65° (about 1.134).depth?: number— How far it sinks at night, radians, before the lean; 0 to π/2. Default the same aspeak.lean?: number— How far the arc leans off the east-west line toward −z, as a horizontal ratio: 0 passes straight overhead (atpeakπ/2), 0.45 is a temperate lean that keeps noon shadows from degenerating. Default 0.45.


