I built OohAlive, a page where you draw an arrow on a photo and the picture flows that way. Then you download the loop as a GIF. Three things went wrong along the way and they were more interesting than the shader, so this post is about those.
The shader
Each arrow adds a Gaussian pull to every pixel, based on the distance to the arrow segment. Two copies of the photo slide along that flow half a loop apart and cross fade, so the other copy covers the moment one resets. A freeze brush paints a mask, and where the mask is set the flow is zero. The preview and the export call the same draw function.
Bug one: the loop was twice as long as it needed to be
The two copies swap places after half a cycle, so the picture repeats every half cycle. My first GIF had 40 frames, and frame 20 was identical to frame 0. I was encoding the same second twice. Scaling the phase so 0 to 1 is exactly one repeat halved the frame count.
Bug two: frozen pixels shimmered
I measured a window on the frozen boat across the decoded GIF and found 1,070 changed values out of about 4,600. The raw frames from the shader were identical there, so the encoder was at fault. The palette lookup in gifenc caches by 5-6-5 colour for each call and keeps the match of the first pixel it meets, so the same colour could land on different palette entries in different frames. One lookup table for the whole GIF fixed it, and the same window now shows 0 changed values. With the first fix, the exported file went from 2.1 MB to 887 KiB.
Bug three: a failing test ate 23 GB of memory
A test compared two screenshots with assert.deepEqual. When they differed, Node tried to print both PNG buffers as a diff and the process kept growing until I killed it. Comparing with Buffer.compare and counting draw calls instead of pixels for the pause test fixed it.
What I would like to know
I've only tested Chromium. Firefox, Safari and real phones are untested. It works best on water, clouds and smoke. If a photo looks wrong, I'd like to see it.
Live page: https://arthur031221.github.io/OohAlive/
Source, MIT licensed: https://github.com/Arthur031221/OohAlive

