voxolith

Atmosphere

The renderer's raw atmospheric effects (fog, clouds, rain and snow, wet and snow-covered surfaces, wind on water, effectScale) and what each one costs.

The renderer draws raw atmospheric effects and knows nothing about weather. Fog, a cloud layer, falling particles, wet or covered ground and wind on the water are independent effects, each off until its amount is above zero, so a scene that sets none of them renders exactly as before.

What the effects mean (rain, a blizzard, a foggy morning) is decided above the renderer:

layerowns
rendererthe effects: optional fields of FrameParams, all off at zero
@voxolith/engine/atmospherethe vocabulary and translator: timeOfDay, Atmosphere presets, blending and transitions, approach, atmosphereFrame
the gamewhether there is weather at all, when it changes, how wetness and snow cover build up

Keep policy out of the engine and meaning out of the renderer.

The fields

The effects are the optional half of FrameParams, typed as AtmosphereParams. They are sent every frame with the camera and lighting; nothing is uploaded.

fog

Exponential extinction towards a colour, optionally thinning with height. It is applied to hits by their distance and to the sky at a fixed far distance, so the horizon dissolves into it. Lamp glows are seen through the fog between the eye and each lamp.

distance turns fog into a view distance ("fog of war"): primary rays stop there, and the fog closes to total over its last quarter, so the cut never shows and nothing past it is traced. The sky is behind the wall too. It is the way to bound a close-up scene at a fine scale, like the nightwood example.

Prop

Type

clouds

A drifting noise layer over the sky gradient. cover 1 is overcast and hides the sun, moon and stars.

Prop

Type

precipitation

Rain streaks or snowflakes as analytic particles: nothing is stored or uploaded, and the field covers a world of any size. The primary ray samples a handful of depth layers, near to far, stopping at whatever it hit, so roofs and trees occlude the particles for free. At each sample, space is sheared along the fall direction (so streaks lean with the wind), stretched for rain, scrolled by fall × time and cut into cells, and a hash puts at most one particle in each cell. World positions stay put as the camera moves, and particles are kept at least a pixel wide at distance.

Prop

Type

The particles move with FrameParams.time, so precipitation needs a continuously rendering loop.

surface

The ground's state rather than the sky's. wet darkens the ground and adds a sheen to upward faces; cover blends upward faces towards coverColor (settled snow). On medium and high quality a short upward ray keeps the cover off ground under canopies and roofs; low skips that ray.

Prop

Type

waterWind

[x, z]: drifts the ripples on water; its length also raises them.

effectScale

How many voxels the effects' own sizes are measured in (default 1): water wavelengths and bed fade, rain and snow particle size and layering, the sky's fog distance and the snow-shelter test. A world at k times the resolution passes k so waves, caustics, drops and snowflakes keep their size in it. Fog density and fall speeds are already per voxel and are scaled by whoever sets them. atmosphereFrame(..., { voxelsPerMetre }) sets all of this for you.

Cost

effectcost per pixel
fog, cloudsa few arithmetic operations
precipitation8 hash samples along the primary ray
surface coverone short upward ray per upward-facing pixel, while cover > 0 (medium and high only)
wet, waterWindshading terms only

From the engine

A game that wants weather keeps an Atmosphere (a preset, a script, a season), changes it by its own rules and hands it to atmosphereFrame with the time-of-day lighting each frame. The result is spread straight into render:

import { atmosphereFrame, ATMOSPHERES, timeOfDay } from "@voxolith/engine/atmosphere";

const weather = { ...ATMOSPHERES.rain, wetness: 0.6 }; // the game owns wetness and cover
renderer.render({
  ...camera(orbit.yaw(), orbit.distance(), orbit.target(), orbit.pitch()),
  ...atmosphereFrame(timeOfDay(0.4), weather, { voxelsPerMetre: 10 }),
  time: now / 1000,
});

See Atmosphere in the engine section for the presets, blending and transitions.

On this page