Check out a tutorial by Dassan Verstrepen on creating material of mud using Substance Designer.
In case you missed it
You may find these articles interesting
My name is Dassan, I’m from the US and I studied game development at the University of Utah. I’ve been lucky enough to work with some awesome teams like Dekogon and Kitbash3D, and I just quit my job in IT to pursue material art full time!
Getting Into Substance Designer
During school, I took a course in Environment Art and had the opportunity to try SD. I had some basic familiarity with digital art but SD’s workflow really blew my mind. I fell in love with how quick and dynamic the software was, and got obsessed with the puzzle-like challenge of creating procedural materials. It’s been about 3 years since and I’m still enjoying it.
Mineral Mud Project
I try to pick projects that are challenging, but I also look for subjects with a general utility that I can reuse and improve over time. When looking through mud references I noticed some interesting patterns that I hadn’t tried before, and that inspired me to start this material. On the utility side, it was an opportunity to improve the crack structure from a previous material I had created.
I enjoy natural materials because they pose questions about their environment and context. In many cases, thinking about the geography and climate of a material can give clues for replicating it. Typically I start with a few references that have a clear contextual focus, like similar patterns, color, roughness, lighting, etc. Once my material matches very closely, I’ll start to exaggerate different elements and seek additional references if I’m at a loss for ideas. For this material, the main reference was from Utah’s salt flats, but I gathered additional references from hot springs for the colorful banding.
Setting Up Cracks
I like to start my graphs by creating a simple pattern to drive the blending of all the different elements. Here I used a Gradient Linear to create a horizontal channel, matching my reference where water had pooled along the roadside.
The next step is to create a base pattern for the cracks, but before moving forward I’d like to look at this simplified example. My final approach is more developed than this, but the idea is the same. The key is the use of Flood Fill to Grayscale, remapping each size of Voronoi pattern to the shapes of the smallest pattern. The advantage of this is that all sizes maintain perfect positioning relative to each other because they are all built from the same small pieces. Tweaks to the small pattern carry over to the larger patterns as well. At the same time, all patterns have separate parameters for independent control.
Here is an overview of the crack structure of my mud material. To speed up my workflow I use a few simple custom nodes from my toolkit. Most of them are just simple presets for default SD nodes and are named accordingly (DV_Bevel, for example). The DV_Voronoi Sampler node is a slightly modified Tile Sampler with a Distance Node built in to create a Voronoi pattern. The DV_FF node is just a container for all the Flood Fill nodes, also with a Distance node built-in. Hopefully this clears up any confusion for those following the graph.
I start with a medium Voronoi pattern (X, Y Amount of ~8), using the height driver as a mask input to get larger shapes on the higher, drier areas. Then I use an Edge Detect with the Edge Roundness parameter to remove smaller shapes and run that through a FF/Distance node to recreate the Voronoi pattern with a more natural look.
From here I used Edge Detect on the FF to Index output. I use FF to Index because Random Grayscale sometimes isn’t random enough, and the Edge Detect fails to identify every shape because adjacent shapes will randomly have the same value. FF to index typically only fails if you have too many shapes, such that the index cannot give every shape a unique value within the grayscale color space. This outputs to a Bevel with negative distance, to be used as a Vector Map for the small crack pattern. I also output a FF to Random Grayscale for the medium pattern, to be used as the grayscale input later.
The small pattern is made with a second Voronoi Sampler. Using the Vector Map Displacement parameter, the positions of the small shapes are driven by the Bevel from the medium pattern. In addition, I blend both small and medium Voronoi patterns together. These steps ensure the small pattern will generally match the medium pattern in shape and positioning. As before, I use Edge Detect and FF to remove unwanted smaller cells and reshape the pattern slightly.
The small Voronoi pattern drives all the crack patterns for the rest of the graph, so it’s important that the shape gets defined at this stage. I used large, medium, and small warp effects, driven by tiled polygon shapes to get a jagged look. You can do quite a lot of look development at this stage, but the goal here is just to get some edge breakup in the small pattern.
After warping the small pattern, all other crack patterns can be finalized. As with the example earlier, I use FF to Grayscale on the small pattern, using the medium Voronoi for the grayscale input.
This is repeated using a third Voronoi Sampler for the large pattern. At this point, all three sizes share the same edges as the small pattern, but all have their own Sampler inputs, Edge Detects and Bevels (DV_Edge_Detect combines edge detect and bevel into one node in my graph).
The medium pattern outputs to a Non-Uniform Dir. Warp, which uses the random grayscale values as a Warp Angle Input. This pinches the edges together in random directions, so each edge has a different width. I consider this the “start” of the Height Map.
There are definitely always peculiarities to organic materials. Natural phenomena are very complex and unique, and sometimes there are relatively small features that are crucial to the context and logic of the material. In the case of this mud, there were a few things that were tricky because of how they interacted with each other. I wanted the mud cracks to terminate randomly, and to curl upwards based on their thickness. In addition, I wanted some cracks to remain connected, regardless of whether they were curling upwards or not.
I started with terminating cracks randomly so that the crack thickness would affect the curling feature when it is created further down the graph. I handled termination by adding a pattern of cone shapes to the beveled medium crack map. Where the added values are highest, the cracks will clip and disappear. Because both the cracks and the added maps have smooth bevels, they taper off smoothly where they terminate. The medium and large maps are added together to keep the large crack pattern from crossing through the medium cells. I also added the height driver to terminate where the high ground will be.
At this point, I included a pattern to get random connected bits. This feature could be handled in a variety of ways, but I found the look I wanted with a Non-Uniform Dir. Warp. I used a Gaussian Noise for the input, the original medium crack pattern as the intensity, and the small Voronoi pattern for the angle input. This warps the noise in random directions up to the edges of the medium cracks. To incorporate this into the height I used the screen blend mode, which retains a slight amount of the crack bevel in the connected bits.
For the curling slope of the cracks I created a mask from the crack final output, just after the termination step, but before the connected bits. The crack mask is Beveled, then inverted and adjusted with a Curve. Next, multiple Non-Uniform Blurs are used to create a smooth bowl shape between the cracks. If the intensity on these nodes is too high they will introduce artifacts, so I use multiple in a row to get the shapes smoother. At this point, all the cracks curve up the same amount, and for some of the smaller cracks, the slope is very steep. I adjusted the aggressive slope by multiplying the curling cracks with a blurred version of themselves.
Next, the curling cracks get a Slope Blur with a negative intensity. This pinches them based on their own slope and makes sure they terminate cleanly at their highest point.
The final adjustment is to Non-Uniform Blur the curling cracks using a mask from the connected bits. The mask is created with a subtractive blend, which outputs the difference in the Height Map from before vs after the connected bits are added. This step prevents any seam from the curved cracks showing in the Height Map.
TL;DR: This step can be avoided by including the connected bits in the crack mask before the curling. The drawback of that approach is that any connected spots will be excluded from the curling and will have no slope. The connected bits could be added after the curling instead, but I never found a solution to blend them that didn’t ruin the curling shape or require a careful mask. As with everything in SD, one thing can be done in many ways and this Non-Uniform Blur step was the tradeoff that I settled on. I hope to return to this problem again sometime, as this is definitely a workflow that could be improved.
With all those features implemented, the final step for the cracks is to blend the small pattern for some light surface detail. I made three variations of the small crack pattern, and each is applied to a different area using the height driver and other masks. The effect here is subtle, but all three variations of the small cracks can be seen in this gif showing every main height blend so far. At this point, there’s nothing left for the height but a bit of surface noise.
I think the last noteworthy thing to talk about is the Albedo Map. For this material, I used Ben Wilson’s Color Variation and Average nodes. This is an amazing workflow, and there is a brilliant presentation out there where Ben explains how these nodes were created. The Color Variation node can basically be thought of as a controllable, randomizable Gradient Map.
In my case, the Color Variation node is taking a blend of the height, curvature smooth, surface noise, small and medium crack maps, and outputting a color map that’s equivalent to a 5 key gradient map.
I used this node to quickly iterate on different looks for the material as a whole. It’s also very useful for getting random color throughout the material by blending saturated variants with a soft light blend mode. When needed, you can replicate the result very quickly with a gradient map for more control.
That’s all the tips I have for this graph! For a closer look at the full graph here’s the high res screenshot. I’m sure there are many ways to improve my workflow and I’m always grateful for any feedback. I also love to rant about relatively arbitrary choices in workflow and art in general, so feel free to reach out with any questions!
Like many others, I render in Marmoset Toolbag, which has a great balance of quality and usability. I start by picking an HDRI that matches the color tone and light intensity I’m looking for. I tend to love dramatic, high-contrast lighting, so sunset/sunrise images are usually a safe choice. From there I adjust the skylight intensity till the material is lit at a similar brightness to the shadows in the HDRI. When in doubt, color picking the scene and comparing it to references is a great sanity check!
Next I add a single directional light. To keep shadows consistent with ambient lighting, the directional light’s position and angle should match the main light source in the HDRI scene. I adjust the intensity till the brightest spot in the scene appears to be near clipping, but not quite. This gives a good contrast between light and shadow while allowing room for adjustments in post. Lastly, I turn on GI and AO for the extra ambient light, color, and shadow depth.
Like many others, I started with Daniel Thiger’s SD fundamentals tutorial series, which covers everything necessary to start making materials on your own. Wes McDermott has a lot of great stuff on youtube as well. Beyond the basics, the best way to learn SD is to experiment. This is something I can’t stress enough for beginners and intermediate users like myself. Even if I already know a great workflow for something, trying new approaches almost always yields a useful discovery. It’s also very valuable to teach others!