Procedural Perlin-based maps with leaflet and web workers

Procedural creation is not necessarily linear. Or it is, but quite often one can run processes in parallel for making it faster. I recently learned some javascript in my everyday-job and I wanted to exploit web workers for creating procedural worlds. In addition, I also learn a bit about leaflet and I am just curious about how far we can go with that library for exploring fantasy worlds.

Thus, after a shy try with leaflet, I got inspired by the nice application of leaflet-fractal so I decided to use the same powerful combination of leaflet-workers-canvas to explore Perlin-based maps. I also wanted to play with isometric perspective so I tried if it was possible and indeed, anything is possible.

Pure Perlin

The first version is purely noise-based. Every pixel can be computed independently. To simulate linear mountain range I could not use pure tectonics (I am trying to keep pixels independent) so I am taking the absolute value of two noises at quite different octaves, turn it upside down, and raising to some high power as 4. I add later some continents as saturated Gaussians and then add the background noise at different octaves. There is a lot of cousine in creating the perfect combination of noises, if such a thing exists. This is the part that requires art.

This is the result (refresh or use the button for a new map):

You can go directly here or check the code in Github. There is no need at all in using voxels/pixels, I just found it funny! Before I forget: it allows to play with the elevation or choose which map you prefer to load when reloading.

Perlin plus erosion

Just Perlin is cool for fast maps. You can make them as big as you want. However, erosion. The calculation is more complex and pixels are not independently generated anymore: we need a grid. Additionally, a fast-enough erosion algorithm to run in on-the-fly and in your browser is a challenge. Mine is not perfect and becomes slow for too dense grid points, but I think I am in the right direction.

For future convenience, I am using a random quadrilateral grid. What is that? A regular squared grid where grid points are randomly moved inside their squares. What I would do such a weird thing?

  1. Keeps the simplicity of a regular grid: easy to map and easy to find the neighbors at any moment. It keeps beautiful algorithms.
  2. Easy to scale: the ultimate procedural map needs to re-scale the resolution with the zoom level. As you can see below, with this type of grid is really easy!
  3. It incorporates randomness in a straightforward way: no straight lines if you don't want them.

This is the concept that I am working now for on-the-fly scaling: I can compute the fluvial back-bone with a not-too-dense grid and generate the details on-the-fly as the zoom level increases.

Problem with random quadrilateral grids? Of course it breaks the symmetry, so some dynamical procedures can have some preference to go north/south/east/west instead of any random direction. River creation for example. Also, I had to write an interpolation code for rendering in the canvas: I need to map the random quadrilateral into a unit square first, and then apply the standard linear interpolation. (Not a big deal actually, there are some good solutions out there for interpolating in unstructured grids.)

Some screen-shoots below! you can test the DEMO here. Code is also available in Github.