Blending Terrain Textures

One of the most common methods for texturing a height map terrain is with multiple tiling layers.  These texture layers are stacked on top of each other and blended together to create the final textured look. In addition to the tiling texture, each layer also has an opacity map which controls how much of the texture is blended in at any point on the terrain. Unlike the tiling texture this opacity map is stretched over the entire terrain and is therefore very low detail.

Textured Terrain in Titan Quest

In a simple example, our terrain could have two layers: sand and grass. Anywhere the opacity map for the grass layer was painted 1 (opaque) we would just see grass. Where the opacity map was 0 we would see sand, and where it was 0.5 we’d see a mix of sand and grass. Note that the bottom layer doesn’t have an opacity map since the base layer must appear everywhere. This blending operation for two textures is implemented like this:

float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
    return lerp(texture0, texture1, layerOpacity);
}

The problem with this basic technique is that alpha blending a grass texture with 50% opacity over a sand texture doesn’t really look very good when you look at a closely:

The blended result on the bottom resembles green sand more than a patch of sandy grass.  If the textures were more closely related this would work better, so this can be solved by adding additional artist crafted transition textures.  This however creates more work for the artists, and requires us to render an additional texture layer. Finally, for every combination of textures that we’re going to layer we’d need a different transition texture, and ultimately we might need several.

There is however what I consider to be a better an easier solution which we successfully used on Titan Quest. The idea is that instead of drawing 50% of each texture at every pixel, at 50% of the pixels we draw one texture and at the other 50% we draw the second. This is what it looks like when we do this:

To implement this, we store a mask in the alpha channel of each of the tiling textures. This mask uses the entire range of values and determines whether or not a texel will be displayed when the layer has a particular opacity. Specifically, a texel is displayed if the mask is less than the opacity value.  This new, splotchy blending technique is simply implemented like this:

float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
    if (texture1.a < layerOpacity)
    {
        return texture1;
    }
    else
    {
        return texture0;
    }
}

The result has a more natural look, and the splotching pattern can be tailored for each type of texture individually. While this grass texture uses a noisy pattern, textures with more structure — such as stones — could be setup so that the blending follows the structure.  With stones, that the alpha mask can be created with high values in the cracks and low values on the flat surfaces.  When this is blended on top of a grass texture, the grass will first appear only in the cracks as the layer opacity is increased.

Because this is a binary decision, the result has hard edges and suffers from aliasing.  It looks best if we smooth out the edges between the textures by doing a small amount of regular alpha blending between the textures. Here’s one way to implement it, although other methods can certainly be used (for Titan Quest we used a simpler method to fit within the instruction limits of ps1.0):

float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
 
    const float blendRange = 0.1;
 
    if (texture1.a < layerOpacity - blendRange)     
    {
         return texture1;
    }
    else if (texture1.a > layerOpacity + blendRange)
    {
        return texture0;
    }
    else
    {
        float f = (texture1.a - layerOpacity + blendRange) / (2 * blendRange);
        return lerp(texture1, texture0, f);
    }
}

Here’s what the final result looks like:

Although these examples show two textures, any number of layers can be blended this way, just like with the basic technique. This type of blending also isn’t limited to terrain textures, and interesting effects can be produced when the layer opacity is animated. For example,you can see the same type of blending at work in this prototype of dynamic infestation for Natural Selection 2:

