Title
Year
Type
2024
code
Genuary 2024. Daily code-art prompts for the month of January. Made with Gum.
I did this year's Genuary as a way to dogfood Gum, the 3D creative-coding library I've been working on. Trying to make something interesting with the engine everyday was a great way to uncover rough edges, weird bugs, and frustrating patterns in this early version of Gum.
It was also a fun way to explore some classic generative art techniques that I'd never coded before - boids, L-systems, hex grids. I tried to spend one to two hours on each sketch, but some took a lot longer.
I gave myself a few constraints for each sketch:
View the prompts, sketches, and notes:
Particles, lots of them.
Spheres parented to a rotating transform. I ended up spending most of the time on Day 1 getting the trails effect working. Recycling the drawing buffer took some effort. I ended up using this effect in a bunch of the later sketches, so totally worth it!
No palettes.
I started the month with a self-imposed constraint that each sketch would use two randomly-picked colors. I wrote a helper to pick color combos that tend to be higher-contrast. The sketch is concentric circles + shader-based noise jiggle.
Droste effect.
The Droste effect is when an image appears within itself. I used the video feedback effect from { day 1 } and UV scaling to get the previous frame drawing inside the new one.
Pixels.
Got WebGL instances working. Sphere instances scaling up and down to act as pixels.
In the style of Vera Molnár (1924-2023).
Rotating cubes with a position-snapping vertex shader. I had never heard of Vera Molnár. Her work is really inspiring.
Screensaver.
Went for a 3D take on the DVD idle screen. Getting the collision detection working inside the rotated space of the cube led me to a bunch of small bugs and annoyances with my transform code in Gum.
Progress bar / indicator / loading animation.
Played around with sine waves unit I ended up with this. More trails.
Chaotic system.
Made some springs. This one starts with a 3D lattice of points, then randomly connects about half of the points with springs. I added enough damping so that the resulting system wouldn't be too chaotic.
I also added a depth-based fog gradient effect, which I ended up using a lot more throughout the month.
ASCII.
ASCII half-toning as a shader effect. Draws the ASCII value-map to a texture. Each tile of the final effect samples the ASCII texture based on the scene's brightness.
Hexagonal.
Did this one a couple days late. It was a good chance to write the cylinder primitive into Gum – which it didn't previously have.
In the style of Anni Albers (1899-1994).
I really wanted to make something that felt woven. It took a lot of fiddling. Animations are sine waves applied in the vertex shader. I added the depth gradient to exaggerate the over-under.
Lava lamp.
Metaballs-ish. Spheres drawn in 3D then fed into a box blur + threshold post-process shader.
Wobbly function day.
Wobbly function is Piter Pasma's term for modulated and nested sinusoids. sin(a + bx + cos(c + dx))
would be an example. This sketch uses 2 dimensions of wobble to drive the rotation of the instanced lines.
Less than 1KB artwork.
Icospheres + random decimation + depth gradient. I kept the script to 0.5KB, which was a fun challenge.
Use a physics library.
Stayed up til 3am learning about physics solvers and getting a really simple sphere-only Verlet system working. Still really busted with large time steps.
Draw 10,000 of something.
Like some of the earlier sketches, { day 4 | day 13 } this one uses WebGL instancing. 10k spheres with size driven by a spherical distance function. All animation in the vertex shader.
Inspired by Islamic art.
Had a bunch of false starts with this one. I kept trying to make interesting things using straight-line intersection math based on articles on Islamic tilings. The ergonomics of doing 2D lines and shapes in Gum were definitely getting in my way.
This ended up basically being a circular version of the Anni Albers weaving sketch { day 11 }.
Bauhaus.
It's not even from the Bauhaus, but I really wanted to make something like this image using a depth-modulated spiral effect. It didn't end up being all that effective.
Generative typography.
For this one, I made a tiny input tool that let me define letters as bitmaps. Those bitmaps determine where spheres end up. A dither + outline post-process effect gives the noisy result. Not super readable.
Use a library that you haven’t used before.
Took this chance to explore a few different patterns for programming async, tweened animations with Gum. I also added some utilities to get the screen-space center of a transform to position the labels.
Point - line - plane.
Shout out to Paul Bourke – his collision and intersection code examples are so handy. Intersections between 3D lines drive the size of spheres.
I wanted the sketch to feel musical in the way that Kandinsky's (who inspired the prompt) paintings do.
Inspired by a photo on your phone.
Brute-force packing with some cute flowers.
Grow a seed.
L-systems are awesome! This was my first time coding an L-system, and I had the most fun writing this sketch.
Code for one hour. At the one hour mark, you’re done.
Simplex noise stack using Stefan Gustafson's noise functions.
Skeuomorphism.
A (barely) skeuomorphic oscilloscope playing a wobbly function { day 13 }.
Signed Distance Functions.
I was excited to get 2D SDFs going. Added some dithering too.
Shaders.
Ray-marching 3D SDFs. After the end of the month I spent another 3 or so day's worth of fiddle time trying to get the ray-marched shape to depth-test correctly with the rasterized sphere.
Generative music / Generative audio / Generative sound.
The large sphere moves though a lattice of smaller spheres, triggering notes when it gets close to them. I pulled in SynthKit to make the sounds. Working with sound again was so fun that it inspired me to spend most of February refactoring and adding effects to SynthKit.
( 1 )