Thursday, August 17, 2017

Decorating the Ocean (Part Four)

A simple coastline embellishment is to darken the water around the coastline:
This is easily done by drawing a darker line around the coast and blurring it into the ocean, and creates subtle effect that helps create visual interest and a break between land and ocean.  It's sometimes seen combined with the horizontal lines embellishment:
The gradient and the shading lines reinforce each other, in a way very similar to the mountain shading used above.

Interestingly enough, this effect also looks pretty good if the water is lightened around the coastline:
This doesn't create as compelling a contrast between the land and the ocean, but it does suggest a surf line (or shallows) which is nice.

A variant of this embellishment is to turn the dark edge into a drop shadow by making it more distinct and offsetting it opposite the light direction:
This creates the impression that the land is floating above the ocean; not my favorite effect but it is dramatic and works well on certain sorts of maps.

This map demonstrates another lovely ocean decoration:
This is an Oriental-inspired map by Ilanthar at the Cartographer's Guild.   He has decorated the ocean in this map by overlaying it with a Japanese-inspired wave pattern.  It adds a lot of interest and character to the ocean.

In SVG, to overlay a pattern of some sort onto a graphic, you use a filter that composes the base image with the overlay image.  If the image is small, you can tile it using an feTile filter. The whole stack looks like this:
// Create a new filter
  // Bring in the overlay pattern
  // Tile the image to repeat over the whole area   
  // Blend the pattern into the background via "multiply"   
  <feBlend mode='multiply'>
You have to take some care when doing this to pick sizes that display and tile correctly.  Non-square patterns also offer some challenges.  If you're just using one pattern, you can work out the proper values and hard-code the solution, but if you're picking between multiple patterns it gets a bit tricky.

Here's an example of a map using a pattern on the ocean:
Keen-eyed observers may detect a tiny little problem:  There's a noticeable gap between the repeats of the pattern!  Bad programming?  No.  It turns out I have discovered yet another bug in Chrome. Perhaps not unsurprisingly, I seem to be testing the limits of what SVG can do in the browser and uncovering areas that no one else has explored.

The work-around (and it took me an embarrassingly long time to think of this) is to tile the pattern myself into an image bigger than my map size and then use that as the pattern.  This also has the advantage that it eliminates some of the fussing to make tiling work, although you are limited to the tiling that you create in the big pattern.  And obviously this can break if the map size gets bigger than the pattern, but for the moment is fine:
One unexpected hurdle for this decoration is finding good patterns.  The pattern that Ilanthar used in his original map and I re-used above can be found fairly easily on the Internet, but there's not a great deal of other usable patterns to be found.  (Even, so far as I can tell, in paid resources.)  Here's an example of another pattern:
Ilanthar has another map where he uses an ocean pattern; in this case it's a more of wave texture than a graphical pattern.  It also doesn't seem to tile perfectly, creating some artifacts.
Here's a quick attempt to re-use this pattern:
Some artifacts are visible here, as I haven't yet put a lot of effort into cleaning up this pattern.

There's a lot of flexibility with ocean patterns and probably some nice opportunities to create interesting effects.  For example, using the wave pattern above at a much smaller scale has the effect of creating a water texture rather than a graphical pattern:
And just to suggest more possibilities, this example map has an interesting approach:
It uses the horizontal lines decoration on the coast, but the rest of the sea is decorated with dots.  That could be easily done with a pattern.

Thursday, August 10, 2017

Decorating the Ocean (Part Three)

In the previous posts, I've described how Dragons Abound draws oceans and how it creates a common coastline embellishment where a series of parallel lines are drawn outward from the coastline:
In this post I'm going to describe how I've implemented another common embellishment.  Here's an example map that illustrates what I'm going to try to do:
In this map, the ocean is indicated by parallel horizontal lines that radiate a short ways from the land before trailing off.  These might have originated as more illustrative wave symbols, but now they're more graphic and stylized.  This example map is nicely hand-drawn and quite artistic.  A fair number of fantasy maps use this technique, but few of them do this nice job with it.

