Tesellation Shader with Noise

In an earlier post I used Directx11 tesellation shaders to generate a high frequency of landscape triangles within the shader, allowing my landscape tiles to generate much higher detail when close to the camera. Other than river surfaces I also mentioned that I hadn’t actually used the extra geometry density for anything yet.

Now I have.

Simply by sampling a perlin noise texture at two frequencies to add extra height within the tesellation shader I can generate a much more interesting landscape close up.


The various lumps and bumps in the foreground here are entirely generated using the tesellation shader and perlin noise. tess_noise2.jpg

In order to prevent obvious visual popping I generate a bump map from the perlin noise at design time, and sample that with the same frequency as the height undulation. I then combine that bump sample with the landscapes more basic normal map to generate a combined normal for light rendering.

Combining normals is not simply a matter of adding both together and renormlizing – this would give an average normal, not a combined normal. Luckily someone has already solved this for me. See here for the details http://blog.selfshadow.com/publications/blending-in-detail/

In order to maintain a good correspondance between close and distant lighting I make sure that I use a high tessellation factor when rendering my design-time “drapes” and normal maps for the distant landscape tiles. When I render them as a simple texture-with-normal map in the distance it looks like a high detail image – the darkening effect of the distant normals gives an illusion of a lot of height variance that doesnt actually exist in the geometry.

Even with the varying height generated from the noise samplers I still place the vegetation directly using a pre-calculated Y coordinate rather than rely on height map sampling in the shader. I just repeat the height undulation code written in HLSL within my C# design pipeline to get an accurate measurement of how high each tree will be at runtime. There are a couple of reasons for this.

  • Trees placed on a slope that use a heightmap to determine their distance from the ground will tend to “skew” in the horizontal plane – the front of the tree is further downhill than the back of the tree and every vertex is offset in the vertical plane based on how high off the ground it is. In the real world trees dont behave like that – they grow vertically without reference to the slope of the ground on either side.
  • Less texture lookups at runtime, traded off with an extra float passed in the Vertex instance stream. Given that the Vertex instance stream is a Matrix, this actually doesn’t cost me anything.

Video on YouTube here.




Trees, sparse foliage, rivers and paths

A quick video of all of the pieces put together. The landscape now uses a tesellation shader to generate higher levels of detail but I dont use those extra triangles at the moment other than on the river surface, which is animated from a height map. The sea doesn’t yet use a tessellation shader but a fixed concentric circle mesh which achieves the same result but with hard coding.

The trees and shrubbery are generated usign the same techniques, planted using a Voroni cell map. The textures over the landscape have been colour matched so they are not so obvious in transition – but I may have over-done this as it all looks the same basic colour now. Back to the drawing board on that.

Youtube Video