18 Responses to “Blending Terrain Textures”

  1. Bramz said:

    May 14, 10 at 11:00 am

    Finally =)

    Nice trick you’re showing here. Discretisation of the ‘control texture’ after interpolation is great to keep different ‘regions’ from mixing too much. It’s simple but very effective. Keep them coming!

    Cheers,
    Bram

  2. Manu said:

    May 15, 10 at 3:06 am

    Very interesting, hope you’ll share other clever tricks with us.
    Good thing with this is, that you can use a really low-res interpolated texture as density input but details in the blending show up in the res of the detail texture. This also plays very nice with detailed specularmaps and bumpmaps.
    I already used a variation of this technique, but never found it described anywhere except in a recent paper on Rendering Grass that also uses something similar to guide the grass-density. Soft particles share the fate: around since ca. 2000 (I still have a copy of the old flipcode article on my hdd), but well known after there was a nvidia white paper in 2007.

  3. marco said:

    May 19, 10 at 12:39 am

    Nice technique, love the detailled description!

  4. Elmigo said:

    Jun 21, 10 at 2:57 am

    Greate tutorial!
    in near future will make variant map class with this technique

    Thanks from Russia!

  5. Dlinna said:

    Jul 20, 10 at 1:01 am

    Hey, nice article.
    But I’ve a little question – what about the size of the blending texture? Let’s say we have a big field – and want to texture it using this technique. So what are the possible ways to solve the problem with the resolution of the blending texture. We can, for example, repeat out texture and, perhaps, also mirror it – but it will look unnaturally (because of repeating the same pattern) especially when looking not from close distance.

  6. Real-Time Rendering · Clearing the Queue (a little) said:

    Sep 08, 10 at 7:30 pm

    [...] Blending Terrain Textures is a nice little article on just that. Lerping bad, thresholding good. [...]

  7. Eric Chadwick said:

    Sep 13, 10 at 2:46 pm

    Stumbled across your blog today, great reading!

    Playing with the Titan Quest editor, it seems to use vertex alpha for the artist-painted opacity map, rather than an actual bitmap. Maybe vertex alpha was just a way for you to generate the bitmap you needed, because it’s easier for the level designers to “paint” vert colors in realtime?

  8. Eric Chadwick said:

    Sep 13, 10 at 3:17 pm

    A couple other examples of the same basic technique:

    Unreal:
    http://www.youtube.com/watch?v=LI4ZHVDuiKo

    Source:
    http://developer.valvesoftware.com/wiki/$blendmodulatetexture

  9. Max said:

    Sep 18, 10 at 1:14 am

    We used textures for the opacity in Titan Quest. They are very low resolution though; if I remember correctly they were about one texel per square meter.

  10. 暗黑3渲染技术分析-地表 « fseraph's space said:

    Oct 06, 11 at 6:01 pm

    [...] 地表混合采用的也是比较传统的方法,这个图是从Titan的主程网站上取来用的,原文在这里:http://www.m4x0r.com/blog/2010/05/blending-terrain-textures/ [...]

  11. rhmznuhsenxq said:

    Aug 07, 12 at 12:35 am

    dinkeDvyHFaZksRiNiF Christian Louboutin Outlet upgareHESeW

  12. N/A said:

    Dec 06, 12 at 2:08 pm

    Great delivery. Sound arguments. Keep up the amazing spirit.

  13. when can i download the fifa 13 demo said:

    Apr 19, 13 at 11:58 am

    This is likely because of the sheer to get down
    thinking draught strategies. The statistical data that they render can serve
    you

  14. cheap nfl jerseys said:

    Jun 08, 13 at 5:17 am

    This is a topic that is near to my heart.
    .. Cheers! Where are your contact details though?

  15. buy proxies said:

    Jul 25, 13 at 11:23 am

    you’re really a excellent webmaster. The website loading velocity is incredible. It seems that you’re doing any distinctive trick.
    Also, The contents are masterwork. you have performed a magnificent
    activity on this topic!

  16. dragreers said:

    Aug 02, 13 at 11:38 am

  17. dragreers said:

    Aug 02, 13 at 12:29 pm

    The Chariot Cougar 1 is the equal seater type of the most popular daughter trailer in the Chariot lineup. It sits in the midway of the Play series between the less costly Cheetah, and flagship CX models, striking a up between features, outlay and weight.
    The Cougar 1 is the in any event trailer as the Cougar 2 individually from the tons of seats, so exchange for a Chariot Cougar 1 study please see the Chariot Cougar 2 review.
    https://www.zotero.org/ganerzbasin Highlights include hold-up that is adjustable to the weight of your children, a sheerest comfortable inner with side foot in the door draught vents and small items safe keeping, five conversion kits to maximise the inject you can contract from your trailer, fold-down storage and superior cover features, including piles of meditative and photo-luminescent materials all around.
    The Cougar 1 is the same trailer as the Cougar 2 separately from the number of seats, so for a Chariot Cougar 1 study divert see the Chariot Cougar 2 review.
    Chariot Cougar 1

  18. PPZOJTX said:

    Aug 02, 13 at 12:35 pm

    http://buylasix.carbonmade.com/#6640 where do i buy lasix – lasix furosemide order


Leave a Reply