Stochastic Geomophical Transport for Terrain Erosion Simulation
One major way to model terrain has been through simulating erosion: how the rock weathers away is a big component of the vibe of the landscape on a geological scale. But there's a couple of components to that: both the erosion itself and also where that material goes afterwards. In short, this new simulation from Nicholas McDonald and Guillaume Cordonnier handles both mountains and rivers.
(Another major way, of course, is Perlin Noise and related approaches, which eschew teleological realism but gain other benefits.)
The idea here is momentum conversation: using a new particle-based algorithm (which can be combined with other geological processes, like tectonics and wind direction) it simulates geomorphological transport, which operates over geological time, taking advantage of the difference in timescales: over the course of geologic time, a river is basically instantaneous.
This makes it very flexible for mixing "a wide variety of phenomena" as they say: in the paper they describe the potential for things like dunes, coastal erosion, floods, rockfalls, varying erosion weights. I particularly like how effective it is at effects like braided rivers and river deltas, which are very common in nature but often overlooked on procedurally-generated maps.
On the other hand, if the erosion is fast (individual rockslides) or transport is slow (glaciers) that breaks the assumption and it won't be as accurate at modeling it.
I think the reason that I'm personally drawn toward this algorithm is because it has a history that is naturally embedded in it.
You don't necessarily need to replicate the exact phenomena that was involved in creating something to get a good result. Much of games and simulation is about picking the right abstraction to get the right feel, regardless of how you get there. It's often the better call, to get the right poetry instead of the exhaustively correct metric. But one benefit that you do get replicate the physical causative process to try to simulate the physical effects of water, wind, and time is that it comes with a built-in sense of history.
Simulation creates its own history. In looking at the terrains produced through this method, you can see the paths of historical rivers, the canyons carved out over millennia and eons. All the details that humans find hard to capture just because of the sheer amount of subtle detail that builds up in tiny ways.
The Terrifying Cave Generation of Minecraft Snapshot 21w06a
The Terrifying Cave Generation of Minecraft Snapshot 21w06a
After a very long wait, we’ve finally gotten to the ‘caves’ part of the Caves and Cliffs snapshots. This is very exciting for Minecraft, since a cave update has been both teased and desired for years. While Minecraft’s original cave system is pretty cool, especially with canyons, Snapshot 21w06a threatens to completely demolish it. While only being the tip of the iceberg.
21w06a introduces the…
The Treachery of Rings- Escaping the consistency of Perlin Noise
Perlin noise is an algorithm very common in computer science- it is an algorithm designed to create maps of graduated floats that range between 0.0 and 1.0, maps that can be referenced by coordinate and thus used to add variety to textures, height maps, et cetera.
The primary advantage of algorithms like Perlin noise, simplex noise, et cetera, is that these variations can be achieved mathematically, rather than by a determinism based on a pre-existing state of input data besides the coordinates. However, the true beauty of these maps is in the ability to use them as a basis for more sophisticated algorithms. Data ranges of these 0.0-1.0 floats can be used to place objects, modulate other values, and so on. However, when they are used as height map data, typically they are either taken “as-is” and used to generate hills/islands or add subtle variety to manually-drawn maps.
Personally, I never liked to see it used to generate islands and hills. The problem I have with it is that, viewed from a macro level, Perlin noise is slightly too consistent.
What bothers me most about naive implementations of Perlin Noise are what I call “height rings.” In this image, you can see bands of slightly darker green that neighbor the higher green and the blue. This is the expected behavior of Perlin noise. Naturally, when you have variables that slowly graduate, they will pass into values that lie between the starting and ending values. In two dimensions, this creates the ‘hills’. This process, using the quasi-random behavior that makes Perlin noise work, creates hills at varying height, spacing, and slope.
So what’s my problem?
Well, the problem is that if one uses Perlin noise to generate landforms, then the landforms generated will not be naturalistic. Hills, viewed ostensibly, behave similarly to this when one compares a single hill in reality to a single hill in a Perlin noise map. However, the problem is that landforms in the real world do not consistently follow this pattern. This is especially true of continents, where the mountainous peaks usually stand to one side, rather than in the center, of the landmass(this is because of continental drift, where the tectonic plates rub against each other, pushing the Earth’s crust upward at each plate’s edges).
Often, Perlin Noise is implemented in such a way that it has ‘octaves’ of itself, where the variations are further varied by repeating the algorithm at a higher frequency and adding it to the previous result. This makes the resulting map more interesting to look at, but still not realistic.
So what’s our goal? We want to create a version of Perlin noise(or any other similar algorithm- What we’re about to do can be used just as well with Simplex or value noise, for instance) that allows values not only to graduate from one to the other, but can also ‘skip’ back down to a lower value- Essentially, creating cliffs. Cliffs that, like the hills, are determined mathematically.
So how do we do that? What we need is an extra dimension to this. We need another graduation of value, one that approaches either a ‘slope’ range or a ‘cliff’ range.
The easiest way is through vectors.
Vectors are representations of directions on the number plane. In two dimensions, we have X and Y. Given each value pair of X and Y, one can extrapolate a direction. Using trigonometry, we get an angle in reference to angle 0, which most often lies on the positive X axis. This angle from a starting rotation can be considered in terms of ranging from 0 to 359. If it wraps across the top, it wraps back to the smaller value. 360 is equal to 0, 361 is equal to 1, et cetera. This is inversely true, as well: -1 is equal to 359.
So, because Perlin noise gives us values that graduate across a range, we can apply this range to an equal positive and negative value set. -1.0 and +1.0 will work just fine. If we do this twice with different modifiers, we can get a semirandom 2-dimensional vector. And if these values can each cross their range independent of each other, what we can get is a direction that can turn clockwise or counterclockwise freely without ‘bouncing’ off the boundary where the angle 0 crosses into angle 359. Instead, depending on the value of one dimension, the other dimension will either graduate cleanly over from 90 to 270, or cross from 270 to 359, wrap back to 0, and then graduate to 90.
If we then project this angle from degrees(or radians) back to a range of 0.0 to 1.0, we get a new map.
Here, we have replaced the ‘hills’ of standard Perlin noise, which always move smoothly from 0.0 to 1.0 and back to 0.0, with a form that can move smoothly from 0.0 to 1.0, OR immediately drop back to 0.0. Thus we have create the basis for more varied landforms in terrain generation.
But we can do even better. It’s dramatic, but not realistic, for cliffs to drop at an angle of exactly 90 degrees, or at least to do so always. So let’s pick a more reasonable shape for them.
We can translate our new 0.0-1.0 range onto a curve, getting any new graduation pattern we want. It simply uses our original pattern as a ‘landmark’ for changing the pattern. This is the result:
Picturing the brown areas as highlands and the white as mountain peaks, already we’re starting to see patterns that look a little more ‘continental’ than we could get with Perlin noise.
Now, let’s re-introduce the octaves which added variety to Perlin:
The same patterns have been transformed- We now have coastlines that are either smooth or ragged, and mountain ranges that don’t necessarily sit in the center of their continents but instead to one side. We even have some very interesting-looking inland seas and archipelagoes.
What’s even more exciting are further potential with this direction of change. For instance, using a third result from our Perlin function, we could add further variety, perhaps by interpolating our translation curve to different shapes. But I think this is a good place to stop for now.
You can, of course, generate things with recorded Photoshop actions. One artist who uses the handle Yo-L did just that. They posted the actions and patterns used, though they require Photoshop CC so this exact set of recorded actions won’t work on earlier versions.
The principle is sound, though, and you can use the concepts for all kinds of image generation. Remember, Photoshop is just acting on a 2D array of numbers. A generator that used a node-based interface or is coded directly by writing functions can do the exact same math.
It’s sometimes worth hauling out an image editor and seeing what an operation will look like as you’re trying to reason through the inner workings of your generator.
Some useful operations:
Curves and ramps:
By applying a gradient (or more complicated ramp or curve) to an image we can create a wide variety of effects.
Clouds, curves, threshold:
This is just a curve layer and a threshold over the cloud filer (which is itself a form of value noise) but it creates very organic transitions:
Adding detail with a blend mode
Need to add detail to a coastline? Here I’m screening a noise layer over a smooth threshold-based coastline to add detail. “Screen” in Photoshop is just inverting the layers, multiplying them together, and then un-inverting the result. Just like the filters, all Photoshop blend modes are just math.
What about removing detail?
Here I’m using a Gaussian blur as a low-pass filter to remove the details from the underlying value noise, which results in a smoother look. If you’ve got a generator that’s too noisy, try filtering out the frequencies that you don’t want.
Distortion!
Alternately, maybe you just want to distort your image a bit and break up its regularity. Remember this post about Íñigo Quílez’s use of warping? Photoshop’s Distort filter does the same thing:
There’s a zillion more things you can do with this (look up image kernels in particular). If you’ve got a generator that is putting out results that are close to what you want but not quite there yet, consider doing some post-processing on it.
I’d love to see other people’s examples of simple post-processing techniques, whether implemented in code or in Photoshop.