Genuary 2022: Generative Art Challenge
I love “computer art”
I love generative art. I love looking at it, I love collecting it (thank you NFTs, and Hic et Nunc in particular), and I love making it.
There are other interesting Tezos based NFT sites now such as Versum, OBJKT, and fx(hash).
Raphaël de Courville asked on Twitter recently who you would point to if someone asked “what is generative art?”. My answer was right away, John Maeda — I saw him talk at a design conference in 2001 in Melbourne and have be inspired ever since.
All that said I haven’t really been creating generative art recently, as in not for the last 20 years. I had a quick go on H=N, but they won’t very artistic, and other than that had just been rehashing old ideas (although this one I’d never actually created, it was just an idea floating in my head since 2001).
I’d got back into it because of a Tweet by Mario Klingemann in early 2021 about a new NFT platform. If he was into it, I was too — I’d been following his work since before he was blogging about how to implement content-aware scaling in Flash! I bought an artwork (a piece that is of the medium) from him, and found myself interacting with people I’d always looked up to on Twitter. Inspiring to be “talking” to your heroes eh!
31 days of creating art
So when I saw people Tweeting about Genuary — creating a new piece of generative art every day of January, based on a prompt — I was in!
Here I will go through each day and show you what I created, what I learned, and some of the other pieces I found that are inspiring!
For some I will link to more details below the title.
Day #1: Draw 10,000 of something.
➡ How it was created
Day #2: Dithering.
Day #3: Space.
Very boring. Just randomly placed circles.
Day #4: The next next Fidenza.
Fidenza is an amazing generative work by Tyler Hobbs. It uses Flow Fields as a base to create some really beautiful, distinct and versatile work.
For this one I cheated. I just posted some work I’d created previously, and instead of looking at Flow Fields (yet) I decided it was more about versatility.
This was a work I had created in Flash in 2001, and then recreated in 2020 in JS/Canvas.
The most interesting thing I did with this one was to create a version for the generative art / NFT platform fx(hash) — see it here. The biggest mistake was to let it create anything (random) and not restrict it to a smaller set of interesting parameters, so a lot of the generated work is kind of ugly.
Day #5: Destroy a square.
Finally I created something that looked nice, and stretched my coding abilities a little more.
The process
- Pick a random point within a square.
- Pick a starting angle.
- Add a random amount to angle and then work out where a line along this angle would intersect with the square.
- Repeat until we’ve gone 360 degrees from the start.
- Draw polygons using these angles.
The hard part was making sure the corners were added to the polygons if a break occurred around it.
Day #6: Trade styles with a friend.
For this one I found someone (Monica Dinculescu) else who was participating in Genuary on Twitter and, with permission from her, tried to replicate her work.
The process
This one was mostly easy. The hardest part was to work out how to draw a rectangle from point a to point b, as I was using a great library RoughJS, to get the hand drawn look.
Drawing the tree itself was simply choosing a number of branches at each point and possibly drawing a smaller one from there. Monica suggested using L-Systems for the tree as she had done but I didn’t have time to get into that.
Day #7: Sol LeWitt Wall Drawing.
I ran out of time again for this one so just repurposed my Day #5, but draw 4 of them with colors from a pallet I stole from LeWitt’s wall drawings.
The most interesting thing about Sol LeWitt is he could be thought of as one of the first generative artists, as he didn’t “draw” the artworks himself, but instead wrote down precise instructions on how to create it, very much how we instruct a computer to create art for us. He showed that the hand of the artist wasn’t as important as the ideas.
INSTRUCTIONS
- Break into 4 squares
- For each square
- Pick a point
- Draw a line to the edge
- Draw lines to edge between 15 and 85 degrees apart
- Fill with a color from pallet
Day #8: Single curve only.
I finally wanted to learn all about Flow Fields, and there is a great write up by the Fidenza artist here.
I also added a UI so I could play with variables that create the art using TweakPane. Another option would be dat.gui.
I know it wasn’t a “single curve” but I was hooked. You can see a visualization of the field generated below.
I also did some reading and took advice from people who know what they’re doing!
- Don’t use random colors. I chose a pallet!
- Try to have “Shapes” at all sizes
- Don’t simply place things randomly. Try something else like a Box-Muller transform.
With that advice I was finally creating things that looked nice!
Day #9: Architecture.
I even got it to animate and output a video using CCapture. Great library.
Process
- Get a “cloud” of points using the non-quite random Box-Muller transform from above
- Sort by the y value for depth
- Draw boxes from each point
There are a few things I added to make it work
- divide the y position to squish the circle
- lerp to the color given the y position to add fog (I first work out the min / max y position to normalize the fog from back to front)
- the height of each box depends on on the distance from the center, put through an easing function.
Even though I was trying for a city, I think it looked nicer like this:
Day #10: Machine learning, wrong answers only.
This one was easy. Just pick from a list of parts of a sentence, or adjectives / nouns and put them together.
I already had a list of nouns and adjectives from my silly CGA-iri work I created in 2012.
Day #11: No computer.
I was intending on doing a Sol LeWitt style drawing, I even had a bunch of instructions written down but in the end it felt too computer-like.
So I ended up going outside and “generating” this from what I found on the ground.
Day #12: Packing (squares, circles, any shape…)
Packing circles is probably the easiest thing to pack, at least if you are not trying to get the most of them in a space.
Jeff has an interesting way of packing arbitrary images but I went with the easy problem.
Amy also goes through some great ideas for packing too.
Taking the advice I learned earlier I did end up with something I like, choosing a pallet, and adding both small and large details. I even wrote some code that tries to fake a “painted circle”.
Day #13: 800x80.
Playing around with Perlin noise, based on this great article. Shows how to get different patterns out of simple noise, this one being marble.
Reminds me of my old 3D Studio Max 1.0 days!
Day #14: Something you’d never make.
Again playing around with old noise algos. Tried to make something super ugly.
Day #15: Sand.
Another old-school effect; fire! By simply turning it upside down and changing the color palette we’ve got sand falling into water?
Day #16: Color gradients gone wrong.
The last old-school effect I’ll look at. This time plasma.
Day #17: 3 colors.
Today we have a random flag generator. The most interesting part of this was the code that makes it look like it’s waving in the wind. It could be done a lot faster using pixels[] or a shader.
- Shape ideas from this generator, and Wikipedia List of Flags by Design.
- Colors from Wikipedia List of Flags by Color and this great visualization of flags by color.
- Turns out most flags have a ratio of 2:3.
There is also this amazing flag that I found. Nothing else like it! Way more than 3 colors so you are not going to see that generated.
Day #18: VHS.
Needed a break today. Could have done a lot more, but I’ve been spending too much time perfecting my circle packing library! Would be easy enough to:
- Get tape to follow correct path
- Add texture to container and other parts
The most interesting thing here is that an easing function is used on the size tape so they spool faster when smaller. The ease function is the same for both spools even though one is growing, and the other shrinking because easing functions work between 0-1
and they grow/shrink like time
vs 1-time
.
Day #19: Use text/typography.
Feeling a little burnt out … who knows what’s going on?
Day #20: Make a sea of shapes.
Using the circle packing library I’ve been working on. Put a “boat” on a random walk, destroying anything it hits, and packing circles back in its wake.
Day #21+22
- #21: Combine two (or more) of your pieces from previous days to make a new piece.
- #22: Make something that will look completely different in a year.
I’ve been playing with different noise generation, as well as gradient palette lookups.
Here I’ve mixed Perlin noise with some Domain Warped noise and a custom gradient color palette.
Over time the palette will shift so the sea (blue) grows and eventually takes over the land.
Come back in a year and it will be mostly gone. Come back in 3 and there will be no land.
Day #23: Abstract vegetation.
Trying not to spend too much time on these. Using techniques from earlier, I place the red circles using some easy Vectors, rotating by `Math.E` each time. Then just place a bunch of packed circles around, and draw using my previous painterly circle algorithm.
Feels nice to have a library of techniques, even if I’m being lazy here.
Day #24: Create your own pseudo-random number generator and visually check the results.
I have no idea how this works. I tried to read some theory on pseudo-random number generators but it really just went over my head. Instead I just smashed the keyboard for some numbers, added a Sine and Cosine and go this.
Using Sine and Cosine helps to keep numbers between -1 and 1, and you can simply add an “abs” to get a number between 0 and 1.
Weird. I think it actually works, although it does skew a little towards “1” it seems.
Day #25: Perspective.
This one is again a mashup of many previous days’ works. I really feel I should start on something new now?
Day #26: Airport carpet.
Based on this “great” carpet I started to build a generator. As you can see I got bored at some point and didn’t bother to replicate properly.
I did create a nice little utility that adds “fur” to images though. It simply goes through each pixel possibly draws a line (from the pixel color) a few pixels up, and a few pixels either left or right.
On Twitter there are some really great examples of way better fur/carpet texture generation!
Day #27: #2E294E #541388 #F1E9DA #FFD400 #D90368
Using my previously created libraries including circle packing, fur, painted circles, and new a new one which draws through a series of circles, giving a brush stroke effect.
This was an exploration of how I can use all my utilities together; I did not used the provided prompt colors so well …
You can draw below and see how the brush stroke library works.
I also started to explore some nicer looking uses.
Day #28: Self portrait.
Used my drawing app to create a self portrait. Rendered using draw-through-circles. Added some shading using RoughJS.
Not really generative though.
Day #29: Isometric perspective.
Today started idea started as simply taking day #21 and making it isometric (using some “stolen” code).
Somehow I couldn’t put it down and learned all about Worley Noise, added multiple layers of trees and then, after working out how to create a cheap/lazy normal map from a height map, adding some very dodgy lighting!
It takes quite a while to generate a large plot of land though … optimizations can wait for later.
Day #30+31: Organic looking output using only rectangular shapes / Negative space.
I needed to get out for the the weekend so just threw this together — inspired by images in this physics article. It did not turn out as I wanted, but there are things to do!
And that’s a wrap …
Wow. That was really amazing!
I haven’t been creating like this in years. Like 10 years! So thank you to everyone for the inspiration.
I’ve learned so much and I’m going to take that knowledge and write a bunch of tutorials / explainers on things like circle packing, flow fields, and different kinds of nice noise — there’s so many: Perlin, Cubic, Worley, Simplex and then domain warping to make ’em look super interesting!