A quiet scene is alive because nothing agrees
A still scene reads as a photograph, so everyone adds idle motion, and the first version is a sine wave. It moves and it still looks dead, which is confusing until you notice that all of it is moving together.
The left half pumps. Every lamp reaches the end of its swing at the same instant and every bulb brightens on the same beat, so five lamps read as one object with five parts. The right half has exactly the same amount of motion in it and reads as five lamps in a room.
The eye is looking at relationships, not at motion
Two things moving at the same rate have a phase difference that never changes, and a constant relationship is the signature of a rigid connection. That is the whole illusion being destroyed: a shared period tells the viewer these objects are attached, whatever they look like.
Give them rates with no neat ratios between them, and phases that do not line up, and the phase relationship never re-forms. There is no cycle to find, so the eye stops predicting and reads independence, which is what "alive" means here.
The obvious shortcut is a trap, and this demo shipped with it: a base plus an index
times some odd increment, 0.62 + i*0.1373, with a phase of i
times the golden angle. The rates are evenly spaced, so every neighboring pair drifts
apart at the same speed, and once the phases are linear in i too the whole
row comes back into line together. Here that happened 28 seconds in and every 46
seconds after, when all five lamps held the same angle at once. Spread the rates
unevenly instead, 0.62 + 0.40*fract(i*0.618034), and give each element a
hashed phase. Over an hour the five lamps come within a hundredth of a radian of each
other for a fraction of a second at most, and usually not at all.
The layers worth having
Amount of motion is not the variable. Number of independent periods is. A scene reads as alive with a startlingly small amplitude if there are enough uncorrelated things:
- Sway, slow, on anything hanging or growing. Seconds per cycle, not tenths.
- Brightness breathing on every light source, on a different period from the sway of the thing carrying it. The lamp and its glow should not agree with each other either.
- Drift, on dust, embers, insects. Tiny amplitude, long period, and the single cheapest layer to add.
- Rare events. Something that happens once every twenty seconds is worth more than anything continuous, because it cannot be predicted at all.
- Parallax, if there is any camera movement whatsoever. Depth reads as life even when nothing in the scene is moving.
Where the shared period sneaks back in
Even having decided all this, it returns, because it is what the convenient code does:
- One global time uniform used raw.
sin(iTime)everywhere is a shared rate by default, and it takes a deliberate act to avoid. - Instancing. Fifty of the same object with the same shader and no per-instance seed is the worst case of this, and it is the one that looks most obviously wrong.
- A shared noise texture sampled at the same rate, which is a shared period wearing a disguise.
- Harmonics. Rates of 1.0 and 2.0 look almost as bad as 1.0 and 1.0, because they realign every cycle. Avoid neat ratios, not just equality.
- Evenly spaced rates. A base plus index times an increment is one rate difference shared by every neighboring pair, and with index-linear phases the whole row realigns every
2pi/incrementseconds.
How to check it
Watch the scene for thirty seconds and try to predict it. If you can anticipate the moment two things will line up, so can the viewer, and that moment is when the scene stops being a place and becomes an animation. The failure is easiest to catch at the edge of vision, so look slightly away from the screen and notice whether anything pulses.
Rules of thumb
- Idle motion reads as life through uncorrelated periods, not through amplitude.
- Give every element its own rate, spread unevenly (golden-ratio fractions, not an even step), and a hashed phase.
- Avoid neat ratios, not just equal rates. 1.0 and 2.0 realign every cycle.
- Give a light's brightness a different period from the motion of the thing carrying it.
- More independent layers beats more movement. Dust is nearly free and does a lot.
- A raw global time uniform is a shared period by default, so avoiding it has to be deliberate.
If you find anything wrong, let me know at hello@andrewdetwiler.com and I'll get it updated.
One email when something new goes up. No newsletter, no schedule, nothing else.
Double opt-in, so watch for a confirmation email. Unsubscribe any time.