This is a problem for computers because they don't do random. I don't have access to some nice radiation, and I only have the one lava lamp, so getting random numbers is pretty much impossible for me - besides, lava lamps are too slow. So I went and got some pseudo-random numbers. They're good enough.
The trouble is, you can't have one global random engine then generate numbers from it using multiple threads, that's a recipe for disaster (see my previous posts). But what you can do is give each thread its own random object to pass around. Each one of these needs to be seeded when it's created, I use the time as a seed, like most people.
Eventually, things got a little complicated, so I made a random class. When an object got created, its constructor would seed the random generator with the current time. But things weren't quite right, the numbers wouldn't generate properly, for some reason, it would give the same ones over and over again. This produced the resulting image:
std::mt19937_64 rng;
// initialize the random number generator with time-dependent seed
const uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::seed_seq ss{ uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed >> 32) };
const std::uniform_real_distribution unif(0, 1);
rng.seed(ss);
seed = unif(rng);
This is quite nice, it requires a lot less code. It also runs a fair bit faster. The previous method took about 2 minutes with my changes to sampling, this one took less than one. Here is the code for that:
return float(rand()) / (RAND_MAX + 1);
I forgot to seed it at first, and got this worrying result:
const auto timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
srand(unsigned int(timeSeed));
seed = float(timeSeed);
Anyway, this the result, it's pretty smooth: