When it comes to
creating materials for my 3D assets, I usually do it entirely within Substance
Painter. In the past this was quite helpful as a lot of my assets were unique
and didn’t use the same material. This time however I am imagining a lot of my
assets to be made from a similar material such as wood or marble. However
because I am using custom normal maps per asset It becomes quite inefficient to
repeatedly save out multiple versions of the same wood material with the only
difference in some cases being the normal and ambient occlusion maps.
To do so would
require me duplicating the same material within Substance Painter and applying
it to different assets within the software, then baking the effects of the
normal value and ambient occlusion into the textures and then exporting them
out of Substance to be used as individual maps within Unreal Engine. I know that was quite a mouthful so please see
the diagrams I have drawn below that illustrate this workflow.
Step 1: Each asset will usually have a high poly equivalent.
Step 2: Using substance painter I can bake the details of the high poly normal object onto a texture and combine this with the diffuse texture to create the finished material.
Step 3: Once I am happy with the look of the material in Substance Painter I can export it out as three seperate texture maps for use within Unreal Engine.
Step 4: I can then load the maps into Unreal Engine and create an unreal engine material shader and apply it to the asset in the engine.
Step 5: I will then repeat this process for every asset in the environment until they all have unique materials.
Step 6: Once this process is complete, all the assets will have a unique material assigned to it which can be problematic if I need to change the look of a certain material across several assets.
Step 7: If I needed to change the diffuse texture of assets A-D, I would need to go back into the substance file for each material and then make the changes individually.
As you can see this
is a somewhat time consuming and inefficient workflow. I was about to continue
working again in this way when I encountered an error within Substance Painter
that prevented me from loading in the custom material I had just created onto a
new asset. My only option was to then re-create my custom material from scratch
onto the new asset, a process that took up precious time. I was frustrated but
nevertheless I had recreated the material and applied it successfully onto the
new asset. With that done I was about to apply my recreated material onto a
new asset when I was met with the same error!
Throughout my
previous projects I hadn’t come across this problem before and it illustrated to
me how inefficient and flimsy my material workflow has been up to this point.
I decided I had
to approach the problem in a new way that would minimise the amount of time
consuming busy work I would need for each asset. This is where Unreal Engine’s
material instances come into play.
Using Material
Instances:
In Unreal Engine you can create copies of a material that
when set up correctly, allow for certain attributes to be altered to add
variation to repeated materials. These are known as Material Instances. I spent
some time developing a workflow to quickly create multiple materials and after
some experimentation I believe I have a good system in place. Below I will
describe my process and the benefits I think this is going to bring to my production pipeline.
Breakdown of my material instance.
In this example my material instances all utilise the same
wood texture however I have enabled them to be hooked up with additional
texture maps that can greatly vary their appearance. This workflow requires
that I create custom normal maps and ambient occlusion maps within substance
painter per asset, and then hook them up into the material instance. See below
how I have used the same wood texture but have been able to add variation
through custom normal maps.
This is the generic wood material I created and applied to several assets in my scene. Let's say I want to add additional details to a specific set of objects, all I would have to do is create a material instance and change the normal map.
Here you can see the details have changed whilst the look of the wood remains consistent across all the assets.
I can even change the colour of the diffuse texture at once without individually selecting materials and changing attributes!
So far I have utilised the material instances within Unreal Engine to create
a variety of materials that all stem from a master material. This method has a
variety of benefits, firstly attributes that control the colour, roughness and
normal map intensity for example are no longer locked down to a single texture
map generated from Substance Painter. Meaning I can create instances of the
same material that can appear vastly different from one another.
For example, I
could make the colour of one material a shade of red whilst the other is blue,
or change how often a texture is tiled dependant on the individual material
instance. Both materials will still use the same maps but I can tweak their
attributes to add differentiation to them without needing to open up Substance Painter, change the material and re-export the texture maps (something that
took me a considerable amount of time previously). Because the normal map
remains static the material instance will not lose the appearance of detail.
Secondly because the materials are instanced, they require
less computational power making them more efficient in the scene. The Engine no
longer has to worry about calculating individual material shaders for different
objects, as the majority of materials are now derived from a master material.
This also has the benefit of keeping my project much cleaner as I won’t have
hundreds of near identical materials clogging up my scene.
And finally this method forced me to be more considerate
with UV mapping. I had to place a greater emphasis on my UV layout as each
asset is utilising the same master material. This means the direction the UV islands
face will need to correspond accordingly with each other. In the past this
wasn’t a big consideration for me as I would just align textures correctly in
Substance Painter, however I prefer this approach as it means the UV’s are now
consistent across all my assets. You can see the example below as to why this
was so important for my workflow.
The UV island faces need to align with eachother so that the wood grain is consistent across all assets.
This new approach to UV layout was also very helpful because
I knew that certain assets wouldn’t need to go into substance painter and could
therefore have their UV islands be placed outside the radius of the UV mapping
grid. I could also use this to prevent obvious texture repetition by moving the islands anywhere I wanted.
So far I am pleased with the new direction I am taking with
material creation as I already feel that I am working more efficiently. Now previously I
had created some custom materials and instances straight in Unreal Engine but
hadn’t considered combining this method with the texture maps I had created in substance
painter before. It’s obvious to me now how inefficient my previous workflow was
and I feel like I should have realised this sooner during my previous projects. I
think I can attribute this to my "newness" of game engine pipelines and
using Substance Painter in general. Back then I think I was just pleased to get results at all. It’s interesting how encountering an error with the software caused me to rethink my
entire approach, and I’m thankful this happened early on as I could have
ended up wasting valuable time working harder, not smarter.