The straightforward approach to implementing this embellishment would be to walk along the coast and draw lines outward and some interval.  But there are a couple of problems with this approach.  First, you can see that the lines are at regular vertical intervals.  If you just step along the coast a certain distance, the lines will be closer together where the slope of the coast is shallow (i.e., close to flat).  Another problem occurs when the coast bends so that the lines from two parts of the shore meet, as happens on the example map near Dennies Point to the upper right.  You would need to make sure as you walk along the coast drawing lines that the lines you draw on the left side of this feature meet up with the lines you draw on the right side of this feature.  A final problem is that you sometimes have to draw lines that don't start from the shore at all, as happens on this map at each of the Points.

It's probably better to think of this embellishment as a pattern that is filling a buffer zone around the coastline.  After some thought, my approach to implementing this was to fill the entire ocean with parallel horizontal lines, and then mask away the parts that were away from the shore.  Let's see how that can be done.

To start with, I need to fill the ocean with the basic line pattern.  This is simply a matter of drawing a series of horizontal lines into the ocean layer of the map, like so:
All I've done here is fill the ocean with color and then draw lines on top.

The next step is to mask away the lines that aren't near the coasts.  However, as I mentioned in the previous post, the problem of "draw a line X pixels away from this polygon" is actually very difficult.  So I can't just expand the coastline and use that to cut off the lines.  Instead, I'll make use of the same trick I used in the last post -- drawing the coastline with a big pen.

To see how this will work, let's first visualize the desired mask.  Typically, a mask is just a black and white image that blocks drawing where it is black.  To start with, I can create a mask that is entirely black and use that to mask the ocean stripes.  This is the unsurprising result:
The mask blocks out all of the lines.  Now I want to modify the mask so that it shows the lines near the coast.  To do this, I want to paint the mask white in a swath around the coast.  How do I do that?  Remember how I used big pens on the coast to create the previous embellishment?
I'll do the same trick, only (1) I'll only draw one big white coastline, and (2) I'll draw into the mask instead of into the display.  The mask will then allow the stripes to show through wherever the big white pen drew:
And indeed, the stripes are now showing along the coastline.

This is too obviously mechanical, so let's working on making it more artistic.  To start with, I can vary the width of the mask so that the distance from the coast isn't always the same.
This effect is subtle, but you can see how the ocean stripes have shrunk in some areas and grown in others.

If you examine the example map above, you'll see that the stripes in that map don't all abruptly end but trail off or get spotty near the end.  Having the stripes trail off (get narrower) is not possible the way I'm doing this, but I can make the ends spotty and irregular.  What I'll do is apply a noise filter to the map to perturb the edges of the map.  A little blur helps too.
That's not quite the same as the hand-drawn version, but it does a lot to break up the artificial edge.

Another problem is that the lines are too regular.  We can start to address that by adding a slight variance to the spacing.
Now I'll add some variation of the line width as well.
Finally, I can add some jitter to the lines so that they aren't so straight.
And putting it all together:
I think the final results look pretty good.

Saturday, August 5, 2017

Decorating the Ocean (Part Two Revisited)

In Part Two of this series, I mentioned that my method for drawing repeated coastlines didn't work well with a mottled sea. The coastlines themselves are made of solid colors, creating a weird effect where they butted up against the mottled sea:
If you look at the peninsula in the right-middle, you can see that the colors in-between the coastlines seem to change as you go around the peninsula.  Actually, that color is staying the same, but it appears to change because the color next to it (the sea) is changing.  For this reason, this coastline embellishment doesn't always work well unless the sea is a flat color.

After posting this to /r/proceduralgeneration, /u/Azgarr suggested that I could use opacity to overcome this problem, by essentially making the areas in between the coastlines transparent so that the sea behind them shows through.  It turns out it isn't quite possible to do it that way, because the way these coastlines are drawn, making pens transparent just reveals the pen underneath, not the sea. But it is possible to get the same effect through careful masking of the pens.

The basic idea is to draw each pen and then mask away the portion where we want the sea to show through for a later pen. That's not too difficult to implement, although just for fun I made it a lot harder by over-generalizing the routine and also re-writing my "change luminance" routine at the same time:
You can see that now the changing sea color is visible underneath the coastlines.

