Professional Services
Order outsourcing

How to Set Up a Procedural Mosaic Generator in Substance 3D Designer

Rebecca El Cheikh created a new generator in Substance 3D Designer and shared with us how it was made.


Hi, everyone! My name is Rebecca El Cheikh. I'm a Lebanese Environment Artist and I've been living in France for the past couple of years for my studies. Art and science have always been my passion, so I first chose a degree in Computer Science and Computer Graphics and then started my career in Commercials by working in a post-production company for 3 years. Throughout my career, I've always worked on personal projects on the side to be able to shift into the game industry later. After moving to Europe, I participated in a student project titled "Along the Rift" and later gained valuable experience as an Environment Artist during my internship at Don't Nod Entertainment, specifically working on Banishers: Ghosts of New Eden.

Speaking of getting the hang of material art, it's not difficult to start learning Substance 3D Designer. With the amount of tutorials out there, it's accessible to learn the basics of it and start applying it in your projects.

Considering the incredible projects artists do, it's easy to get inspired and pick a topic to start. As with anything, practice is the key to success. There are plenty of tutorials out there for any level and a lot of thought processes are shown and explained by artists. I've learned Substance 3D Designer by doing that and by applying the different techniques in my own projects. As you practice, it becomes more natural. I currently use Substance 3D Designer and Substance 3D Painter for texturing.

The Idea Of Procedural Mosaic Generator

The first generator I've ever seen was Daniel Thiger's Tire Generator during my undergraduate studies in Lebanon. I remember it as one of the most adept ways to use Substance 3D Designer. The first time I tackled the creation of procedural filters/tools on Substance 3D Designer was during Along the Rift, almost 2 years ago. Although it was basic, I did a procedural brush stroke filter at the time. I enjoyed it so much that I directly planned future more complex projects like an embroidery and mosaic generator. Creating mosaics on Substance 3D Designer always seemed to me like tedious work and I wanted to find a solution for it. Here's a preview of how the generator looks:

Setting Up The Generator In Substance 3D Designer

To begin, I always start any project by brainstorming and gathering references. It's important to have a baseline and plan for the project and to always start big and later work on smaller details. The mosaic generator's main feature was to follow the outlines of any given image. If I could create an Alpha Map of those tiles, then the rest would follow smoothly. This feature alone comes with different problems and questions such as: "How am I going to determine which shapes the tiles will follow? How are the tiles going to follow specific directions and how are they going to be created? Am I going to have to separate them or work on each shape individually or not, and how?"

Creating stripes of tiles that follow the curves of a shape

I started the project several weeks before the new Paths and Splines nodes were added. Therefore I decided to start by figuring out how the tiles will follow the shapes. For now, I'm using a simple square to show how I created tiles that can follow any given shape.

With every mosaic looking different depending on the curves and position, the logic was that I had to generate stripes following the given shape and then subtract a series of a long perpendicular pattern to these stripes such as the following:

First, I ran the original shape through a Bevel node. Then, I used a total of 16 histogram scan nodes blended together to extract the lines used to created the stripes and the long perpendicular pattern. I was then able to cover the largest shape that could be inputted by the users, a flat square.

Based on the image created, the stripes were achieved using an edge detect and the perpendicular shapes from Substance 3D Designer's new Path/Spline tools. The first step involved using Mask to Path to generate paths from the visible lines. Then, Paths to Spline was used to convert the paths for further manipulation. Finally, Scatter on Spline Grayscale was employed to add patterns to the splines, resembling features found in Tile Sampler or Scatter Circular. However, in this case, the patterns followed the position and rotation of the given spline.

The resulting graph for this process would resemble the following:

Note that, since the mosaic tiles could be rotated in any given way, the perpendicular shapes had to be longer than the stripes to be able to cover the whole area. To avoid overlapping, I ended up doing this process twice, one for the original shape, and another for a square just slightly smaller (by subtracting an edge detect).

This was probably the hardest part of the project. As stated before, Substance 3D Designer's update had not yet been released at the time of this project, so I tried to find a way to make a similar output. In the end, I resorted to creating a really thin line with the Edge Detect and using it as a mask for a Tile sampler of 100x100+ perpendicular patterns. The result was messy with the perpendicular pattern empty in places and clustered in others. It might still have worked, but the update came out at the right time so I used the better option.

Extracting shapes from any given picture

Now that the mosaic generation of one shape is done, it's time to find a way to create shapes from images. The most optimized way I found that worked on almost everything was using the node Lighting Cancel Low Frequencies. The process didn't always separate all the shapes, but most of the lines were visible so that the mosaic did its contour as closely as possible. I simply had to extract the background's color with a Value Processor and use Replace Color Range to change it to black. This way, I had the black-and-white contour of the given input.

The outline-extracting process looks like this now with clear separate shapes:

Separating individual shapes from the outline image

