Pure CSS contour terrain

This experiment shows how simple CSS transformations and transparent images can be leveraged to show and rotate a contour terrain generated from a height map in the browser with good performance. The following code pen contains a demo: Given a grayscale heightmap, I was originally going to turn each pixel into a cube, with each […]

This article was posted by Independent Software, a website and database application development company based in Maputo, Mozambique. Our website offers regular write-ups on technical and design issues, ranging from details at code level to 3D Studio Max rendering. Read more about Independent Software's philosophy, or get in touch with Independent Software.

This experiment shows how simple CSS transformations and transparent images can be leveraged to show and rotate a contour terrain generated from a height map in the browser with good performance.

The following code pen contains a demo:

See the Pen Pure CSS 3D Contour Terrain by Independent Software (@independent-software) on CodePen.1

Given a grayscale heightmap, I was originally going to turn each pixel into a cube, with each cube consisting of 5 <div>  elements (a top, and four sides). These cubes would then be stretched along the Z-axis to show a terrain:

Pure CSS 3D landscape result

However, in Firefox this approach did not work when the number of cubes surpassed 16 (see this post for an explanation) and in Chrome performance became unacceptable at around 256 cubes, or a 16×16 height map. Even showing only the tops of the cubes would quickly become too much. Clearly this technique could not be used for heightmaps of any usable size, i.e. at least 100×100.

I therefore took a different approach. If each layer of the height map were dynamically rendered into a transparent PNG, then I would need only as many divs as I have different height levels in my height map. For 64 levels (reasonable to obtain the effect I was looking for), this would thus yield only 64 div elements, each div containing a slice of the terrain.

Taking this sample 256×256 heightmap with grayscale values 0-63 as input for a small PHP script:

Sample heightmap

The first image is colored only where the heightmap has grayscale value 0, the second image is colored only where the heightmap has grayscale value 1, and so on. A second image is then used to determine which colors to use to color the final PNGs:

Sample color map

The resulting 64 slices set as base-64 encoded backgrounds of div  elements placed in a single container element, and each slice is translated along the Z-axis by a small amount. Slice 0 is not translated at all, while slice 63 is translated to the height of the final terrain:

Final contour terrain

It turns out that the performance of this approach is quite good. The PNGs add up to a total of about 400 kB, and can be generated beforehand for speed (i.e. the PHP code is not part of the final project). With animations added that zoom and rotate the terrain, this has the potential to become part of something bigger.

Save

Save

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">