How was FunkyVector made?

This post was originally written in 2016ish but never published… pressing publish now!

The basic concept was simple. The complexities were intense.

Standardised experiments

On 18 Dec 2014 I decided to publish a bunch of experimental graphics. I have been doing computer graphics in various forms for 25 years, but most usable code is made after circa 2005. There are various reasons to make code open source, in this case it was the attempt to maintain a level of professionalism that public facing code demands. In doing so, a standardised approach was needed, something rarely found in anything experimental. Hopefully I would comment crazy stuff and credit lifted stuff (many snippets have been ported, many one liners are copy+paste).

The first step was to create a structure for the existing generative graphics to adhere to and in doing so common interface for them to expose. An ongoing work in progress, the code is currently haphazard at best, but it used to be a disaster. Some common problems (often found elsewhere) were abstracted into modules like dom (that works in node too), colours (get/set palettes, get/mix colours), geom (line intersections), etc. Basically trying to reduce the reinventing the wheel. Ever had to draw a circle in canvas? I don’t know how many times I have typed something similar to this:

var circleRads = Math.PI * 2;
ctx.drawCircle = function(x, y, r) {
  ctx.arc(x, y, r, 0, circleRads, false);
}

FunkyVector was made as an extension of these experiments so the actual art that FunkyVector uses is still open source; each art piece is simply an experiment that exposes a set of properties. The experiments are loaded by FunkyVector which harnesses their algorithms and displays them in a handy user interface for exposure.

Reproducing on demand

To make a randomly generated graphic reproducible a seeded random implementation was required. Given any random input (originally integer, now optionally alphanumeric) an experiment would produce the exact same results at any resolution. Although a seeded random wasn’t entirely new to me, as is often the case, the real world application of one was!

Out of the box, most experiments flourished with the newly introduced random engine, but very soon into the project some abnormalities surfaced. Computer programs are predictable, and what seemed like strange errors at first would always turn out to be human error: forgetting to reset the random seed or allowing an extra call to the native random() to accidentally slip in, or leaving time based calculations in place. However after fixing these bugs, in some experiments the graphics would sometimes not play fair. After much investigation it turned out to be rounding errors. The winning solution was to adopt a similar approach to WebGL (et al.) fragment shaders in using a domain from zero to one for coordinates: all maths was calculated within the domain of 0 tp 1, and only on the final pass where pixels are actually rendered was values scaled to canvas size.

The first major problem was solved.

Rendering in the browser.

Never an innovator, rarely an early adopter, I like to use things that are at least somewhat established. Not so with canvas, I was on that shit like my mum’s nipple (footnote to having a child) . The vast majority of the experiments were done using canvas’s 2d context. I use canvas all the time, I have loved this concept since flash BitmapData days. This part was easy, and well documented.

Rendering on the server was not so easy.

Thanks to the cool folks it was possible though (respect to nodecanvas contributors). Node canvas is an implementation of canvas that runs in node built on Cairo (follow the rabbit hole). The api is identical to the Dom canvas, and since it runs in node one can make a canvas on a remote server, save it to disk or whatever you like. There is no window, document

The hard part was getting it running on a server, with the fun installation hurdles, and hooking up the application go renser these images oj demand. There still is lots of room for improvement within this code: concurrent rendering? Hah, nice one. Definitely achievable if there was a need for it, but not trivial.

What else?

Things I never wrote about 🙁

Webgl Rendering

Vector Bot

Backwards compatibility

Making it work on fucking phones

stripe + printful

print dimensions

print api

Leave a Reply

Your email address will not be published.