Splatter, splat, splash-ing ♬
It may have been old news already Internet Explorer officially going into retirement, not unlike Flash player reaching EOL possibly, clear sign happily however that web programming was never more fun and full featured. Writing vanilla, framework-less, transpiler-free client-side code is a real option these days: No fluff, no fuss! Finally!
And seeing how generative art is popular again reminds me of the late nineties when there was similar sense of excitement around creative media in general and, coming from a music background, I was trying to decide where to go next with my infant grasp of it and a new millennium on the horizon.
More than interactive graphics or AI, I was interested in conceptual and networking aspects, the promise of nonlinear narratives and self publishing, but I wonder if this all means somehow… it could be… the world is telling me… the time has come to… be pressing jacksonpollock.org onto a GIF?! 🤠
Quirky and fanatically pompous, Neen was amusing as a whole, but this one bit I have always thought special, because it deals with ever relevant impossible debate themes such as originality and appropriation, the where the value lies question, on results or mostly effort, or which proportion of both, and is also a nice play on the "computers can do that?" perception.
I believe the story goes Stamen had initially developed a meatball (sic) based, Convergence inspired drawing app called splatter that was then modified and served up as an art piece with a domain to match, which is luckily still accessible to fiddle with and to study. From what I can tell, the idea is to:
- Sample cursor movement for control points tracing out Bézier curves to mimic brush strokes, thinner at higher rates.
- Run heavenly
RANDOM-ous
thrust 🚀 relative math pulled from Newton's own revised Principia secret notes unearthed in 1913 while dismantling his Leicester fields home where today, let's not forget, you can certainly borrow a telescope from, to determine the size and rotation of hellipses decorating the tips. - Sprinkle extra paint drops here and there,
RANDOM-ly
. - Pick a fresh color at
RANDOM
with each tap or specific keystroke.
Going through the base script, I first want to get rid of Paper.js, which is a fine library, but there really are one-for-one browser-native CanvasRenderingContext2D
equivalent methods to fully cover intended behaviour here. For example, quadraticCurveTo()
or ellipse()
can be used respectively instead of Path.curveTo()
or Path.Ellipse()
etc.
Next, I feel like disguising some of the geometric calculations with an abstraction for readability's sake, adjust for the latest JS language spec and anti-lint rules, because look at those barbaric var
declarations from a bygone era crowding the entrace, DRY up the hyperinflated color switching routine, add touch device listeners, double check the visual output is no different, and that should leave only the GIF encoding part to figure out.
Except, uh-oh, hold on, it's in the details, the formula is tied to the lineCap
being round? Seems tacky. I appreciate the bright looks, but, engine wise, would rather focus on the original. I may have to factor out the very Web 2.0 nearly three quarters of a megabyte combined excess weight of Pixi.js, glMatrix, jQuery, Underscore, and Eric Meyer's reset.css, but at least the model is no fudge.
Simply put, path points are collected while dragging, iterated over to rubber stamp radial-alpha-gradient.png scaled copies for each, like glowing beads, rendered off screen, then texture fed into a couple of shaders, one for rotating through the color palette and one that reads alpha values past a certain threshold to know if the out pixel should be kept transparent.
Other than replacing external dependencies, I took care to: (a) WebGL2 reformat the main shader, (b) Preload SVG sprites for each color to avoid having to rely on a static image and to skip the ColorChangeFilter
shader pass, (c) employ modern JS as appropriate.
Drawing manually can get boring of course. But, Lévy flight type RANDOM
walking, in particular after the Pareto distribution in my eyes, works fairly okay for spreading paint apparently, so why not bring those elements into the mix as well. The trade off is longer jumps are noticeably straight line. However, lowering the max travel cap will counter that effect and gives more concentrated drips, which is sort of cool too.
Since Go's standard library offers built-in image processing tools, dynamically compiling animated GIFs is reasonably straightforward to achieve using WebAssembly even. Not blocking the event loop took some trial and error, but offloading the encoding calls onto a web worker seems to have done the trick.