In a recent post I shared some thoughts about art and included a few, somewhat tongue-in-cheek comments about the use of random number generation. Specifically,
Random is evil. Random is lazy. Random is OK when you’re starting a new piece. It’s OK when you have a formula and you’re searching for an interesting range of input parameters. But once you find something interesting, lock in those parameters and start focusing.
Interestingly, this was the part of the post that generated the most comments – only a few, but it was definitely the thing that several people latched onto. So I thought I’d expand my thoughts on it.
Now of course I don’t actually think random is evil. But it can be lazy, and it can definitely be boring. But yes, I use random all the time. In my blgo library I have a random module with all kinds of useful functionality that derives from Golang’s built-in pseudo random number generator (PRNG). In my bljs library, I had to build my own PRNG because one doesn’t exist in JavaScript. No, Math.random
is not a useful PRNG since you cannot seed it.
So what, in my opinion, is a good use of random and what is not?
Random positions and sizes
Not a great use of random. One of the most boring. I once said something like, “If you can draw a shape, you’re an artist. Randomly draw 10,000 of the same shape, you’re a generative artist.” But honestly I think that’s the ultimate in boring, lazy generative art. Here’s 10,000 random points:
And 500 random squares with random sizes:
And 500 random lines:
I could go on. And I could generate 10,000 individual “art works” like any one of these with a few lines of code. Each would be different. But I wouldn’t call it art. Maybe in my very, very early days of experimenting with graphic code I thought this looked kind of cool. But seriously, I hope your skills and self-expectation rise above this level really quickly.
A Different Random?
So what might be better? Taking it slowly, let’s just try a different random. If you’re using Math.random
or something similar that generates a random number, you’re probably getting a uniform distribution. This means that there is an equal probability that you’ll hit any given number in a given range. So it’s all pretty flat and boring. You could try a normal distribution. This favors numbers in the center of your given range, giving you something like this:
For this, you’ll either need a PRNG that has a normal distribution function, or you’ll need to come up with one yourself. Here’s a JavaScript example I found on StackOverflow that seems to do the trick:
// Standard Normal variate using Box-Muller transform.
function randn_bm() {
var u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}
Unlike a uniform distribution generators however, normal distribution generators will usually give you a range of numbers both negative and positive. Most of the generated numbers (around 99.7%) should fall into the range of -3.0 to +3.0. So you’ll have to do some transformations to get them into the range you actually want them.
Here’s an example that places 100 squares in a normally distributed random position, and uses a normal distribution for their sizes as well:
In this case, I took the absolute value of a generated number (which would generally wind up in the range of 0 to 3, weighted heavily towards 0) and multiplied it by 40 to get the size of each square. This skews the square sizes toward the smaller range. Of course, you could do different math to skew it to larger squares, or even towards medium sized squares, with smaller and larger ones occurring less frequently.
And some random lines with normal distribution:
If you find normal distribution interesting, you might want to look at one of the many other probability distributions.
We’re still in the realm of random, but even so, I think the results are much more interesting.
Noise
Another strategy that is more interesting than uniform random distribution is using noise. This usually means Perlin or Simplex noise (which I’ve discussed here in depth). Here, I chose 10,000 random points, but only accepted them if the noise value at that location was above 0 (in a range of -1 to +1):
Things get more interesting when you throw size into the mix. This one does the same thing, but draws squares. The size of each square is in proportion to the value of the noise at that point.
Other
Other things to try are various types of attractor formulas, chaos games, iterated function systems (IFS) and other fractal-related formulas. These can often be just as chaotic and unpredictable as PRNGs, but at the same time give some kind of underlying structure that is much more interesting than uniformly distributed random numbers.
Random Colors
I know next to nothing about color theory, and tend to do things in black and white as long as I can get away with it. Big fan of monochrome. But now and then I’m forced to use color under extreme duress. My first naive attempts to fly under the radar with color usually go along with a function I created called randomRGB
, which does what you would guess.
Here’s the above normally distributed squares (a few more of them this time) with random RGB color values.
Well, it IS colorful. But it evokes absolutely nothing. From there, I usually move over to HSV colors, which at least sends me in the right direction. Here, I’m using a random hue from 0 to 60 and a saturation and value of 1.0:
At least this has something going for it. A kind of pixelated, MineCraftian fire maybe. Or, we could keep a single hue and vary the saturation:
Or a random value:
These at least have something going for them. If you want to go all out, you can start creating color palettes. Adobe Color Wheel is a great resource. Here’s a split complementary palette I generated:
To be fair, I’m still just picking one of the five values from the palette randomly, so it’s still pretty lame. I refer back to my first statement of this section. I think it would probably be better to use the reds in one area and the blues in another and the green as a highlight… or something.
Random is Not Evil
As you can see, in just about all of my “non-random” examples, I’m still using random to some degree. But I’m using it secondarily, piping it through something else, which gives it some structure. Once you have some kind of predictable structure, then you start tweaking values to move that structure a bit this way or that way and start adding some of your own taste and judgement into what you are creating. Then it starts to become more of your work, not just the work of a PRNG.
Often, I will have some formula that generates some kind of fractal or attractor. It can produces quite different images depending on what parameters you give it. But that means there can be millions or even billions of different potential images (infinite really, but many of them will be very similar). So I’ll create a loop that just makes a bunch of thumbnails with random parameters and generate a grid of images. On each thumbnail, I’ll print the parameters that created that image.Here’s a sample from last year:
When I see one I like, I’ll hard code those parameters into the code and generate a larger version. Then I’ll tweak them one way or the other to create something that I really, really like. This use of random allows me to explore way more possibilities in a much shorter time than manually trying to find a good set of parameters.
Summary
I could probably go on about this subject a lot longer, but hopefully I’ve clarified my thoughts a little bit and maybe given you some ideas to try out.