This map is made in pure SVG -- no Javascript! View the source if you don't believe me! :-) ; doesn't work in all browsers, and works differently across some browsers, sadly. (There is javascript to change the seed and change the parameters using DAT.gui, but the map itself is made with svg filters)

Note that this is a generic map renderer. Given two grayscale images with elevation (heightmap) and moisture, it will use SVG filters to turn them into what you see above. For the demo I use SVG's perlin noise to generate both the elevation and moisture images.

Maybe I should've used GL shaders, but I wanted to see what SVG could do with filters:

• SVG feTurbulence gives us perlin noise. Let's use red channel for elevation and green channel for moisture.
• SVG feColorMatrix gives me a way to convert (elevation,moisture) to browns and greens
• SVG feComponentTransfer lets me do thresholding. When elevation < some_value, alpha = 1; else alpha = 0. This will be the water layer.
• SVG convolve filter gives me an emboss effect

The matrix trick works by defining a color vector for elevation (0 elevation to 1 elevation) and another color vector for moisture (0 to 1), and then adding them for the actual elevation and moisture. Most color tables aren't linearly separable like this. I picked some colors for the four corners of the table, and then I tried to come up with some vectors that approximated those colors. They're pretty close, so I got lucky!

```    Color square from mapgen2
E=0 M=0 210 185 139  subtropical desert
E=1 M=0 201 210 155  temperate desert
E=0 M=1  68 136  85  tropical rain forest
E=1 M=1 153 170 119  taiga

Vectors on the four sides of the square
At M=0 E vector is 210   -9, 185 +25, 139 +16
At M=1 E vector is  68  +85, 136 +34,  85 +34
At E=0 M vector is 210 -142, 185 -49, 139 -54
At E=1 M vector is 201  -48, 210 -40, 155 -36

I can approximate this with
Base is      210  185  139
E vector is  +40  +30  +25
M vector is -100  -45  -45

Reconstructed values at the four corners of the square:
E=0 M=0 210 185 139 -- exact match, by definitions
E=1 M=0 250 215 164 -- too red?
E=0 M=1 110 140  94 -- too red?
E=1 M=1 150 170 119 -- just right

After plugging these initial values in, the colors seemed too
boring, so I tweaked the values in the matrix until I got
something I liked.
```

In GL, we could do this with a texture lookup instead. It gives us a lot more flexibility. You'd embed the Whittaker Diagram colors into a texture and then use u = elevation, v = moisture as the lookup coordinates. You can directly include water in the texture instead of the separate image I used for the SVG diagram.

If this kind of thing fascinates you, check out Toby Schachman's Shadershop and this libnoise tutorial.

Written 21 Nov 2014