star 14, 3
star 7, 2
children 7, scale: 1/8r, offset: 1do|i|
text (0x2641+ i).chr Encoding::UTF_8endendend
translate x: -2do circle; moon 0.45end
translate x: 2do circle; moon 0.55endendend
The fine people of /r/generative / Genuary2021 have a series of challenges for generative works for the month of January. I don’t think I’m going to do all of them, but pick and choose. For example, the very first prompt is:
// TRIPLE NESTED LOOP
My goal was to draw a grid of circles across the X/Y the image and nest them for the third dimension. To make it a little more interesting, I added a few different color modes. seededRandom is my personal favorite, that was interesting to get working.
Much like transpiling register machines, now we have a chance to transpile stack machines. Unfortunately, it doesn’t actually speed up the code nearly so much (the stack is just not as effective of a memory structure in this case), but it’s still an interesting bit of code.
Okay, enough with register machines. Let’s make something new. This time, a stack based machine!
Rather than keeping it’s memory in a series of memory cells, there will be a single stack of values. All functions can pop values from the top of the stack or push them back on. I will add the ability to read the X/Y value and directly write R/G/B, but you can’t write to the former or read from the latter, so you can’t use them as registers. Let’s see what that looks like!
So the main problem we have is that we’re interpreting the code. For every single pixel, for every line of code, we’re doing a few housekeeping things and making at least one function call. For a 400x400 image with just 10 lines of code, that’s 1.6M function calls. Like I said, slow.
Now that I’ve got register machines working, one of the next ideas I had was to implement different wrapping modes. Currently, as it stands, X and Y are passed into the machine as floating point numbers from [0, 1] across the image and output is expected to be [0, 1] for each of R, G, and B. Any values that end up outside of that range, we truncate down to that range. But some of our mathematical functions (multiplication, exponentiation, negation, etc) tend to generate numbers way out of this range. But they don’t have to!
Okay. First Pictogeneis machine: a register based machine. Today we’re going to create a very small language with a small number of registers that can read from the outside world, write colors, and act as temporary variables.
The basic idea is to generate programs (in various styles) that can take x,y coordinates and return colors. Then apply that to every pixel on an image to make generative art. Once we have, figure out a way to mutate/breed the programs so that we can apply a genetic algorithm to them and make awesome images! Sort of like Electric Sheep (that brings back memories).
The evolution point of view was actually a pretty tricky problem, since programs can have a number of different representations. I could compile them to bytecode and mutate that, but how do I make most code at least potentially meaningful?