@ferret/clouds
Classes
CloudField class
class CloudFieldcover: number | |
readonly layers: LayerKind[] | |
constructor(o: CloudFieldOptions = {}) | |
setCover(c: number) | |
setWind(w: WindFn) | |
drift(kind: LayerKind, t: number): [number, number] | how far a layer's frame has drifted by time t (summed over whole seconds, cached) |
puffsOf(kind: LayerKind, ix: number, iz: number): Puff[] | the puffs of one cell of a layer: a deterministic function of the cell's integer coordinates, in the layer's own (drifting) frame |
puffsNear(kind: LayerKind, x: number, z: number, t: number, radius: number): Puff[] | the puffs of a layer within radius (metres) of a world point; positions are in the layer's frame (add drift for the world) |
density(p: V3, t: number): number | How thick the cloud is at a world point, 0 (clear) .. 1 (inside the heart of one). Each puff is a soft ellipsoid; the game thickens its fog and greys the view with this when a ship flies in, and a wet cloud can add film weight. |
shadowAt(x: number, z: number, y: number, sun: V3, t: number): number | How much of the sun the clouds take from a ground point, 0 (full sun) .. 1 (full shadow): the ray to the sun is crossed with each layer. sun is the unit direction to the sun (y up). With the sun at or below the horizon everything is shadow. |
shadowGrid(cx: number, cz: number, y: number, sun: V3, t: number, size: number, n: number): Float32Array | shadow values around a centre, row-major n*n floats 0..1 over a square of side size m: what a ground shadow texture is made of |
packages/clouds/src/field.ts:57
CloudView class
class CloudViewreadonly frame: BABYLON.TransformNode | |
constructor(private scene: BABYLON.Scene, readonly field: CloudField, o: CloudViewOptions = {}) | |
setSun(d: V3) | the direction to the sun (unit, y up) |
setTint(r: number, g: number, b: number) | a warm or grey cast over all clouds (sunset, a storm) |
setTier(t: CloudTier) | |
update(cam: V3, t: number) | call each frame with the camera position (world) and the time (s) |
dispose() |
packages/clouds/src/view.ts:53
Functions
flowWind function
function flowWind(field: FlowField, at: [number, number] = [0, 0]): WindFnThe wind of a @ferret/flow field at the height of the layer, at the position at (x, z): a front brings its clouds with it.
packages/clouds/src/wind.ts:5
hash3 function
function hash3(a: number, b: number, c: number): numbera hash of three integers to 0..1
packages/clouds/src/field.ts:42
puffShade function
function puffShade(up: number, toSun: V3, from: [number, number] = [0, 0]): numberThe brightness of a puff for a sun direction (unit, y up): the tops are lighter, the flat base is darker, and the side towards the sun glows. from is the unit horizontal direction from the cloud's centre to the puff; 0..1.
packages/clouds/src/field.ts:169
puffTexture function
function puffTexture(scene: BABYLON.Scene): BABYLON.DynamicTexturepackages/clouds/src/view.ts:16
Interfaces
CloudFieldOptions interface
interface CloudFieldOptionscover?: number | 0 clear .. 1 overcast |
layers?: LayerKind[] | which layers exist (default all); a cheap tier leaves cirrus out |
wind?: WindFn | |
seed?: number |
packages/clouds/src/field.ts:48
CloudViewOptions interface
interface CloudViewOptionspackages/clouds/src/view.ts:51
Puff interface
interface Puffp: V3 | |
r: number | radius, m |
up: number | 0..1 height in its cloud (the top is lighter) |
flat: number | vertical squash of the volume: 1 round, small for a veil |
alpha: number | opacity multiplier |
packages/clouds/src/field.ts:16
Types
CloudTier type
type CloudTier = 'high' | 'medium' | 'low'The picture of a CloudField (Babylon is the engine's global BABYLON). One mesh per layer, one draw call each: every puff is a quad billboarded in the vertex shader, lit by the sun (setSun), fading out close to the camera and into the haze far away. The cells within the tier's radius are made again when the camera crosses a cell, the cover changes or the sun has moved enough to change the shading. No texture file: the puff is drawn into a texture here.
packages/clouds/src/view.ts:9
LayerKind type
type LayerKind = 'cumulus' | 'cirrus' | 'stratus'packages/clouds/src/field.ts:14
V3 type
type V3 = [number, number, number]The cloud field: clouds as a pure function of position, time and the cover, like terrain, so every peer and every start sees the same sky. No Babylon here: the picture is view.ts, and the same numbers answer the questions of the game (how thick is the cloud at the ship, is this ground point in a cloud's shadow).
Three layers by weather: fair-weather cumulus (clusters of puffs with a flat base and a lighter top), a high thin cirrus veil, a low stratus deck that comes with overcast. Each layer lives in a frame that drifts with the wind at the layer's height (the wind is a function; flowWind in wind.ts gives one from a @ferret/flow field, so a front brings its clouds). The drift is the wind summed over whole seconds, so two peers asking for the same time get the same offset whatever their frame rates.
packages/clouds/src/field.ts:11
WindFn type
type WindFn = (height: number, t: number) => [number, number]the horizontal wind (m/s) at a height and time
packages/clouds/src/field.ts:13
Constants
LAYERS const
const LAYERS: Record<LayerKind, LayerSpec>packages/clouds/src/field.ts:35
TIERS const
const TIERS: Record<CloudTier, { radius: number; maxPuffs: number; layers: LayerKind[]; }>packages/clouds/src/view.ts:10