However, there's an odd thing happening around the smaller islands:
It looks like the coastlines are getting clipped.  The problem is more obvious if I make the coastlines black and thicker:
It looks like the lines are getting clipped to a rectangular box a little bigger than the bounding box for the island.  This seems pretty strange, but I've seen something similar before, with SVG filters.

SVG filters have a specification for both an origin and a width and height to define the area of the filter.  This defines the area where the filter will be applied.  Normally a filter is attached to an SVG object, and by default the filter area is set to be bounding box for that object.   You might expect that the filter would then get applied to everything inside the box.  And it does.  For example, a blur filter would be applied to everything inside the box, and the resulting graphic would then be shown on the screen. But -- and this is a little non-intuitive -- the effect of the filter is also limited to the box.  For many filters this doesn't matter, but if you have something like a blur filter that might smear the object out beyond the edges of the box, that doesn't happen.  Instead the smear ends at the edge of the box:
That is an SVG circle with a blur applied.  You can see the straight edges of the filter limits.

The solution is to manually increase the size of the filter area.  And apparently the same is true for masks.  In the case of my map, the mask is getting clipped to the overall bounding box for coastline path of the islands.  Although I've used filters in other places in the program, they'd always been applied to the whole map, so I hadn't noticed this issue.

As with filters, the solution is to manually specify a bigger area of effect:
With that fixed, here's an example of another style:
One problem with this method occurs when adjacent coasts cause the coastline embellishments to overlap:
Since the embellishment lines are not completely opaque, when they cross each other they "stack up" and make a new color.  That's a little unartistic.  The impact can be minimized by keeping the outermost area very light, but I can't offhand think of any easy way to prevent the problem.

Despite that problem, I think the new approach is an improvement, so thanks again to /u/Azgarr for the suggestion!

Wednesday, August 2, 2017

Decorating the Ocean (Part Two)

In the previous posting, I started talking about how Dragons Abound draws oceans.  In this installment, I'm going to talk about how coastlines are drawn.

On the land side, coastlines are just lines around the edges of the landmasses, sometimes with some shading added to create a slight 3D effect:
On the ocean side, the base rendering just has the normal ocean coloring.

There are a number of techniques that artists use to embellish the ocean side of the coastline.  The most common technique is illustrated in this example from the previous posting:
The artists adds a series of areas around the coast in gradually darkening ocean colors.  These areas may (or may not) be outlined in a darker color.  Often the areas also get wider as they get darker and farther away from the coastline.

Creating this embellishment seems daunting.  Each succeeding line is an expanded version of the coastline, so at first glance, it looks like you need to repeatedly dilate (or expand) the coastline.  And expanding (or contracting) a polygon is a decidedly non-trivial problem.  It's complicated for convex polygons and worse for concave polygons.  There's also the nasty problem of intersecting polygons, as with islands near the shore.

Fortunately, there's an easier way to get this effect (at least in SVG).  The key idea is to repeatedly draw the coastline with different size "pens" (some very big!) and different colors, and overlap them to create this effect:
How this works may be more obvious if I turn off everything other than the coastline embellishment:
Here the coastline is drawn first in the darkest and biggest pen, then the next lightest and next smallest pen, and so on.  Slightly smaller and darker pens are interspersed to create the dark borders for each region.  It culminates in a narrow white line.  Half of this is then hidden underneath the rendering of the land.

As the pen gets bigger, the edge of the drawn area tends to naturally smooth out, but as you can see in the above animation, when you move a large circular pen along a path you tend to get a lot of regular circles.  That shows up on the map as smooth circular bumps, as in these areas:
That looks a bit mechanical.  To address this, I apply some smoothing to the bigger pens.  I have to be careful to keep the smoothing consistent between the main pen and the outline pen, and not to smooth near the coast (which would cause problems):
Taking a step back, then, this embellishment is created by drawing a sequence of coastlines from widest to smallest, varying the luminosities of the lines to create a series of gradually brighter regions separated by small darker lines.  Inside the program, I have an array of lines to draw -- for each line I have the width of the line, the color of the line, and how much to relax the path.

