Advanced Terrain Texture Splatting

Published July 18, 2013 by Andrey Mishkinis, posted by AndreyMI
Do you see issues with this article? Let us know.
Advertisement
In this article I will explain a texture splatting algorithm which allows you to create more natural terrain. This algorithm may be used in shaders of 3D games as well as in 2D games. One of the most common ways of terrain texturing is blending multiple tiled layers. Each layer has an opacity map which defines the extent of texture presence on the terrain. The method works by applying an opacity map to the higher levels, revealing the layers underneath where the opacity map is partially or completely transparent. Opacity map is measured in percentage. Of course on each point of a terrain the sum of opacities of all layers makes one-hundred percent as the terrain can't be transparent. Instead of tile textures, the opacity map stretches entirely on all terrain and therefore has quite a low level of detail. Now we will pass to the most interesting part -- algorithms of blending of textures. For simplicity and obviousness our terrain will consist of sand and large cobble-stones. 1.jpg Simplest way of blending is to multiply texture color with opacity and then sum results. float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.rgb * a1 + texture2.rgb * a2; } Such a technique is used in Unity3D in the standard terrain editor. As you can see, the transition is smooth but unnatural. Stones look evenly soiled by sand, but in the real world it doesn't happen like that. Sand doesn't stick to stones, instead it falls down and fills cracks between them, leaving the tops of stones pure. Let's try to simulate this behavior in Excel plots. As we want sand to be "fallen down" between cobble-stones, for each texture we need the depth map. In this example we consider the depth map is generated from grayscaled image and stored in the alpha channel of a texture. In Unity3D it can be done in the texture inspector by setting the flag "Alpha From Grayscale". First of all we will consider the simplified model of depth map of sand and stones. 2.png The blue line on the plot symbolizes the depth map of sand and red is cobble-stones. Notice that tops of stones lie higher than sand level. Considering this fact, we will try to draw pixels of that texture which is above. float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a > texture2.a ? texture1.rgb : texture2.rgb; } 3.jpg Excellent! Tops of cobble-stones remain pure whereas sand lies in cracks between them. But we didn't consider layer opacity yet. To use it we just sum depth map and opacity map. float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a + a1 > texture2.a + a2 ? texture1.rgb : texture2.rgb; } At the expense of summation less transparent texture will be higher than usual. 4.png 5.jpg So we have a more natural transition from sand to stones. As you can see, grains of sand start filling cracks between cobble-stones, gradually hiding them. But as calculations happens pixel-by-pixel, artifacts begin to appear on the border between textures. To get a smooth result we will take several pixels in depth instead of one and blend 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 at first get part of a ground seen at a certain depth. 6.png And then we normalize it to get new opacities. 7.png 8.jpg As a result we found the algorithm of textures blending, which allows us to reach close to a natural terrain image. In summary I want to explain what this algorithm was developed for and how we use it. The shader was developed for turn-based strategic indie game Steam Squad. As engine and developing platform we use Unity3D. And as the Unity IDE is extremely flexible, we made our own level designer extension. In general the level designer is a simplified Unity3D terrain editor with some features of Titan Quest Editor. When you paint the texture on a terrain there is a recalculation of the opacity map corresponding to this texture. And as the sum of all opacities has to make 100%, the editor automatically normalizes opacity maps of other layers.
">Here is short YouTube video showing how it works
. Shader which uses this algorithm in Unity3D Asset Store
Cancel Save
1 Likes 17 Comments

Comments

Boruki

That's a really cool technique! It adds quite a lot visually for only a little work.

Thanks for sharing!

July 17, 2013 06:21 AM
MarkS_

This is one of those techniques that when seen, causes you to ask yourself: "Why hasn't anyone thought of this before?"

The bottom picture looks natural. This is very impressive!

July 17, 2013 06:32 PM
riuthamus

I think many people have, the issue is the draw call and the load times; which leads me to my question.

Doesnt the pixel shader run slower and cause considerable lag on a procedurally generated terrain setup?

This setup would work on solid, never changing terrain, but I think it would cause serious issues with terrain that was to change on a constant or semi constant basis. Each modification of the land would require another draw call, would it not?

Also, with our system we have been looking at doing this but we have 3 textures maps ( normal, specular, color ). Each one of these would need a new sample, this means 3 * 3 = 9 samples. We would have to blend this with another texture ( for the edges of the blocks/regions ) making a total of 18 samples.... is this correct?

July 17, 2013 08:53 PM
riuthamus

I have no clue why my post generated two down votes... as there was nothing negative about it. Oh well.... whatever!

July 18, 2013 01:18 AM
MarkS_

Seemed to me like you raised some valid points. O.o

July 18, 2013 01:59 AM
slicer4ever
I really like this technique, I'm defiantly going to keep it in mind for the future.
July 18, 2013 02:00 AM
riuthamus

I like it as well... i just want to understand how it could be used in a modular world rather than a static one.

July 18, 2013 02:02 AM
AndreyMI

Riuthamus, good questions!

Shader behaves exactly like default one. Of course, it has more math operations, but delay is absolutely insignificant. In the my implementation of shader I can blend 9 textures: 4 color maps + 4 normal maps + noise map. And with some math magic I still fit in SM2.0 limitations.

Also with some storage magic the changing of texture transparency isn't more difficult than moving point of a mesh. I can change it in realtime, but changing of set of textures is still expensive operation.

Sorry but I can't show you all sources because the shader is part of commercial project.

July 18, 2013 06:45 AM
James42

It would be helpful to people attempting to duplicate your results if the textures depicted above could be provided (or a modified version of them, such as with a text watermark).

July 18, 2013 07:07 PM
unbird
Nice. Especially the clarification with the Excel graphs. Congrats and thanks.
July 18, 2013 08:35 PM
Schrompf

You could get the same result by prefiltering the alpha map, avoiding all but one sample in the pixel shader. And if you employ some kind of relief shader, I suggest using the height map instead.

I employed this method to much success, but I didn't use a hard comparision but instead used a simple smoothstep() to blend between to two. Also works nice, but had the downside that the order of sequence is now important. It's always "one on top of the other". Which was fine for me as my terrain blending put one material per pass.

July 20, 2013 01:18 PM
benolds

Great effect, thanks for sharing!

July 22, 2013 01:23 AM
Carandiru
Awesome-sauce!!!
July 22, 2013 08:04 AM
Ben Bowen

This'd look nice with some sort of emboss-mapping like effect.

July 30, 2013 07:01 AM
Migi0027

Amazing!

Keep up the good work!

September 03, 2013 09:03 AM
AndreyMI

I implemented this technique in Unity3D. You can find shaders in Unity Asset Store and here is a demo.

September 13, 2013 10:59 AM
hupsilardee

Thanks Andrey, this technique is beyond fantastic!

June 23, 2014 09:12 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

In this article I will explain a texture splatting algorithm which allows you to create more natural terrain. This algorithm may be used in shaders of 3D games as well as in 2D games.

Advertisement

Other Tutorials by AndreyMI

AndreyMI has not posted any other tutorials. Encourage them to write more!
Advertisement