Texture shading your hillshade

Texture shading your hillshade

These guys do amazing things creating maps - John M. Nelson, Stephen "Mapsmith", Craig Taylor, Daniel Huffman - and their maps, visualisations and images are inspiring. A tweet by Terry Stigers pointed me at the work of Leland Brown and his texture shading algorithms.

Texture Shading

I do like a nice shaded relief map. Wouldn't it be nice to be able to use those in your desktop GIS of choice and make your hill-shaded backdrops even nicer?

Well, you can. The source code and some pre-built binaries for Windows and Mac OS X are available. As I don't have a Windows or Mac OS X machine and use Linux (Mint) I need the source code. Head over to the texture shading repository on box.com and look in the Software folder. Download the Source_Code folder in its entirety and save the zip file somewhere. Extract it. Read the User Guide.

The user guide gives clear instructions on how to compile the code into something usable. To compile the source code into the texture and texture_image executables you need to have a GCC compiler installed on your Linux box. Install it if you don't:

sudo aptitude install build-essential

This will install the necessary bits - gcc, g++ and make.

I found the compiler commands in the User Guide failed with "undefined references to sin/cos/pow/sqrt" and other errors.

Try the commands in the User Guide - they may work for you. I had to append a -lm to each command. This worked on my Linux Mint. Run the following commands in the directory where you extracted the source code

gcc -O2 -funroll-loops -DNOMAIN -c *.c -lm
gcc –O2 –funroll-loops *.o texture.c -o texture -lm
gcc –O2 –funroll-loops *.o texture_image.c -o texture_image -lm

The first command creates a bunch of files with .o at the end. The second and third commands use these new files to build the texture and texture_image files that we'll use to generate our textured shading. Once the commands have completed successfully you'll have two new files: texture and texture_image. Run each command without any arguments to print out the basic help information for each one.

$ ./texture
Terrain texture shading program - version 1.3.1, built Oct  6 2016

USAGE:    texture detail elev_file texture_file [-options ...]
Examples: texture 0.5 rainier_elev.flt rainier_tex.flt
      texture 1/2 rainier_elev rainier_tex
      texture 2/3 rainier_elev rainier_tex -mercator -32.5 45

Normal range for detail is 0.0 to 2.0.
Typical values are 1/2 and 2/3.
(Either decimal or fraction is accepted.)

Requires both .flt and .hdr files as input  (e.g., rainier_elev.flt and rainier_elev.hdr).
Writes   both .flt and .hdr files as output (e.g., rainier_tex.flt  and rainier_tex.hdr).
Also reads & writes optional .prj file if present (e.g., elev.prj to tex.prj).
Input and output filenames must not be the same.
NOTE: Output files will be overwritten if they already exist.

Available option:
-mercator lat1 lat2    input is in normal Mercator projection (not UTM)
Values lat1 and lat2 must be in decimal degrees.

Right, you've got some working commands now. Give it a go. Here are my steps in quickfire mode: I downloaded some Terrain 50, a 50m DEM available as open data from Ordnance Survey. I picked the NN tile as it has Ben Nevis and some other fantastic mountains and used QGIS to built a VRT from all the ASCII grid files*.

Terrain 50 NN tile

I created a hill-shaded image in QGIS using the NN tile.

From QGIS I exported this as both a RAW and a RENDERED GeoTiff (EPSG:27700). I then used gdal_translate to convert to GridFloat format:

gdal_translate -of EHdr -ot Float32 nn_t50.tif nn_t50.flt

I found the texture commands didn't like the files created from the QGIS rendered GeoTiff as they were multi-band so use the RAW GeoTiff.

Using the ./texture command I created the first texture shaded image as a .flt file. Then using the ./texture_image command I exported the results as a texture shaded GeoTiff.

Load the texture shade into QGIS, add your hill-shade and coloured DEM. Play around with blend modes and transparency until you get something that works for you.

Hill shade and texture shade
Hill shade and texture shaded multiply blended

Add some tinting by blending in the 50% transparent DEM

No transparency just multiply blended

Did I mention reading the User Guide? It has a heap of tips on how to get the best out of your DEM. I created a matrix of detail parameters and contrast levels to see what effect they had. Another post maybe.

texture detail | texture contrast
0.25 | -2 -1 0 1 2 3 4 5
0.33 | -2 -1 0 1 2 3 4 5
0.50 | -2 -1 0 1 2 3 4 5
0.66 | -2 -1 0 1 2 3 4 5
0.75 | -2 -1 0 1 2 3 4 5

* Creating a VRT from the ASCII grid files and converting to GeoTiff introduces grid artifacts that can be seen in some of my images. See here and here for ways around it. I found that converting the ASCII grid files to GeoTiff with gdal_translate and then warping them into a single mosaic with gdalwarp (set "-r average" instead of default "near" and "--config GDAL_CACHEMAX 7000" to speed things up) worked. Hillshades created with SAGA, GRASS and QGIS had none of the stepping/terracing artifacts present. You might also get different results trying the default Horn and alternative ZevernbergenThorne algorithms.