I'm using a pretty bright sequence of luminosities (I told you that routine would come in handy) for the coastal highlights, but of course this is adjustable.  Here's a map where I've made the decoration more subtle:
Here's a map with a common variant of this embellishment:
In this example, instead of varying the color of the sea between the embellishment lines, the sea is kept the same and the lines fade until they match the color of the sea.  This is just a different sequence of pens -- all the fat regions are given the color of the sea, and the thin regions are given progressively darker colors as they approach the shore.  So we can draw it exactly as we did the original embellishment, just using a different sequence of colors:
One drawback of this implementation is that if the sea has any kind of variable coloration (such as mottling) this will not be reproduced within the embellishment, because the embellishment is created by drawing an SVG path and those paths are a single color.  This map illustrates the problem:
You can see that the sea color seems to shift around the blob of land in the center-right of the map. Around 6 o'clock on the blob, the sea has been mottled to a lighter color, but the color in the embellishment doesn't change.  In general, it's best to use this style of embellishment on a map with a flat sea color.

Here's another interesting variant of this embellishment:
Here the mapmaker has repeated the coast lines until the entire sea was filled.  The endless repetition ends up creating a sort of texture in the sea area.  To do this in Dragons Abound I just need to add lots of  lines.
This looks subtly better if I vary the distance between the lines slightly.
I'm not sure I like this, but it's an interesting effect.

