Home
Search and run commands
J
Nathan's generative art gallery
2021

Generative Art

An art exhibition and exploration of code.

Table of Contents

Introduction

Generative art has alway been a hobby of mine, which inspired me to build . Technically, generative art also includes AI-generated artwork, but my work is more in line with "creative coding" - creating computer graphics directly through code, not a black box model of weights. One of the things that always stuck me about creative coding was its transience - much of the colors and shapes are the result of some controlled randomness. Each piece is inherent unique because that randomness will likely never occur in exactly the same way ever again. In this way, not only do I get the privilege of seeing dozens if not hundreds of unique art pieces as I build a sketch, but I also get to share that privilege with others. As a side note: I refer to generative artwork as sketches, which I suspect is quite common after popularized the convention.

Features

Many of the features are actually not visible to the end user; indeed, I primarily aimed to streamline the creative-coding process with a series of bash scripts and common utilities for p5.js and Three.js. I will likely publish those utilities as some kind of library for others to use. In fact, I technically already published one called , but it is in dire need of documentation. The most important internal scripts I created are creating sketches from a base template and forking sketches (so you can create your own templates or work off of previous pieces to create new ones). The base template includes a standard HTML file importing some shared styles and a main Typescript entrypoint. While this is decently useful, most of the power is in a series of TypeScript utilities shared across all sketches, ranging from math functions to adding a little title to the bottom of a sketch. Here's what creating a sketch might look like, followed by forking it to make even more variants.
1 2 3 4 5 6 7 8 9 10 11 # must change permissions (for this user) to run the scripts > chmod u+x ./scripts/create.sh > chmod u+x ./scripts/fork.sh # create a new sketch from the base template > ./scripts/create.sh new-sketch "created sketch ./sketch/new-sketch" # copy the contents of new-sketch & assign a random name > ./scripts/fork.sh new-sketch "created sketch 109327"
This process is not very complicated and could easily be achieved by making a copy of the folder containing the template, but I learned Bash in college and I might as well use it. You can examine the (admittedly very simple) scripts in more detail on GitHub. In order to further reduce developer friction, all folders placed in the sketch directory are also automatically added and linked to the home page using the same strategy of my (Vite's import.meta.glob to find all of the sketches and then adding them to the DOM). Unfortunately, while this eliminates the need to manually enter the sketch links and name on the home page, using client side JavaScript to append links to the DOM causes a brief website flash because it is not server side rendered.
My little generative art gallery
My little generative art gallery
You'll have to visit the art gallery yourself to see all of the interesting things I've made, but here's a sneak peek of some of the pieces. Just be aware that you'll probably never see the same thing ever again when you reload each sketch, so save an image if you like it!
"Noise"
"Noise"
"Galaxy"
"Galaxy"
"Galaxy" also highlights how powerful forking or building off previous sketches is - it's a clone of "Monochrome Nodes", but adds colors and changes the configuration of the sketch a bit to make the result include more swirls.
"Monochrome Nodes"
"Monochrome Nodes"

Technical Stack

I built the generative art gallery home page using Vite, Tailwind, and TypeScript. The actual sketches use either p5.js or Three.js. Generally, it will be quite obvious which is being used - I only use Three.js for shaders and 3D sketches.

Challenges Faced

I initially didn't realize Vite does not support multiple pages and entrypoints when using plain JavaScript or TypeScript like the other metaframeworks I was so comfortable using. Fortunately, this is a relatively common problem and I found an easy fix that required manually building an object of the necessary entry points Rollup (which is exposed in Vite's config). I'm also currently reworking many of my old sketches to use TypeScript & the new workflow I described in the section. This is more a tedious process than an impossible challenge, but it is somewhat difficult to rewrite untyped old code from years ago for almost a hundred sketches (I only have around a dozen or so sketches rewritten as of writing!)

Current Status

I started creative coding back in 2021, but the website hasn't changed all that much compared to the internal tools I've been developing for myself. For example, instead of using Vite's import.meta.glob to auto-add sketches to the home page, I ran a custom script that would scan the file system (this hasn't changed actually, just Vite does it now) and directly modify the main entry point before each commit. It was a pretty ugly solution and I often forgot to run the script, resulting in a usually out-of-date gallery that required another commit just to update it. Interestingly, this approach may have been more user-friendly because the file contents would be present in their entirety, not appended later on as I am currently. This actually forced me to consider the balance between developer experience and user experience - should I chose a more developer friendly solution, but potentially damage performance? I think the answer is simply more well-designed and maintained abtractions and libraries that could provide both. For the foreseeable future however, the gallery will remain a simple HTML file linking to other HTML files.

Future Enhancements

I'm considering using Remix (because I love it so much - it would automatically support file based routing and server-side render the sketch links on the home page) + my personal UI library to create a consistent theme across all of my services, but
  • I refuse to become one of those "senior" developers that constantly rewrite the product without adding new value and
  • I currently appreciate that the art gallery is a bit unique and expressive compared to the rest of my more uniform projects.
More importantly, I need to add configuration options (sliders and whatnot to control constants) and a reload option (rebuild the sketch without refreshing the page) directly on sketches, which would drastically improve user experience. In any case, creating more generative art is definitely a higher priority compared to adding new features. I'm also thinking about adding just normal drawings and pixel-art to the gallery, since the domain is intentiionally vague.

Conclusion

Throughout the project, I've learned that forking to create seemingly new art is a somewhat unique concept to creative coding and programming in general because of the random generation that is so commonly employed in sketches. While it iis possible to start from a template (in drawing a character sketch you may start with a character outline to get the proportions right), the only way to add to an existing completed piece is either erasing core parts of its identity or simple expanding it (such as drawing in the margins). This is not the case in creative coding - you can always add to a piece while preserving much of the original's identity (in terms of code). Even changing a few numbers to get shockingly different behaviors. If you're interested in creative programming and want to get inspired, you can look at my work (I'd be flattered, but many of my sketches are quite simple and flat compared to the epic shader work I'm trying to learn) or check out the for a list of generative artists and resources I've been collecting. You could also start with , but you will need to know JavaScript syntax or at least basic concepts like functions and conditions to understand what's happening in the templates.