The hat never moved,
and it made a seventh of the flicker
We animated our own logo. The first version shimmered along every static edge, and nothing in the artwork was responsible.
AgentSee
We animated our own logo. The first version shimmered along every static edge, and nothing in the artwork was responsible.
01 — The mark is eight numbers
Eight numbers describe an expression: how far each of the two lids has travelled, how the lid curve skews, how far the fedora has rotated, the iris offset on each axis, how contracted the pupil is, and how wet the catchlight looks. Twenty-two named poses use them. The fedora is the only brow this face has, so hat angle does the work eyebrows would.
A sequence of poses is a chain, and each chain carries its own timing rather than inheriting a global one. That pairing is the decision we would defend hardest, because pace is part of an emotion and not a setting. A double take that eases out the way a sign-off does stops being a double take.
Drawing the frames by hand was never an option. Art made that way drifts the first time a colour changes in the stylesheet, and nobody diffs a PNG.
Who made it is worth stating, because the music issue beside this one answers the same question the other way round. The idea was James Hartt's, one of the two of us: an eye wearing a fedora, and the domain agentsee.work to go with it.
Almost everything after the idea was constructed by agents. The paths, the eight axes, the renderer, the twenty-two poses and the eighteen chains were written to direction rather than drawn or typed by a person. That is the reverse of the theme, where every note was placed by hand and the tooling only did the cutting. The two sit beside each other deliberately.
02 — The renderer was not deterministic
A few hundred frames make a clip. Laying them all out as a grid and taking one screenshot is far faster than launching a browser per frame, so that is how the first version worked.
Then the same SVG, placed in two cells of one screenshot, came out different. Not subtly: 948 pixels of a 360 by 360 frame differed at full contrast.
The grid was the cause, not the drawing. Render that same content in two separate browser launches and it is byte for byte identical. We tried rearranging the cells, then a single column. It still diverged.
What you see is every unmoving edge crawling. The fedora is the tell. It holds completely still in those clips, and it produced 14 per cent of the flicker in the finished one.
We spent an evening hunting through the animation. It took that long to think of checking whether a still frame was still.
One launch per frame fixed it. It also cost roughly four times the render time. Most of that came back by rendering each distinct pose once and repeating it through holds — three quarters of a full run had been redrawing pictures it already had.
We looked for the cause in the moving parts. It was in the one thing that never moved.
03 — The glow covered two fifths of the frame
Video for an episode needs a transparent background, so the mark renders with alpha. The soft glow behind it, which reads as warmth over a dark page, spread across 39 per cent of a transparent frame and reached 48 pixels past the artwork.
It stayed invisible for as long as we developed against dark backgrounds, which is exactly how it reached a finished export. What we took from it was not about glows. A setting that is undetectable in your working conditions will survive every review you perform in them.
04 — A wrong measurement is worse than none
To check the iris moved the way the data said, we tracked the centre of its amber mass between frames. Then the eye blinked.
The lid clips the iris. So the centre of whatever is left follows the lid, and the tool reports tens of pixels of travel that never happened. It gave us a confident wrong answer twice. Both times a filmstrip settled it in one look.
Checksums are no use either. PNG bytes are not stable across renders. So a checksum reports eight images changed when seven of them are pixel for pixel identical, and only comparing pixels answers the question actually being asked.
The third is worse, because there is nothing to fix. Motion blur averages across sub-frames, and that damps a fast tremor well below the figure in the configuration. So the number we set is not the swing a viewer sees — and the swing a viewer sees cannot be recovered from the frames.
That one has no instrument. It gets judged by eye.
Alpha coverage looked like a measure of edge quality. It is not. The ramp around the outer silhouette can be flawless while every internal edge is a hard one-pixel step, and the internal edges are the ones that look wrong.
05 — The reason this is published
None of the faults above were found by reasoning about the code. They were found by rendering something, looking at it, disbelieving a number and measuring again. The work was fast and mostly automatic. Deciding which of four plausible explanations was true stayed manual throughout, and it was the entire job.
The tooling is in the repository, along with a longer version of this written for whoever maintains it. If you are animating an SVG through a browser, read the part about determinism first, because you will not think to check it.