DustMotes
Dust hanging in a lit room, built as a field rather than a particle system, with most of it out of focus.
Options
-
ground#17171c -
css colour
The air, and what shows where there is no dust. Dark, because everything drawn here is light caught on something: on a pale ground the motes have nothing to be brighter than and the whole thing disappears.
-
mote#fdf6e4 -
css colour
The motes. Warm rather than white, because the light catching them came from somewhere and nothing in a room is lit by a pure white source.
-
pitch34 -
8 to 160 px, good: 22 to 60
Cell size, and so the density: one mote per cell. A fine pitch costs nothing extra per pixel, because a pixel always looks at the same nine cells, so this is the one density control in the library that is free to turn up. Below about 15 the motes start to overlap into a fog.
-
size1.5 -
0.3 to 8 px
Radius of a mote in perfect focus, in pixels. Small: a sharp mote is a speck, and it is the blurred ones that take up room. Raising this makes the sharp ones into dots, which is the look of snow.
-
haze0.72 -
0 to 1, good: 0.5 to 0.9
How much of the field is out of focus. High, because at the scale of a mote the depth of field is almost nothing and nearly everything you see is a smudge. At 0 every mote is sharp, which is the single clearest way to make dust look like a screensaver.
-
light125 -
0 to 360 deg
Where the light comes from. It decides which side of the frame the dust is visible on, which is what gives the air a direction. Pair it with LightShafts set to the same angle and the motes are in the beam.
-
falloff0.65 -
0 to 1
How hard the light falls off across the frame. At 0 the dust is evenly lit everywhere, which reads as a texture rather than as a room with a window in it.
-
drift0.75 -
0 to 2
How far a mote wanders, as a share of the cell. It travels a closed path, so it comes back: dust hangs rather than going anywhere. At 0 it is a still field, which is a legitimate way to use this and very quiet.
-
sparkle0.12 -
0 to 1
Share of motes bright enough to read as sharp specks. A few, and they are most of what makes the air look occupied: it is the thing you notice in a sunbeam. Past about a third it stops being dust and becomes glitter.
-
seed7 -
0 to 9999
Seed for the field. The same seed gives the same air, so a recording and a live page match mote for mote.
-
period44 -
10 to 180 s
Seconds for one cycle of the drift. Long, because dust moves slowly and a backdrop has to survive being ignored.
What it needs
- Category
- Backdrops, an effect
- Dependencies
- None at all
- Browser
- WEBGL2
- Frame budget
- ~0.3 ms · 1 context
- Pinned to
- v0.13.0
- A field, not a particle system. The frame is a lattice, each cell holds one mote whose position is a function of the cell, a seed and the clock, and a pixel looks only at the nine cells around it. Nothing is stored and nothing is advanced
- That is not an optimisation, it is what makes the item possible here. An array of particles advanced each frame cannot be seeked, so it cannot be recorded; it drifts on a dropped frame, because each position depends on the last; and its cost grows with the count. This way the count is a division rather than a loop, so ten thousand motes cost exactly what a hundred do
- Most motes are out of focus, and that is the clearest difference between dust and snow. A real mote is a few micrometres across, so at any focal distance nearly all of them are blurred smudges and only a handful are sharp
- A blurred mote is drawn both wider and fainter, because a lens spreads the same light over more area. Those two together are what make a wide smudge and a tight point read as the same object at different distances rather than as two different things
- The motes catch the light rather than emitting it, so where one sits in the frame decides how bright it is. Without that the field has no direction and reads as static
- They rise as often as they fall. Dust in a lit room is moved by convection rather than by gravity: it hangs. Falling dust is snow
- Each mote is a gaussian rather than a disc, because a mote has no edge whether it is in focus or not
- Built for a dark ground and declared as one. This is light caught on something, and on a pale ground there is nothing for it to be brighter than
- One WebGL2 context, one full-screen triangle, no buffers and no attributes
- Measured at 0.018 mean absolute change per frame on a 0 to 255 scale and 0.37ms at 640 by 360, with a loop seam of exactly zero. The first version drifted 0.7 turns on the vertical and the seam measured 2.59: a time coefficient has to be a whole number of turns over the period or the loop never comes home
- Nine cells per pixel, each one four hashes and an exponential. That is the whole cost and it does not change with the mote count: `pitch` sets the density, and a finer pitch costs nothing extra per pixel because the neighbourhood is still nine cells
- No textures, no buffers and no feedback. There is nothing to allocate and nothing to respawn