Hello, and welcome to the Pretty Colors edition of Adventures in Terrain Generation. This episode in particular is special because, as promised, it will be the first one to not involve that function that everyone needs a break from. Now that you’ve breathed your sigh of relief, let’s start roasting/freezing this planet!
Step 0: Gathering some Knowledge
Here are some facts from high school Environmental Science I had to re-learn for this chapter:
- Temperature is warmest at the equator and coldest at the poles (luckily I didn’t have to look that part up).
- Water is slower to change temperature than land, making the ocean warmer on average.
- The surface temperature of land that’s covered in snow is lower than that of land without it. This isn’t just because cold makes snow happen, but because snow is extremely reflective and bounces back most of the sun’s light, absorbing little heat. This partially explains why ice caps can stay icy even when they’re covered in 24-hour sunlight, as well as why I can’t drive on sunny winter days.
- While normal water freezes at 0°C, the salt in seawater lowers its freezing point to -2°C. This finally answers the question “What’s cooler than being cool?” first posed by philosopher Andre 3000 in his influential essay “Hey Ya!”
With this, we have enough information to start simulating global temperature in our world.
Step 1: Latitudinal Temperature
Since temperature is invisible (believe me, I checked), we’re going to need a new way to view the world so we’re looking at temperature values and not physical geography. By the end, we want our temperature map to look something like this:
With this color scheme, everything above freezing temperature is between orange and yellow, and everything below freezing runs from green to blue. With that in mind, here’s my first run at the temperature map:
Okay, so obviously this is pretty simple so far. At this point, temperature is based solely on latitude and doesn’t take elevation or material into account. Because of this, temperatures run in a smooth gradient from 45°C (113°F) at the equator (shown in white), to -45°C (-49°F) at the poles. These numbers are somewhat arbitrary, but are based on the ranges I saw on real-world maps while researching this and that’s good enough for now.
This temperature map in particular is going to become important later as we start to simulate seasons (something I haven’t tried yet at time of writing). The map, as we have it right now, effectively simulates the equinox, when the position of the earth relative to the sun results in it being directly above the equator. However, during the winter and summer solstices, the sun is directly above the Tropics of Capricorn and Cancer, respectively. In practice, this means we can simulate seasons by moving the center of the temperature gradient up and down as a sinusoidal function with a period of one year and an amplitude of 23.5°. If that’s too math-y, don’t worry about it because we’re not going to talk about it for another 4 chapters*.
Step 2-4: Terrain and Elevation-Based Temperature
Now that we have the extremely basic set up, we need to take materials and elevation into account. Remember from the OutKast reference above that higher elevations result in lower temperatures, and water ends up warmer than land. If we apply that to the terrain we’ve been generating so far, we get the following map:
Now that we have something pretty close to our target image, we can apply it to our terrain. Basically, anywhere on land that falls below 0°C will become covered in snow, and anywhere in the ocean that falls below -2°C will freeze into ice.
While this does look pretty close to what we’re going for, there’s a slight problem with the ocean not quite simulating depth as well as I wanted it to. So, through a series of events that doesn’t bear going into in this chapter, I wound up with this:
Already, we can see a problem with the ice as it comes close to land. It’s forming these weird, sharp curves that don’t line up at all. Luckily, I have an explanation! When I was calculating where the ocean should freeze, I made the decision that shallower water should be warmer. After all, if there’s less water to warm it should be easier to keep it from freezing, right? Ha! Wrong! In fact, the opposite should be true. I have a working theory as to why this happens, but I reserve the right to be completely wrong since I didn’t research this as well as I should have. Basically, there are two forces here that I think are at play:
- Convection currents in deeper water bring more warm water to the surface. The motion of the current and the warmth at the surface keep the water from freezing.
- Water near the coastline is too shallow for these currents to do much, and the proximity to the land results in nearby snow reflecting away the sunlight so less warmth reaches the water in the first place.
Knowing that, solving this problem is as easy as flipping a value. However, there’s a slightly bigger problem in how the ice looks when you look a little closer.
Step 5: Oh.
The problem, if it’s hard to tell from the image, is we’re seeing sharp, sawtooth-like edges where we should be getting smooth curves. It looks horribly unnatural and just plain ugly. Luckily, I have an explanation for this too! Less luckily, it’s a bit harder to solve. Even less luckily, it has to do with math. Don’t worry, I took a preemptive cat photo.
If you remember the last chapter, you’ll know that when we were initially deciding on elevations, we used decimal values from 0-1. That was fine at the time, but eventually it’d be nice to know exactly how high in meters a block in the world is. To do this, I decided to map those decimal (continuous) values from 0-1 to integer (discrete) values from 0-256. The problem is, when we do this, we have to drop the decimal part of the value. This means a number like 245.85 is going to get shortened to 245. When we only care about what the terrain looks like, this isn’t really an issue, but now even a small difference in elevation can cause a much higher difference in temperature. This means that numbers that would be really close to freezing temperature (like 0.2°C) might actually drop below freezing because the block we’re looking at is one meter higher than its neighbors. It’s these small changes to elevation that cause the aliasing (“sawtoothing”) shown above. The solve for this, unfortunately, doesn’t seem simple (at least it didn’t at the time). I could create a new grid that keeps track of the continuous elevation values, but that would essentially double the size of the world and cause the “game” to run slower. As one attempt at a fix, I tried using randomness to decide which blocks should be ice and which should be water, similarly to how we handled trees in Chapter 2. My thought was that it would blend the icy coastlines into the ocean a bit better. The results were, um…
Not only is this ugly, but you can tell from the little ice-islands on the right that it didn’t even solve the original problem.
After spending almost two weeks puzzling over this, I finally solved it by remembering something extremely obvious: the way we calculated elevation is a math function. I didn’t need to keep track of the values we got when we initially calculated it, because I could just plug in the same variables I used to get the same result! The actual calculation itself is time-efficient and only happens once, so it doesn’t slow down the “game,” and I can completely ignore the integer-ized values to avoid the aliasing. After a hearty facepalm, I implemented it and you can see the new result below.
With that squared away and the hair I pulled out starting to grow back, basic temperature was finally done. The final temperature map, a bit warmer since I had to rework the whole system, is shown below.
Still beautiful. And now, the resulting terrain:
Incidentally, this marks the last time the world’s surface will visibly change until… Chapter 6? Next time, we’ll go into some actual computer stuff (sorry in advance), talk about rendering, and make the map actually 3D (kind of)!
*Real quick note about the future of the series: So far I have 11 total chapters planned. Of those 11, five cover things I’d already accomplished when I started writing Chapter 1. Three of them of them cover things that I’m pretty sure I know how to implement, and the other three seem so far out of my league at this moment that I’m kind of scared to think about them. I know I said seasons would be 4 chapters from now but, since that’s among the things I haven’t tried yet, this is subject to change.