Finally, it's always fun for me to see how close Dragons Abound can get to my example maps, so here's a render using colors and line sizes (and some additional noise) to match the first example map, in a side-by-side comparison:
Not an exact match (and the example map has some lovely land details that I can't yet recreate) but I think the sea at least looks pretty close.

Next time I'll look at another common coastline decoration.

Monday, July 24, 2017

Decorating the Ocean (Part One)

Oceans can create large empty spaces in a map, so you often see embellishments added to create some visual interest and/or to break up the empty space.  For example, one of the things you'll often see on fantasy maps is some embellishment where the ocean meets the land.  Here's an example:
Here the map maker added a series of contours around the edge of the coast to suggest the ocean getting shallower inland.  In this series of postings I'll discuss various approaches that Dragons Abound uses to illustrate, decorate and label oceans and coastlines.

The default ocean rendering in Dragons Abound is to use a single flat color:
The only mildly interesting thing here is how Dragons Abound selects a color for the ocean.  I want to have a variety of possible ocean colors.  Initially I created an array of RGB color values that worked well as oceans and chose randomly from that array, but eventually I wanted a wider selection of colors.  I also found that the random ocean color often didn't work well with the random land color.

The key insight was to select randomly in the Hue - Saturation - Luminosity (HSL) color space rather than the Red - Green - Blue (RGB) color space.  The colors that work well for oceans are all in a single stretch of the hue space, from slightly green-blue (0.50) to slightly violet-blue (0.60).  And the clash between ocean and land colors is not a hue problem, but occurs when there is a mismatch between the Saturation or the Luminosity of the colors.  So by choosing randomly in the hue space of 0.50 to 0.60 and matching my Saturation and Luminosity appropriately to the land color, I end up with an ocean color that usually looks pretty good.

A flat ocean color is a little boring for a fantasy map, but it works well on something like a geopolitical map:

You'll notice that the example map at the top of this posting has a grain texture added to the ocean. This seems like a fairly simple embellishment, but SVG is a vector graphics format, and things like texture that are fairly straightforward in a raster-based format are more challenging in SVG.  You can get some texture effects using SVG's filter system, but it isn't simple to figure out. After some experimentation, I have this:
I'm not entirely happy with how it looks and so it continues to be a work in progress.

It's so difficult to find good information on SVG filters that it might be helpful if I mention a few resources I use.   Two tutorials I've looked at a lot are from Smashing Magazine and from Creative Bloq.  Neither of these has anything to do with maps, but both have a lot of interesting material and give you a good idea of the versatility of SVG filters.

Another good resource is Inkscape.  Inkscape is an open-source vector (SVG) graphical editor.  It includes a large number of filters, so it's often useful to take a look at the filters there and if you find something useful, look at the source of the filter to see how it is constructed.

Finally, there's filtered, an open-source SVG filter editor.  It allows you to compose a filter and see what it looks like on an image.  It's old and seems to be abandoned, but it still works fine for me and can be a quick way to try out different parameters, settings and compositions.

Moving on from the grain effect, the next embellishment I looked at was to mottle the ocean.  The idea here is to add some subtle texture to the ocean color.  (You can see some use of this in the example map at the top of this post.) This helps break up a large stretch of unrelieved color on the map and adds some visual interest.

This is fairly straightforward because I don't color the ocean as a single big polygon.  Instead, I color each of the world locations that make up the ocean individually and then apply a slight blur to merge them together.  So mottling is accomplished by coloring the individual locations differently.  Here's an example where I give each ocean polygon a slightly randomized color:
This is more interesting than the flat ocean, but overall not really that good.  Mottling works best when the effect is subtle (so that it doesn't distract from the map content) and not obviously patterned or random.  The above map uses random mottling that only changes the shade of the ocean color. This looks okay but obviously mechanical.

Here's a version using noise:
This isn't as obviously mechanical as the purely random mottling, but has a tendency to look like clouds, which can be distracting.  There's a lot of room for experimentation here, and much probably depends on your particular tastes.

I have also experimented with mottling by changing the hue instead of the shade.  For example, by making parts of the ocean greener or more purple.  That doesn't seem to work as well; or at least is difficult to do well for an arbitrary color.  Since the oceans on my maps can be a variety of shades from green-blue to purple-blue, I have not been able to get this working to my satisfaction, so it's not currently an option.

Another interesting embellishment is to indicate deep water by using a darker color and outlining the deep water areas.  This is a sort of "continental shelf" effect that shows where the open ocean starts:
Here you can see at the bottom middle the dotted darker area of the deep sea.  In ancient and medieval times, this would mark the area of dangerous sailing, away from the shallower and calmer shore waters.  I implement this by coloring the deep area a shade darker than the shallow area, but there are a few tricks to doing this well.

The first is figuring out the threshold depth for deep water: Where does "deep" start? One approach is to look at a bunch of maps and figure out a good typical depth value.  This has the advantage that you'll sometimes get a map with a lot of deep water and sometimes a map with no deep water, so you automatically get some variety.  The disadvantage is that you have no control over when deep water shows up, since it's a side-effect of the terrain generation.  An alternate approach is to randomly generate (or select) how much deep water should appear on the map, and then set the threshold depth accordingly.  So if you want about 30% of your ocean to be "deep water", then sort all the ocean depths and pick the one that is 30% from the bottom of the ocean to be the threshold for "deep water".

The second trick is to relax (smooth) the contour between the shallow water and the deep water.  The coast is an example of a depth contour (it separates the positive height land from the negative height land), and you can see that it is very wiggly and fractal.  The same level of detail doesn't look good as a water depth contour:
It's harder to map ocean depths than coastlines, so our eyes expect to see less detail in these sorts of contours.  The fix is to apply fairly heavy smoothing to the contour line before drawing it.

The third trick is to generate the color of the deep water by reducing the luminosity of the base ocean color.  This looks good, and it works well for any color, which lets me use random ocean colors without having to worry about the corresponding deep ocean color.  (As an aside, it turns out to be very useful to have a utility routine for changing the luminosity of a color.  The deep ocean here is the ocean color with less luminosity; the same thing is done for the darker shade around the edge of the forests.  You can do this by converting your standard Red-Green-Blue (RGB) color into a Hue-Saturation-Luminosity (HSL) color, reducing the luminosity, and then converting it back.)

An obvious extension of this deep water embellishment is to shade all of the water by depth, making the shallow areas lighter and the deep areas darker, essentially a depth map.  Here's an example of what that looks like:
(I'm showing more of the map here so that you can get a sense of the ocean depths.)

Interestingly, this looks a lot like the noise-based mottling.  If you know it's a depth chart then you can see it makes sense, but at a glance you'd probably just take it to be decorative.

When making the depth-based map I temporarily turned off the normal blurring of the ocean colors, and although the ocean above looks pretty smooth, if I zoom in far enough you can see the individual triangles that make up the ocean:
Finally, here's a map combining grain, mottling and ocean depths:
Next time I'll start talking about decorating the coastline.