Over the years and through various projects, I’ve discovered a true passion for creating biome and terrain textures. I had previously worked on forest ground textures, but I wanted to push the quality further and put all my skills into practice.
Right from the start, I had a pretty clear idea of what I wanted to achieve. I had in mind memories of the pine forests I visited as a child when my family and I went on vacation to the South of France.
I recalled something very dense in needles and elements, very dry too, where the ground was almost imperceptible due to the thick coverage. Following that, my goal was very clear: to reproduce it entirely procedurally, using only Substance 3D Designer.
I could certainly have used MegaScan atlases, which would have greatly accelerated and simplified the process, but I wanted to build up a small library of generators and see how far I could go using just one program.
I began by gathering references by just doing a quick search on Google Images. The most important and useful aspect for me was to find close-up references for each of the elements I wanted to include in the texture (needles, pinecones, dead branches, etc).
I also used more general references to understand how the different elements interacted with each other once on the ground. At this stage, it’s best to already have an idea of how to proceed and where to start, the different generators you’ll need, the different layers and their order.
It’s also very important to define the size of the surface to be represented. As far as I’m concerned, I decided to represent a 4-meter surface as I wanted to create a Game-Ready texture that could actually be used in production. In other words, a relatively large texture that could be used on large surfaces and easily repeated.
This texture relies entirely on the use of generators. I had to create a certain number of them, but I also reused a few of them made previously for other textures such as the grass material made a few months ago.
Making a generator isn’t something very hard to do (depending on its complexity, of course), but given the large number I had to make, I’m only going to focus on the main ones.
First, I took a sphere and modified it to give it an elongated, pointed shape similar to a needle. I then used a 2D Transform to rescale and reposition my spine so that its base is at the exact center of space.
This step will allow me to automatically create variations with multiple needles, ensuring that they are always connected by the base.
Note that I use a simple Blend to crop the bottom part of my needle just by modifying the Cropping Area parameters.
I discovered this technique while watching Jonathan Benainous’ GDC 2023 talk on The Material Art of The Last of Us Part 1.
This parameter is very useful and helps save nodes that would have been used to create the mask manually. I then created several warped variations of the needle by using a Warp and Perlin Noise, taking care to mask the base of the needle so that it’s not affected by the Warp and remains in the center.
When using noise, gradient, Uniform Color, or any other map, always ask yourself if you need them to be at the same resolution as the rest. In many cases, the answer will be no.
Uniform Color can be reduced to 1x1px, a gradient can be limited to a thin strip 1px wide by a few pixels long and Perlin or Gaussian noises, being already very soft noises, can also be reduced by several resolutions without seeing any difference in quality.
Similarly, when you want to blur a texture, think first of just reducing its resolution. This will blur it naturally, and you’ll have saved a node and a bit of computing time.
Once the variations had been created, I inputted them into a Splatter Circular. That’s why it was important to have the base of the needle in the center.
This ensures that the position and rotation point of each instance are the same for all of them, and that all their bases overlap at a single point. For this to work, it’s also essential to reduce the Radius in the Position tab of the Splatter Circular to 0.
Next I created an ID Map so I could later control each of my needle independently (allowing me to give them different colors and normal orientations).
To do so, I duplicated the Splatter Circular, changing only the Luminance Random to obtain a greyscale mask. I converted this map using Vincent Gault’s Fine Edge Detect.
(It produces much finer and more precise edges than the basic Edge Detect).
I then sent it to a Flood Fill and Flood Fill to Random Color. I ended by removing the edges from the edge detect with a Distance node (by setting Maximum Distance to maximum and Combine Source/Distance to Only Sources).
I finally gave a distortion effect to the needle by using a Swirl and a Directional warp and exposed a few useful parameters.
This Needles generator is done, but it won’t actually be used as such in the final graph, where the scattering and layering of all the elements will take place. In fact, I’m using it as a basis to create other generators.
I decided to create a pile of needles instead of directly using my Needle Generator in my final graph. The reason is I’ll use a Shape Splatter node to scatter my elements, and unlike the Tile Sampler, it has a limit scale of 5.
Meaning you simply can’t go over that value. Since I wanted to cover the entire texture with a thick layer of needles, I would have needed a large number of scattered instances.
And since the more instances you have, the smaller they are, I would have been blocked by the scale limit of 5.
To do so, I simply created a Shape Splatter in which I input a few variations of the Needle generator.
By using a primitive shape like a disk, I was able to hide the needles on the edge of the texture and create the stack effect I was looking for.
I then used two Shape Splatter Blend Color to recreate my normal map and my ID/Vector Map.
Needles Branch Generator
To create this generator, I’ve also reused the Needle Generator made above, which I scattered using three very similar Shape Splatters with different Random Seed values.
I only used very few parameters of the Shape Splatter. In fact, all you must do is scatter the needle on a vertical line.
Once done, I rebuilt my other previously created maps (Normal Map, ID/Vector Maps) using Shape Splatter Blends and gave it its final look by warping it and adjusting levels.
Before moving on to the next generator, I exposed a few parameters that will be useful to create variations.
Second Needles Branch Generator
This generator reuses the Needles Branch Generator created above. To make it, I simply created a few branch variations and placed them by hand (this is probably the least procedural part of this texture).
I created 3 different branches that I connected to a Switch Material node so I could choose which one I wanted to use.
Young Fir Cone Generator
For this generator, I started by creating the cone shape using primitive shapes. Fir cone scales were obtained using a Polygon 2 and a Shape Extrude, which I scattered using a Tile Sampler.
I then blended it with the shape. A Swirl Grayscale is used to curve it, and I ended up adding a few more little details.
Fir Cone Generator
The creation of the fir cone is very similar to the previous one, except that I use two Tile Samplers to scatter the scales. One for the center and one for the border of the cone. For each of them, I created two variations of the scales.
One for the left side and tilted to the left, and the other for the right side and tilted to the right. I then use a mask to control where I want each of those variations.
I also use a Scale Map to control their size and have larger scales on the inside of the cone and smaller scales on the outside. This gives the cone a bumpy 3D effect.
Dead Branches Generator
For the dead branches, I first created a cylinder using Gradient Linear 2. Then, using Directional Warps and noise based on Directional Noise 4, I frayed the ends of the cylinder to create the appearance of broken wood.
At this stage, the branch is still perfectly straight, so to remedy this, I distort it using a Directional Warp and a Crystal 1.
Now that I’ve got my main branch, it’s time to add branchlets. To do this, as seen above, I start by rescaling the branch so that its pivot point is at its base. This will ensure that their bases won’t move during the rotation and remain merged with the main branch.
I then create a succession of 3 Tile Samplers. The first 2 will scatter the branchlets with a left and then right rotation for both sides. I use the third one with a high number of instances which allows me to add micro details and a global asperities layer to the branch.
Since these branches represent a significant part of the texture, I decided to expose certain parameters to ensure that I could easily generate very different branch instances.
Among them, the most important are the size, the warp intensity, and the number and size of branchlets.
I won’t spend time on the ground because it’s completely unimportant. I detailed it much more than I should have, thinking that it would be visible in some places. But as I built up the texture, it turned out not to be visible at all.
Even if it’s not important, it’s still useful for creating a macro volume that will simulate uneven ground on which all elements will be scattered. Just bear in mind that it’s only necessary to have a very macro and blurred noise, representing only the large volumes. A Perlin noise or a blurred Cloud 2 can do the trick just fine.
Now that I have all my generators and my base soil, it’s time to really get down to business and layer everything together. This part of the process is actually rather quick, as once the first scatter setup has been created, it can simply be duplicated and adjusted for the other generators.
To perform this task, I’ve decided to rely solely on the use of Shape Splatter and Shape Splatter Blend (Color and Grayscale) as it offers a non-destructive approach and will be very useful to simultaneously build my Height Map, Normal Map, and BaseColor Map.
So I started by setting up my Shape Splatter, connecting my generator instances to it and my ground created just above in Background Input.
For the first Shape Scatter, there’s no need to worry too much about the parameters; the idea here is just to cover the ground with a homogeneous layer of pine needles. For this purpose, I did modify some parameters, such as X and Y Amount, Scale, Scale Random, Random Position, Random Rotation, Height Scale, Conform to Background, and Smooth Conform to Background.
I then created a black and white Mask representing the needle scatter by converting the Splatter Data 1 output of the Shape Splatter to grayscale (R to 1, G and B to 0). This mask will be used to blend the BaseColors and Normal Maps.
Also, be aware that the Shape Splatter and Shape Splatter Blend (Color and Grayscale) output is 32-bit, which can sometimes create problems. In that case, you can simply fix it by changing the format to 8 or 16 bits.
I then create Shape Splatter Blend Color and Grayscale to also generate the other maps created in my generators: Normal Map, ID/Vector maps, Masks, and others if needed. This way, I can generate my Normal Map and BaseColor at the same time as my Height Map.
For the normal map, I start by recreating the Vector Map and Normal Map using Shape Splatter Blend Color (don’t forget to check “Is Normal Map” in the Shape Splatter Blend options).
Once created, I blend them together with a Normal Combine, modifying the intensity if necessary. I then combine them into a new Normal Map derived directly from the Shape Splatter result.
This way of creating the Normal Map allows me to obtain different Normal orientations for each instance of the elements and will have the effect of redirecting light bounces differently so that the needles appear to be laid over the ground and intertwined in successive dense layers. This technique avoids the flat look of a height map converted directly into a Normal Map.
This technique is also very effective for representing grass, moss, and many other vegetation elements.
As most of the elements are very small and already create a very busy and noisy normal map, it’s unnecessary and, in my opinion, even inadvisable to add too many details, especially micro details in the BaseColor.
The most important thing in this process is to give them a unique color to create variety and slight color variations. The exact method might slightly vary for each of the elements, but in most cases, it relies on the same steps.
In any case, I started by converting my Vector Map to grayscale so that I can use it in a Gradient Map. The Pick Gradient option in the Gradient Editor allows you to retrieve the values of a selection made with the mouse.
Best of all, the selection works even outside the Substance 3D Designer window!
I then added a fairly fine, organic noise, also used with a Map gradient, this time to add micro-detail. Depending on the case, I can also add a little more detail, based, for example, on AO and Curvature.
I then blend it to the ground BaseColor or the previously blended elements using the Black and White Mask made above.
Once the first layer has been created, I repeat this process for all the elements I wish to scatter by duplicating this entire part of the graph and reconnecting it to the previous one.
The only difference is the use of a Random Mask to mask certain areas of the texture. This Map is a black-and-white mask derived either from the height map or from a simple noise, such as Cloud, Moisture, or others.
I also created a Normal Map used as a vector Map from the same type of noise, but this time scaled down to remove any micro-details it might contain.
This Normal Map, once connected to the Vector Map input, allows me to modify the position of elements in a much more organic and realistic way. The Random Position moves instances in a random direction but with the same strength.
This means you end up with something that is no longer grid-based but also not very organic at a macro scale.
The entire texture has the same level of density, whereas using a vector map gives different strength values based on the Vector Map to each instance, resulting in some areas being very dense and others almost empty at the same time.
By combining it with a mask, the result becomes very organic and visually much more interesting.
Once all my elements have been scattered, I finalize my BaseColor by adding a little Ambient Occlusion, especially to fake the depth and thickness of the layers of needles.
I also tweak the colors, luminosity, and contrast with a level and HSL and finish by sharpening the whole result.
As for the Normal Map, I added more volume by blending the Normal Map with a blurred version of the Height Map to retain only the macro details.
To sum up quickly, for this texture, there are over 16 different stages of element scattering. That’s a lot! Of course, this has a huge impact on performance, so when you want to create a texture of this type with a huge number of elements, be very careful about the potential impact it could have, and always bear in mind that each step adds a considerable amount of computation time.
In my case, I could obviously have reduced and optimized certain steps further or chosen to reduce the richness of elements present in the texture (i.e. fewer shape splatters and generators to compute), but as mentioned above, my objective was to build up a small library of generators and create a texture with a large variety and diversity of elements, in order to be as close as possible to reality.
A small piece of advice when working in Substance Designer – try to order your graph as much as possible, especially when it becomes huge like this one. This will enable you to see things more clearly and to modify or locate parts more easily.
Personally, I discovered the amazing Ben Wilson’s BWTools 2.0 a few years ago.
This small plugin includes several options, including reorganizing your graphs and automatically creating pins and frames. And best of all, it’s free! Honestly, it’s become so much a part of my daily life that I can’t live without it. I can’t recommend it enough!
I used Marmoset Toolbag 4 for my renders as it’s almost a plug-and-play software and provides a very good quality of renders.
I used a 2:1 ratio, which is more elongated and cinematographic than 16:9. I also lowered the FOV to around 30 to flatten the perspective. As for the Post Effect. I only changed the Tone Mapping to Hejl.
The rest will be done in Photoshop.
I started by creating a plane about ten meters on a side, which I made slightly uneven by creating small random bumps. Having a slight relief in addition to the displacement of the texture will help create more shadow and make the renderings more believable.
Once in Marmoset, I increased the Subdivision Level to ensure good displacement fidelity. I also wanted to suggest the presence of trees for a more relevant context, as well as a character to create a sense of scale.
And what could be better than stags for a little forest immersion? To do so, I downloaded some free 3D assets from Sketchfab.com. Stags were placed close to a line of force, about 1/3 of the way down the image.
I spent quite a bit of time placing the trees, turning them in all directions to try and find the most interesting placement.
I found this stage to be very important, as it allows for anchoring the texture in a more believable environment, creating a natural framing on the edges that enhances the readability of the image, and visualizing how the material looks in both shadows and highlights.
In the end, it contributes to creating a more captivating and dynamic image composition.
I started the lighting phase by spending a little time finding an HDRI that suited me. I ended up downloading one from polyhaven.com. I then created a Directional Light which I oriented so that the light came from the top left of the image.
Having a light source facing away from the camera rather than in the same direction helps capture more shadows and AO adds depth to the image and makes it easier to visualize the Roughness.
To accentuate the latter, I added a spotlight oriented in the same way as the Directional Light, but at a slightly lower angle.
Once done, I imported the renders into Photoshop for the final step. I started by tweaking the levels, contrasts, and colors. Then I created a vignette to frame the edges even more.
I ended by creating the sketch effect on the stags. To do so, I made 2 renders. One with the stags and one without. Then in Photoshop, I masked the stags using the second render in order to only keep their shadows. I then reused the same Mask to let the sketch noise appear.
This last step concludes my Forest Ground Material.