Saturday, April 05, 2008

Terrain Precalculated Shading Techniques

After adding slope lighting and seeing how simple it was to make a terrain look better with no run time cost I decided to extend this method to more realistic looking shadow/shade.

Above is a non shaded, non shadowed terrain. This is the control image to which the next 2 results can be compared. In this normal method a height map is procedurally generated and the terrain texture is then created from this height map and a set of layer textures.

For slope lighting an extra step is added during the terrain texture generation.
For each vertex of the terrain, the neighbour vertex in a specified direction is checked. If it is higher than the current vertex shade is applied. This is a relatively fast technique. In a height map of 512x512 the number of comparisons is 262144.

Shadow texture generation is an extension of the slope shading technique. Instead of checking the immediate neighbour a ray is cast from the current vertex to a specified light position. For every step along the ray the height of the terrain at this point is checked, and if it is higher than the ray shadow is applied to the original vertex. (i.e. there is no direct line of light between the light source and the vertex). In my opinion this produces more realistic results and will combine well with shadow maps or shadow volumes but it is allot slower than the previous methods. To calculate the shade applied to each vertex in the shown 512x512 terrain 45556293 checks were required, which took 27 seconds.

This could probably be improved so that the terrain is checked at a lower resolution, with an approximate shade applied to the "in-between" vertices. This would allow the light source (probably the sun in an outdoor scene) to move.

Decade Blog is 1 year old today. 10% of the way through its life!


  1. Just wondering: are you doing real raycasting (based on the mesh), or do you calculate the shadows directly from the heightmap bitmap ?

  2. Hi Kris

    I do not do real ray casting. I move over the heightmap and interpolate the height for each step alog the way. Much easier and probably alot easier than checking for line, polygon intersections with the mesh.

  3. That's what I figured. :-)

    Nice results, btw!