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.

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:

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