Texture Blending

Texture blending with multiple textures is dealt with in many tutorials, principally in Caitlin Zima’s series of guides here. An issue when using this technique is that is truly does blend two dissimilar textures together, essentially blurring one into the other as shown below.


This is unrealistic. A better approach is documented here . This approach does not blend the values of the pixels by combining their values and dividing by a blend factor, but uses the blend factor to select a pixel from one or the other underlying texture. This means for any one pixel the result comes from one or the other texture but not a blend of the two.

The result can be seen here


This gives a more realistic looking result close up, with either stones or grass showing. In the link to Andrey Mishkinis’ example he provides the renderer with a height map alongside the visible texture and samples the height map of the two textures – the highest pixel wins and gets painted. This requires some complexity (and artistry) in terms of providing extra textures just for determining height. In my example above I side-step the issue to get a slightly less accurate effect but one which does not require an extra texture sample or further artwork.

To get the effect of depth on the texture I simply convert them to grayscale and sample the result – the darkest pixel is deemed to be the deeper, and does not get rendered. Because the conversion to grayscale is arbitrary (I could have chosen the reddest pixel as an alternative) the pixel painted is a bit arbitrary but consistent.

The HLSL to do this is (where groundCoverage and appliqueTexture are the result of a tex2D sample of my two textures.)

// Grayscale

float groundCoverageGrayscale = dot(groundCoverage.rgb, float3(0.30, 0.59, 0.11));
float appliqueGrayscale = dot(appliqueTexture.rgb, float3(0.30, 0.59, 0.11));

// Apply applique in preference to ground cover
if (appliqueGrayscale > groundCoverageGrayscale)
textureColor = normalize(appliqueTexture);
bump = appliqueBump;
textureColor = normalize(groundCoverage);
bump = groundCoverageBump;


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s