Aleksandra Jankowska explained how you can create a procedural material for a Cambridge-style house using Substance Designer.
In case you missed it
You may find these articles interesting
My name is Aleksandra Jankowska and I’m an environment artist at Splash Damage.
After graduating from the University of Hertfordshire in 2018, I have received an internship award in The Rookies competition and I have joined Ninja Theory to work on Bleeding Edge. It was during that time that I had the pleasure of living in the truly magical city of Cambridge where I found the inspiration for the Substance Designer material I would like to break down for you today.
Inspiration and Gathering References
Substance Designer is an astoundingly powerful software that always intrigued me. Seeing works of extremely talented and expert artists such as Jonathan Benainous, Daniel Thiger, and Pauline Boiteux has inspired me to finally dive into the wondrous world of Substance Designer nodes.
Ever since picking it up, I found myself noticing patterns and surfaces in real life that the idea of recreating them in SD excites and challenges my brain. I always make sure to take as many good reference pictures of them as I can and file them away, creating a library of references that I can reach into every time I want to practice SD.
One of those surfaces that inspired me was a windowed façade I stumbled across while taking a walk around enchanting Cambridge.
When I take previously mentioned reference pictures, I deconstruct what I see as if I’m already making it in SD. I believe that a good sense of proportion is a key skill of every excellent environment artist therefore I make sure to take at least one picture en face. I like to take a few photos from some extreme angles as well as it helps me reference the roughness and any subtle distortions of a surface, double important in this case, as since depth is such a big factor, it provided me with plenty of information on angles and shapes on the trims. I have also taken some en face pictures of the stone brick themselves, which I will discuss later on.
The first thing I do is work out how I want the material to tile. To help me visualize how the proportions change, I start with setting up a network of basic shapes on which I build on top of later on. This approach opens the possibility of quick and easy change of the size of particular elements and an effortless generation of masks you might need.
To make this process even easier and to assure everything is in the right position, I have adjusted the perspective of my en face reference picture in Photoshop and blended it with my graph on low opacity.
I placed shapes so they aligned with the picture, however it was just a guide – as I have decided to divagate from the reference and focus just on one window some proportions had to be tweaked ever so slightly. I also decided to mirror the pillar from the left side, so it frames the window nicely.
Another important matter I had to consider early on was Height Map limitations. I was cautious about the top set of trims as it comes out of the wall quite a bit, which would block a lot of the upper values of a Height Map and leaving me with not a lot of room to sell the depth of the window frame itself. It was because of that that I have decided to leave the top layer of the trim out of my material. Now that I have identified both the highest point, top of upper trim, and the lowest point, glass in the window, I could start building my Height Map. As a reminder of how much space I have left, at the end of my height graph, I have blended in the window frame shape on Substact mode which helped me to balance out the height positions of particular elements.
One of the things that really sells this material in my opinion is the trims. I decided to make them first as their placement is important for adding brickwork later on.
The curved trims have all been created using the same technique of manipulating a Gradient Linear with Curve and bending it to the desired shape. It’s very easy as long as you have a reference from an extreme angle so the silhouette of the trim you’re recreating is clearly visible – just draw the shape you see with a curve. It is worth breaking wider trims into smaller ones first, again, due to a limited amount of values in a black (0) and white (1) map, trying to fit it all into one might not give you the desired depth and shape definition.
I created what I affectionately call ‘egg trim’ using mostly discs of different sizes which I then subtracted to achieve desired shapes. Bevels in negative values have proven very useful to create the recesses with those lovely sharp corner lines.
I did the exact same thing for the decorative corner pieces in the window frames.
The square trim was the easiest of them all as I simply took advantage of the Cube 3D node. Even though in real life the trim is made of cubes, I have decided to tilt them in my 3D recreation to help readability and reduce tearing. I did the same for cylinders in between, using Shape Extrude this time to achieve my desired effect.
Height Maps are a lot of fun to work with in Substance Designer however they are just 2D textures and that brings a fair share of limitations. Like I’ve mentioned in the square trim section, it’s worth pushing the angles out a little to sell the illusion of depth, but the challenge I ran into when it came to wrapping the trims around the columns was a completely different matter.
This is the solution I came up with:
I used a beveled square to subtract from my column trim to produce a silhouette of the trim. The value of the bevel itself is irrelevant, it should be adjusted until the silhouette of what you see in the Blend node roughly correlates with how much the trim comes out of the wall. I made a mask out of that using a histogram scan which I then blurred slightly to smooth out the edges. Then I beveled it out again to avoid tearing and sell the illusion that the trim wraps itself around the column. You can see in the graph I do the same for the top and bottom of the trim with a beveled rectangle that correlates with the width of the trim.
Devil is in the details when it comes to realistic textures. Especially with man-made items, it’s important to pay attention and do research on how something was built.
Looking closely at my reference, I noticed that bricks on the back wall align with decorative bricks of the window frame, with the exception of the bottom edge (green and red). They aren’t even wide, much like the bricks at the bottom (pink and purple). There were also some unique elements (red circles) that I decided to not add as they would be a dead giveaway of a tiling texture.
To match those characteristics, I constructed the brick pattern manually on the back wall as it allowed me to condition their width to the window frame - should I change its proportions, the brick width will follow. I used a brick generator on the extruded part of the wall.
It’s very important to eradicate perfectly straight lines as they instantly make everything look artificial and too perfect.
To break up straight lines I mostly use Slope Blur and Directional Warp, but I found the latter to not be suitable for this particular purpose as it’s direction-based. In this case, I used two slope blurs, one bigger that simulates the uneven shape of a brick and another smaller that implies wear closer to the surface. I like breaking up my damage and grunge workflow like that as it gives me more power to show more subtle.
I applied almost identical logic to edge wear on all the cracks and separation lines.
I tried to imagine how the stone would crumble and picked a noise I thought would work best, tiling it a fair amount – the damage I was after wasn’t caused by force where chances are, a big chunk would be chopped away, but a more subtle, bits taken away by time and environmental factors. I used two slope blurs, one of lesser power that digs deeper and another bigger that suggests more recent wear closer to the surface.
It’s worth remembering that the edge will never be consistent throughout the whole item, therefore I like to Blend it with a noise map of choice on Multiply mode to add a little more randomness.
It’s important to incorporate that damage in the diffuse map as well as Height Map. Not only it will highlight the height map damage detail but also add another layer of realism and storytelling as it exposes the grainy composition of the stone.
For this material, I wanted to try something new and use photographs for textures. To do this, I had to prepare them first, fix perspective where needed, remove cement lines and any larger imperfections that could tile. I also went ahead and made them tile – I have initially used Substance Designer Make it Tile Photo Color node however in the end I decided I could achieve a better result by doing it manually. I was aware they will serve as the base and I will be adding things on top of it therefore these alterations didn’t have to be 100% perfect.
I used 5 different textures in total:
After bringing them all into Substance Designer, I had to color-match them. Most of the textures were pretty grey so the process wasn’t very tricky. I used HSL nodes to bring them as close as possible and then used Color Equalizer to even out their tone.
They are looking very flat right now, but they make a great base to add a variation of color where I want it.
To randomly assign different textures to different bricks, enforcing the illusion of them being made of different pieces of stones, I use a setup involving Flood Fill.
After Flood Fill, I connect a Flood Fill to Random Greyscale, followed by Quantize Greyscale, which allows me to define exactly how many masks I want. Then I plug in the Gradient node which will allow me to use the Color to Mask node and finally define the randomized masks. I really enjoy this setup as it’s easy to generate several different options through Random Slider in Flood Fill to Random Greyscale.
I use it to introduce color variation into my Diffuse Map as well. I use HSL nodes on my texture so far, pushing its values to the extremes I’m happy with, whether it’s Hue, Saturation or Lightness, or all the above. Then I blend it back into my Diffuse map and use the already established Flood Fill to Random Greyscale, which influences the texture in a non-uniform way and creates a nice variation within seconds.
I also used Flood Fill to add back those areas of grey visible in the reference photo, by connecting Flood Fill to Gradient with Levels.
I cannot recommend Flood Fill and its family of nodes enough, it’s a brilliant, multifunctional tool. Very easily you can add height variation of your bricks (Flood Fill to Random Greyscale blended with Flood Fill to Gradient work great), add roughness breakup to highlight particular bricks (Flood Fill to Random Greyscale), or previously mentioned, color variation and mask generation. It’s great!
There was a lot about stained glass in the window to take in from the reference.
Straight away I noted that the bottom part of the window has a double border that is much darker than the centre of the window. Small squares in the middle have slightly different colors. Another thing is that they each have a pattern that reminds me of a wave or tiger stripe, which is randomly rotated and non-uniformly distorted.
I created the patterns by running Crystal 2 node through Vector Warp greyscale, using blurred Perlin Noise as Vector Map. I played with the values until I was happy, blurred it and then coloured it using a uniform colour and blend on Multiply mode. I needed more than just one pattern, so I copied this graph and generated a couple of more swirly textures by changing the seed on Crystal 2 node, Perlin Noise node and sometimes rotating the pattern in Safe Transform node. When I had a satisfying number of different patterns of different colours, I applied them to the stained glass using the previously mentioned random Flood Fill mask. The double border of the bottom window had a separate, singular, darker texture.
A similar pattern can be spotted in slight deformation of the glass, each of the small squares has a bit of distortion, a large and smaller wave running over it, but not following the color. I have added this detail in a normal map, the only normal detail I have generated by hand. I have followed the same workflow as before but created more suitable textures for the task.
Larger, stronger waves visible from a distance.
And subtle waves visible up close.
Grunge and Dirt
Just like with damage, I find it very important to be intentional with your grunge placement. My reference pictures were a good starting point.
When analyzing dirt patterns of material, I first look for bigger shapes that will help me pick the initial noise map from the Substance library. Then I look at its edges, how they fade out/dissolve and I try to replicate it by blending other noises over my primary noise map. When I add grunge I always work in a few layers as I enjoy the amount of control it gives me. I use a lot of Levels nodes, often leaving one at the very end so I can have influence over the mask and adjust it as needed as I develop the material further.
It has a fairly clear edge that’s a little blurred and only at some places becomes so soft, it blends into the stone.
It has similar shapes as the white deposit but doesn’t blend into the stone as smoothly, it has a slight granular quality to its fade-out therefore I multiplied it by white noise to replicate that quality. I also noticed in the reference that it appears not only at the bottom but a bit at the edge of a brick in the second row – I added that little touch with a quick transform, blended with another noise mask for variation, and blended the two again.
In this material, I used Mask Generators such as Sun Bleach, Dirt, Dust, and Edge Damages.
Unlike many, I am not opposed to using Substance’s Mask Generators nodes. I believe they can be a useful tool, as long as you don’t leave them unaltered. I like to set them up, make a call on whether its dirt pattern can be of use to me, and then I proceed to apply it to areas that make sense and often overlay another noise map to break it up.
Pushing the Realism
Even though the dirt applied so far matches the reference, the material itself still looked flat and a little too clean, so I decided to push it a little further. I realized my material lacked more sharp dirt, all grunge so far seemed very diffused and blurry and I decided to emphasize the crevasses.
I used an Ambient Occlusion node on my basic shapes from the beginning of my graph to separate the areas I wanted to work on. It was important to do it before any intricate detail was introduced as it assured a clean outcome, uninfluenced by bricks, etc. As I’m recreating a large surface, I used World Units mode and it delivered a great mask for me to work with. I used a gradient which allows me to control where most of the dirt will be applied. To achieve my final mask, I blended my AO blend with Grunge Map 09 on Add Sub mode, adjusted my levels, and Subtracted flat horizontal surfaces that got caught in AO generation due to the window frame being slightly receded.
To finish the grunge pass off, I added some splashes at the bottom, leaks and used a gradient map to lighten the top a bit – I like to do that on large objects as it enhances the feeling of weight and the objects being grounded, and creates a bit of a sun bleach effect.
To make the diffuse map a little "punchier" I blended it with itself on Add Sub mode using a low value of 0.05 opacity.
There’s not a lot of metallic information to be conveyed on the map. I’ve applied metallic values only on window glass including the lead.
When watching the gameplay of Resident Evil VII, I was in absolute awe of the gorgeous environments. I noticed that the Roughness Map on many objects is very exaggerated, prioritising roughness breakup contrast over more realistic colour values. Something about the way light glides over those over-the-top roughness maps, underlining every dirt patch, makes them really appealing to the human eye. Ever since I try to apply those principles to my work as well.
I started building my Roughness Map the Flood Fill to Random Greyscale we used for the Diffuse Map earlier; having different roughness values on different bricks helps to highlight the construction of a wall when viewed from an extreme angle. I run the Flood Fill to Random Greyscale through Histogram Scan which I like to use when working with a Roughness Map as it very easily allows you to adjust the intensity of your texture’s breakup and position.
Roughness Map is a brilliant tool to further sell the feeling of texture and so I used it to enhance the feeling of porosity of the stone. I did that by blending White Noise into my Roughness Map. To break the map, even more, I converted the initial Diffuse blend of all the stone textures into greyscale as it has a lot of noise that I wanted to highlight. To extract the larger clumps of dirt and other surface inconsistencies, I blended the texture with itself on Add Sub, Inverted it, and used Histogram Scan to separate what I needed; I blended it into my Roughness Map using Add mode. Placed Histogram Scan at the end to adjust it as needed.
I combined all my grunge masks into one and using it as a mask once again, I blended Clouds 2 noise map into my Roughness Map so far.
For stained glass, I used a similar approach as brickwork.
I created a mask based on the AO of the window leads pushed through the Dust Mask Generator to simulate the build-up of dirt and dust around the edges of the glass squares. I adjusted the curve of Flood Fill to Random Greyscale of the windows that I used before for Diffuse variation and blended that with blurred BnW Spots 1 for some breakup. I blended that with a dirt/dust mask and created my final roughness mask for window glass.
And voila! In the end, we get these beautiful results.
I would like to thank Ellie and the 80.lv team for giving me this opportunity, it’s been a great pleasure and privilege to be able to contribute to the vault of knowledge of this portal.
I hope you all enjoyed this breakdown and found it useful. If you would like to get in touch, you can find me under Aleks Jank on all social media.