But here’s one from today: These odd little surface blemishes. In this shot, they’re all black. In others, there are some white ones, too.
As before, this turned out to be another little glitch in my multithreaded terrain generation.
In MMORPG2, generating the world terrain data happens in the background — when the game starts up for the first time, it starts generating terrain data. It uses several threads to do this; all working at the same time. Each thread works on building the data for a little rectangle of terrain.
Some bits of the terrain data being generated rely on other, nearby bits of terrain data. For example, on a particularly steep slope, fields expose dirt, rather than showing grass. Sometimes that terrain data which I need to fetch (particularly when determining the surface normal, which itself affects the surface color), a thread needs to query the data being worked on by another thread.
To handle this case, I keep a flag for each bit of terrain data, marking whether or not that bit of terrain data has yet been generated. If it hasn’t, the terrain generation thread will go ahead and generate that data itself, even if it’s outside the region it was supposed to be generating. If it has, then it just uses the data which had already been generated. The theory is that when the thread which had been supposed to generate that data eventually gets around it doing it, it’ll say “hey, somebody’s already generated this for me. So I don’t need to generate it myself, I’ll just use whatever they calculated.”
Works great, except for a minor problem; I was setting the “I’ve generated this data” flag slightly before I actually set the data. So if thread 1 needed external data and started generating it, then if thread 2 needed that data, it was possible that thread 2 would ask for the data in the brief moments between when thread 1 set the flag which set “this data has been generated!” and when it had actually stored the data. Which resulted in thread 2 grabbing data which it thought was set, but actually wasn’t. Which led to artifacts like those shown above; little single-vertex-wide glitches, mostly along the edges of the blocks of terrain during initial terrain generation.
By switching the terrain generation to set the generated terrain values *first*, and the flag stating that the terrain values had been set *after*, this problem has now gone away.