This is the most expensive process I did but I still found it necessary to do. Let's suppose that the outline is thin, if I were to create the mosaic simultaneously on all the shapes, there would be a high risk that the perpendicular patterns would intersect with stripes from different shapes. Although it might work in a few cases, I felt it was better to do it on individual shapes for a cleaner and safer result. I'm still not sure whether that was the wisest decision because it was by far the least optimized way to do things because it increased the computation time from 15 seconds to slightly more than a minute for 2k textures. I tried to use the Switch Grayscale so that Substance 3D Designer did not compute empty shape inputs, but unfortunately, it still computed both True and False inputs, which rendered it useless for optimization purposes.

At this stage, the Flood Fill to Index node proved to be highly convenient and useful. There were two main advantages to using this node. Firstly, by setting the option to Ignore Shapes Smaller than 0.1, we could prevent the mosaic creation node from being applied to these smaller shapes and avoid generating black images. Secondly, this node output both the number of shapes detected and a unique value associated with each shape. This enabled us to extract a specific shape using the Pixel Processor node, allowing for further manipulation and control.

The Flood Fill to Index Grayscale assigns the grayscale values based on a simple division of 1 by the number of shapes detected. For example, if there were 3 shapes, the grayscale values would be 1, 0.666, and 0.333, respectively.

The Pixel Processor node, on the other hand, performed the following operations: it retrieved the value corresponding to the shape number specified, scanned the image for pixels with this value, and output those pixels as white. The remaining pixels were multiplied by 0, resulting in them being displayed as black. This process effectively isolated and highlighted the desired shape while darkening the rest of the image.

The overall process now looks like this:

After testing, I repeated the unique shape extraction process 32 times. Considering I decided to go for 64x64 mosaic tiles on average at the end, this amount was the safest way to ensure the most necessary number of shapes were processed. With the shapes smaller than 0,1 removed before all of them were separated, the worst case would be that about 12 shapes were not processed. Anyways, the gaps would be filled later (explained in the next section) and the mosaic still looked clear and took less time to generate the mosaic.

Filling up the gaps

If the image inputted had a lot of clustered shapes smaller than 0,1, or there were large black spots, the resulting work done so far is a mosaic alpha with empty areas. So doing this procedure again on the inverted alpha was essential to cover this scenario. Although it was not as important in the following case, the generator should cover every scenario possible, even if it took extra time to calculate everything.

Taking care of shapes smaller than 0,1

I created a spiral-like mosaic pattern to be blended with shapes that were too small to be turned into a mosaic. Since they weren't prominent, users wouldn't normally notice the web-like pattern. In the end, when everything was merged, Flood Fill to Index was used again to remove dot-like shapes smaller than 0,02.

The Mosaic Material Creation

With the mosaic alpha finally done, what's left is to create the mosaic material and beautify the output. I made the tiles bigger by Blurring and using Histogram Scans, added variations to the edges with Slope Blurs, and subtracted Flood Fill Gradients to break their linearity.

The only tricky part was coloring the tiles. Mosaic tiles normally have one color each, and I was not using a Tile sampler/generator that would normally do the job. To solve this problem, I created radial gradients of each tile by Blurring them and using this alpha in Warp and Slope blur. The colors would be pushed out, and the dirt would replace what was in between the tiles anyway.

Setting Up The Final Renders

With Marmoset Toolbag, you can efficiently create a nicely lit scene that quickly updates as progress is made. I had 3 preset material render files ready to use and test for any material I created; a sphere, cylinder, and plane. I only had to change the brightness levels and colors in Lights, depending on the colors and reflectivity of the material. I always had a strong directional light base (top right), a strong rim light in the back, and two warm/cold area lights for a nice contrast.

Final Words and Pieces of Advice

As previously mentioned, practice is the essence of getting better in Substance 3D Designer. Whether through tutorials or studying different projects, practice remains the only way to truly master this program. The timeline for this does not exist, and it will differ from person to person, but as one practice, it will come naturally.

I've joined a few groups on Facebook and Discord related to Substance 3D Designer, watched a lot of tutorials, and always tried to study what other people did in their projects. The Inside the Node group on Facebook might be my favorite place and the one that pushed me into learning Substance 3D Designer more deeply with Pixel Processor and FX-Map nodes. It was essential for this project and boosted my knowledge and logic of the program to another level, which in the process, allowed the creation of this project.

Although this is more of the foundational aspect of Substance 3D Designer and might not always be used for materials, it's still a good plus to have a base knowledge of it. Honestly, mastering the program is an extensive journey that I’m yet to complete, but this is the advice I can give you for now!

Rebecca El Cheikh, Environment Artist

Interview conducted by Theodore McKenzie

Join discussion

Comments 1

  • Wirrmann Nicolas

    Very nice!
    The floodfill to index can actually output the value as an integer (1, 2, 3..), the shapes are all white because the values are above 1. It makes it even easier to extract a specific shape and you don't need to know the total amount.


    Wirrmann Nicolas

    ·10 months ago·

You might also like

We need your consent

We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more