Skip to main content

Ground 048

Ground 048 is a plain dirt scan that can be used as the base ground for nature scenes, as a filler material for the crevasses between paving stones or to build other, more complex materials. The aim with this material was to create a dirt material with no large gradients or other patterns that would make tiling difficult.


For this material I started by filling a shallow bowl with potting soil and flattened it out a little bit using a shovel. I then placed the camera on a tripod facing downwards and moved the bowl below it in a serpentine pattern. I recorded 370 images this way.


Initial processing in Metashape and xNormal

I imported these images into Metashape and processed them using Metashape and xNormal as if it was a normal scan (see Height Field Photogrammetry).

Taking a look at the raw texture from Metashape you can still see the edges of the bowl:

_EXPORT_Soil_Chunk 1_DETAILED_small

The full raw texture has a resolution of 24K x 24K which allows for a lot of detail:


The displacement map created by xNormal shows a some distortions around the edges but the usable area is large enough.


I then cropped both the color and displacement map and rotated them.

Further processing in Substance Designer

The final processing happened in Substance Designer. Here is the final graph (The image is very large, you can open it in a new tab):


To make this section easier to follow I’ll be going through the processing steps in the order in which they happen in the final graph and not necessarily in the order in which I added them because I iterated over several versions. Doing it like this makes it easier to follow.

Preparing the color map

The initial color map had a lot of very small white specs in it (presumably fertilizer since it’s potting soil?). When looking at the image from a greater distance these white spots created some unwanted noise.

Here is a close-up:


I then separated just these white spots using a “Color to Mask” node. Here is the mask:


This mask was then used to blend in a slightly offset version of the same image (and by that I just mean a few pixels). This replaces all the white spots with a fitting brown tone from same area, making the material a bit more uniform.


Preparing the displacement map

I gave a similar treatment to the displacement map. This time I separated all the highest (brightest) areas and used the mask as the input for a “Non Uniform Blur Grayscale” node in order to smooth out these peaks. The change is - admittedly - extremely subtle.







Tiling using the “Atlas Scatter” node


At this point I still only had a small non-seamless color- and displacement map. Just tiling them using an image editor would be time-consuming and would likely result in a recognizable seam. So I tried something different: Using an “Atlas Scatter” node. This node’s intended use is to scatter individual elements from a texture atlas (like a set of leaves) across a surface. If two elements intersect each other then the one with the higher elevation (brighter displacement map) will be shown. This means that leaves can partially cover each other based on their displacement map. But what if - instead of placing leaves onto a dirt ground - I use the node to place parts of the ground itself? This idea actually works pretty nicely, if you apply a few additional tricks.

To get started I multiplied the displacement map with a blurred square to create a “vignette” effect. This means that the height map tapers off towards the edge. This ensures that there can’t be a seam once the texture is randomly splattered across the surface.


The Atlas Scatter node requires an opacity map to work properly. For that purpose I just used the blurred square directly (after running it through a contrast node).


With this my “texture atlas” consisting of color, displacement and opacity map was completed:image-20210619114828871




I plugged the three maps into the Atlas Scatter node and used the following settings:

  • X-Amount: 3 / Y-Amount: 5
  • Scale: 1.75
  • Rotation Random: 1.0

And the color map already looked pretty good...


However, the displacement map still had a few issues. Since the displacement map has to taper of towards the edge there were now visible valleys across the map:


Fixing the displacement

To address the displacement issue I added a the blurred square that I had used to bring down the edges of the displacement map in the atlas and added it to the atlas itself. For this purpose I (mis-) used the metalness channel since it wasn’t being used in this project. With this technique I now had an additional map in the metalness channel that contained only the displacement artefacts.

image-20210619124005653By inverting this map and adding it back to the real displacement map I was able to counteract the initial distortion. I also added a subtle procedural noise on top. The resulting displacement map is much more uniform and easier to tile.


Final steps

At this point the material was pretty much finished.


I added the nodes for the normal map and created a roughness map based on a “Curvature Smooth” node with the normal map as the input. The roughness is just the inverted curvature map which works pretty good in this situation.

Ambient Occlusion

The AO is similarly simple: I literally just used SD’s built-in “Ambient Occlusion” node and gave it the displacement map as input.


I really like how this material turned out, however I think there are some ways to improve this approach. The most obvious one is to capture several different bowls of dirt to break up the pattern even more. Capturing different kinds of dirt/soil and mixing and merging them could also yield interesting results.