Sponsored By

WebGL Terrain Rendering in Trigger Rally - Part 3

Rendering large, detailed terrains efficiently is an Interesting Problem in computer graphics and games. Doing it with WebGL makes it even more interesting.

Jasmine Kent, Blogger

September 12, 2013

3 Min Read
Game Developer logo in a gray background | Game Developer

Previously in this series:

This time we'll look at how the terrain height data is stored and processed!

Trigger Rally terrain screenshot

Trigger Rally’s primary source of terrain height data, forming the overall shape of the mountains, is real satellite data from the Engelberg region of the Swiss Alps. A big thank you to Jonathan de Ferranti of viewfinderpanoramas.org for permission to use his Digital Elevation Map collection!

I wrote a tool to convert the data into a tileable 1024x1024 16 bit image. The low 8 bits are stored in the red channel and the high 8 bits in the green. Here it is, with the green channel amplified for illustration:

Primary height map

At load time, the game transforms this into a single channel 32 bit float texture. It then draws the racing track spline (which is different for each track) onto this image.

The height data is sampled in arc seconds, which corresponds to about 21m by 30m at Alpine latitudes. I’ve scaled down the mountains in the game by a factor of about 3, so each pixel of the primary height map is 7.5m by 10.8m.

This resolution is fine for the mountains and just about enough for the track, but it’s not enough to be smooth to drive on, nor is it visually interesting in the foreground.

Keeping it smooth

The first thing to do is smoothly interpolate the height map. Linear filtering is usually smooth enough for images, but for geometry we really need higher order continuity. There are various options here, but I went with Catmull-Rom interpolation.

So far we have something like this:

Terrain with no detail

Adding more detail

Now we need to add some higher-resolution detail to make the terrain more interesting and plausible. For this I use a 512x512 8 bit map with height in the blue channel, and height derivatives in red and green:

Detail map

Sampling this detail map at 1 pixel per vertex at the highest terrain resolution and adding it to the primary height makes things look a whole lot better:

Terrain with detail

The detail map is modulated by the terrain gradient and by proximity to the track spline. This makes steep areas bumpier, and valleys smoother. It also keeps the track (where you have to drive!) nice and smooth, although this is configurable per track spline segment in the editor.

Surface map

The shaders need some extra information about the terrain, which I store in a "surface" map:

Surface map

  • R: d(height)/dx

  • G: d(height)/dy

  • B: surface type (dirt or grass/rock)

  • A: detail multiplier (determined by gradient and track proximity)

Tune in next time

In the next post I’ll show you how the surface shading works. If you can't wait, you can peek at the GLSL shaders in all their messy glory here on GitHub!

@jareiko

Read more about:

Featured Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like