Mixing terrain textures

  • Tutorial

In this article I will talk about the texture mixing algorithm, which allows you to bring the appearance of the landscape closer to natural. This algorithm can easily be used both in 3D game shaders and in 2D games.

The article is intended for beginner game developers.

One of the most common ways to landscape textures is to mix textures of several layers. These layers are superimposed on each other, thereby forming the appearance of the landscape. In addition, each layer additionally has a transparency map, which determines the degree of texture presence on the landscape. It is measured as a percentage. Naturally, at each point in the landscape, the sum of the degrees of transparency for all layers is one hundred percent, since the landscape cannot be transparent. Unlike tile textures, the transparency map is stretched entirely over the entire landscape and therefore has a fairly low level of detail.

Now let's move on to the most interesting - texture mixing algorithms. For simplicity and visibility, our landscape will consist of sand turning into large cobblestones.

The easiest way to mix is ​​to multiply the texture color and transparency, and add up the results.
float3 blend(float4 texture1, float a1, float4 texture2, float a2)
	return texture1.rgb * a1 + texture2.rgb * a2;

This is the technique used in Unity 3D in the standard landscape editor. A smooth, but unnatural transition immediately catches your eye. The stones look evenly soiled with sand, but this does not happen in reality. The sand does not stick to the stones; on the contrary, it crumbles and fills the gaps between them, leaving the tops of the stones cleaner.

Let's try to simulate this situation in the most ordinary Excel with its tables and graphs. Since we want the sand to “fall through” between the cobblestones, for each texture we need a map of its depth. In this example, I generated it from the texture itself in shades of gray and placed it in the alpha channel.

First of all, we will consider a simplified model of a map of the depths of sand and stones.

The blue line symbolically indicates a map of the heights of sand, and the red line shows cobblestones. You can notice that the tops of the cobblestones protrude above the level of sand. Given this fact, let's try to display the pixels of the texture that is higher.
float3 blend(float4 texture1, float a1, float4 texture2, float a2)
	return texture1.a > texture2.a ? texture1.rgb : texture2.rgb;

Fine! The tops of the stones remain clean, while the sand seems to crumble in the gap between them. But we have not yet taken into account the degree of transparency of the layers. To do this, we simply add a height map with a transparency map.
float3 blend(float4 texture1, float a1, float4 texture2, float a2)
	return texture1.a + a1 > texture2.a + a2 ? texture1.rgb : texture2.rgb;

By summing, the less transparent texture will be higher than usual.

So we got a more natural transition from sand to stones. It is seen how grains of sand begin to fill the gaps between the cobblestones, gradually hiding them behind them. But since the rendering occurs pixel by pixel, artifacts began to appear on the border between the textures. In order to smooth them somehow, we will take not one, but several pixels in depth and mix them.
float3 blend(float4 texture1, float a1, float4 texture2, float a2)
	float depth = 0.2;
	float ma = max(texture1.a + a1, texture2.a + a2) - depth;
	float b1 = max(texture1.a + a1 - ma, 0);
	float b2 = max(texture2.a + a2 - ma, 0);
	return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2);

In the code above, we first highlight a portion of the relief visible at a certain depth.

And then we normalize it in order to get new degrees of transparency.

As a result, we got a texture mixing mechanism that gives a result close to the natural look of the landscape.

In conclusion, I want to talk about why this algorithm was developed and how we use it.

The shader was developed for the indie game Steam Squad in the genre of isometric 2D strategy. As a development framework, we use Unity 3D. And since the Unity development environment is extremely flexible, we made our extension - a level editor. By and large, the editor is a simplified copy of the standard landscape editor with elements taken from the game editor Titan Quest.

When drawing with a texture over the landscape, the corresponding transparency map is recalculated. And since the sum of all degrees of transparency should be 100%, the transparency maps of all other layers are normalized. You can see how it looks in the editor on a short video.

Also popular now: