Hills that look like hills

Progress report: Hills now look quite a bit more like hills.

As mentioned previously, the hills were looking pretty awful – even a 2048×2048 texture, when stretched over miles of landscape, has pixels larger than a house. Instead of using such a texture directly, it makes more sense to tile a smaller texture repeatedly over the landscape. To add variation, one can use a landscape-wide single-channel image to blend between two different textures.  As it happens, the author of the height field I’m using for the hills (virtual-lands-3d.com) provided the hill model with a map named “flows” and a map named “rough” which seemed to correspond to fertile areas and rocky areas. After a little tweaking of their levels, I merged them into a two channel texture.

Two channel blending map

Which I'm also considering just hanging somewhere because it looks cool

This technique pretty much solved the problems with variation in the distance, but then so could the “one big texture” approach if I didn’t care about problems up-close. The problem being that “half dirt, half grass” under this scheme means you get a semitransparent layer of grass everywhere.

Grey-brown hills with green streaksDirt overlaid with a transparent layer of grass

Applying a threshold to the value doesn’t help much either, since the low variation rate just means you get a mile of grass, followed by a crisp cutoff into a mile of dirt. One solution to this is to overlay a medium-scale noise over the blending value, but I found that while that did add variation, the tiling became too obvious in the medium distance and the cutoffs close to the camera were still too stark. A better approach turned out to be embedding a gradient in the alpha channel of one of the tiling images, and comparing that to the blend value. In this way it’s possible to paint dark areas around the cracks in the dirt texture, so low key values only display grass there, while brighter values represent areas where grass will only grow if the terrain is very grassy.

Near detail with cutoff. Note this is where my art skills fail me, a better cutoff texture would keep any given grass blade a solid colour, and to be correct there should be an equal amount of each shade of grey in the image so that a cutoff at a certain percentage will give exactly that percentage of coverage. Mine has far too many solid whites but gave decent results for this scene.

The problem with cutoffs, though is that they become meaningless in the distance. Only a handful of metres out from the camera, the cutoff texture has begun to blur down towards middle-grey. The solution to this is simply to use a soft threshold that gets progressively softer as the distance gets higher. Even the grass in the foreground benefits from a little softening.

Hills with an inappropriate cutoff, one large solid grass area followed by a large dirt area

The distance with a hard cutoff

Hills with more appropriate blending. Hard cutoffs in foreground blend into soft mixtures in the distance

The distance with a linear soft cutoff

What next?

There are still a few things I’d like to do with the landscape shader. Currently it’s quite wasteful to sample the high-detail textures all the way out in the distance where they’ve blurred into a solid colour. If I were to create a proper heightfield-based landscape system rather than just building the model by hand, it would be quite easy to tweak where to switch to a less expensive shader.

In a similar vein, it would be nice to support normal maps on the near detail textures. One thing I didn’t mention above is that the hill model is a little too low-poly in the distance and doesn’t light very well, so rather that using its vertex normals I converted the original heightfield into a normal map and used those. If I were switching to a system that had a different shader and more-tessellated geometry in the foreground, the cost of generating tangent space vectors could be paid once when the high-detail geometry is created.

Finally, it would be nice if the hills actually cast shadows. Relying on realtime shadowing techniques would probably look terrible, since they tend toward crisp edges which would look strange on huge, soft features like hills. One solution would be to pre-bake a soft lighting solution into another channel of the blending texture, and merge that with any realtime shadows at render time.  If it were necessary to support the possibility of the sun direction changing, it would be better to create a shadow texture for them (probably via a large number of raycasts) when the program starts, and only update it if the sun moves. Either technique would need to balance softness against potential strangeness when a conventionally-shadowed object is standing in the penumbra casting its own crisp shadow, and it would be necessary to work out when and where non-hill objects could safely receive soft hill shadows. Given all these problems, I’m probably going to have to wait until I actually have shadow casting available for normal objects in the first place.

aaaso that a cutoff at a certain percentage will give exactly that percentage of coverage. Mine has far too many solid whites but gave decent results for this scene.

5 Responses to Hills that look like hills

  1. Sadly not. That would be nice wouldn’t it? It’s currently just a heap of free textures and heightfields, I’ve not even got to the point of making the engine turn the height data into a mesh, I’m just using it to make a big model offline.

  2. I think to do the fertility pattern, I’d actually want to something simulation-y to work out water paths, and then that leads to all sorts of thought about whether you need to do any other simulation to, I dunno, glaciate your valleys or something.

Leave a Reply